linux/drivers/net/wireless/cw1200/scan.c
<<
>>
Prefs
   1/*
   2 * Scan implementation for ST-Ericsson CW1200 mac80211 drivers
   3 *
   4 * Copyright (c) 2010, ST-Ericsson
   5 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/sched.h>
  13#include "cw1200.h"
  14#include "scan.h"
  15#include "sta.h"
  16#include "pm.h"
  17
  18static void cw1200_scan_restart_delayed(struct cw1200_common *priv);
  19
  20static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan)
  21{
  22        int ret, i;
  23        int tmo = 2000;
  24
  25        switch (priv->join_status) {
  26        case CW1200_JOIN_STATUS_PRE_STA:
  27        case CW1200_JOIN_STATUS_JOINING:
  28                return -EBUSY;
  29        default:
  30                break;
  31        }
  32
  33        wiphy_dbg(priv->hw->wiphy, "[SCAN] hw req, type %d, %d channels, flags: 0x%x.\n",
  34                  scan->type, scan->num_channels, scan->flags);
  35
  36        for (i = 0; i < scan->num_channels; ++i)
  37                tmo += scan->ch[i].max_chan_time + 10;
  38
  39        cancel_delayed_work_sync(&priv->clear_recent_scan_work);
  40        atomic_set(&priv->scan.in_progress, 1);
  41        atomic_set(&priv->recent_scan, 1);
  42        cw1200_pm_stay_awake(&priv->pm_state, tmo * HZ / 1000);
  43        queue_delayed_work(priv->workqueue, &priv->scan.timeout,
  44                           tmo * HZ / 1000);
  45        ret = wsm_scan(priv, scan);
  46        if (ret) {
  47                atomic_set(&priv->scan.in_progress, 0);
  48                cancel_delayed_work_sync(&priv->scan.timeout);
  49                cw1200_scan_restart_delayed(priv);
  50        }
  51        return ret;
  52}
  53
  54int cw1200_hw_scan(struct ieee80211_hw *hw,
  55                   struct ieee80211_vif *vif,
  56                   struct cfg80211_scan_request *req)
  57{
  58        struct cw1200_common *priv = hw->priv;
  59        struct wsm_template_frame frame = {
  60                .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
  61        };
  62        int i, ret;
  63
  64        if (!priv->vif)
  65                return -EINVAL;
  66
  67        /* Scan when P2P_GO corrupt firmware MiniAP mode */
  68        if (priv->join_status == CW1200_JOIN_STATUS_AP)
  69                return -EOPNOTSUPP;
  70
  71        if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
  72                req->n_ssids = 0;
  73
  74        wiphy_dbg(hw->wiphy, "[SCAN] Scan request for %d SSIDs.\n",
  75                  req->n_ssids);
  76
  77        if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
  78                return -EINVAL;
  79
  80        frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
  81                req->ie_len);
  82        if (!frame.skb)
  83                return -ENOMEM;
  84
  85        if (req->ie_len)
  86                memcpy(skb_put(frame.skb, req->ie_len), req->ie, req->ie_len);
  87
  88        /* will be unlocked in cw1200_scan_work() */
  89        down(&priv->scan.lock);
  90        mutex_lock(&priv->conf_mutex);
  91
  92        ret = wsm_set_template_frame(priv, &frame);
  93        if (!ret) {
  94                /* Host want to be the probe responder. */
  95                ret = wsm_set_probe_responder(priv, true);
  96        }
  97        if (ret) {
  98                mutex_unlock(&priv->conf_mutex);
  99                up(&priv->scan.lock);
 100                dev_kfree_skb(frame.skb);
 101                return ret;
 102        }
 103
 104        wsm_lock_tx(priv);
 105
 106        BUG_ON(priv->scan.req);
 107        priv->scan.req = req;
 108        priv->scan.n_ssids = 0;
 109        priv->scan.status = 0;
 110        priv->scan.begin = &req->channels[0];
 111        priv->scan.curr = priv->scan.begin;
 112        priv->scan.end = &req->channels[req->n_channels];
 113        priv->scan.output_power = priv->output_power;
 114
 115        for (i = 0; i < req->n_ssids; ++i) {
 116                struct wsm_ssid *dst = &priv->scan.ssids[priv->scan.n_ssids];
 117                memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
 118                dst->length = req->ssids[i].ssid_len;
 119                ++priv->scan.n_ssids;
 120        }
 121
 122        mutex_unlock(&priv->conf_mutex);
 123
 124        if (frame.skb)
 125                dev_kfree_skb(frame.skb);
 126        queue_work(priv->workqueue, &priv->scan.work);
 127        return 0;
 128}
 129
 130void cw1200_scan_work(struct work_struct *work)
 131{
 132        struct cw1200_common *priv = container_of(work, struct cw1200_common,
 133                                                        scan.work);
 134        struct ieee80211_channel **it;
 135        struct wsm_scan scan = {
 136                .type = WSM_SCAN_TYPE_FOREGROUND,
 137                .flags = WSM_SCAN_FLAG_SPLIT_METHOD,
 138        };
 139        bool first_run = (priv->scan.begin == priv->scan.curr &&
 140                          priv->scan.begin != priv->scan.end);
 141        int i;
 142
 143        if (first_run) {
 144                /* Firmware gets crazy if scan request is sent
 145                 * when STA is joined but not yet associated.
 146                 * Force unjoin in this case.
 147                 */
 148                if (cancel_delayed_work_sync(&priv->join_timeout) > 0)
 149                        cw1200_join_timeout(&priv->join_timeout.work);
 150        }
 151
 152        mutex_lock(&priv->conf_mutex);
 153
 154        if (first_run) {
 155                if (priv->join_status == CW1200_JOIN_STATUS_STA &&
 156                    !(priv->powersave_mode.mode & WSM_PSM_PS)) {
 157                        struct wsm_set_pm pm = priv->powersave_mode;
 158                        pm.mode = WSM_PSM_PS;
 159                        cw1200_set_pm(priv, &pm);
 160                } else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) {
 161                        /* FW bug: driver has to restart p2p-dev mode
 162                         * after scan
 163                         */
 164                        cw1200_disable_listening(priv);
 165                }
 166        }
 167
 168        if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
 169                if (priv->scan.output_power != priv->output_power)
 170                        wsm_set_output_power(priv, priv->output_power * 10);
 171                if (priv->join_status == CW1200_JOIN_STATUS_STA &&
 172                    !(priv->powersave_mode.mode & WSM_PSM_PS))
 173                        cw1200_set_pm(priv, &priv->powersave_mode);
 174
 175                if (priv->scan.status < 0)
 176                        wiphy_warn(priv->hw->wiphy,
 177                                   "[SCAN] Scan failed (%d).\n",
 178                                   priv->scan.status);
 179                else if (priv->scan.req)
 180                        wiphy_dbg(priv->hw->wiphy,
 181                                  "[SCAN] Scan completed.\n");
 182                else
 183                        wiphy_dbg(priv->hw->wiphy,
 184                                  "[SCAN] Scan canceled.\n");
 185
 186                priv->scan.req = NULL;
 187                cw1200_scan_restart_delayed(priv);
 188                wsm_unlock_tx(priv);
 189                mutex_unlock(&priv->conf_mutex);
 190                ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0);
 191                up(&priv->scan.lock);
 192                return;
 193        } else {
 194                struct ieee80211_channel *first = *priv->scan.curr;
 195                for (it = priv->scan.curr + 1, i = 1;
 196                     it != priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS;
 197                     ++it, ++i) {
 198                        if ((*it)->band != first->band)
 199                                break;
 200                        if (((*it)->flags ^ first->flags) &
 201                                        IEEE80211_CHAN_NO_IR)
 202                                break;
 203                        if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
 204                            (*it)->max_power != first->max_power)
 205                                break;
 206                }
 207                scan.band = first->band;
 208
 209                if (priv->scan.req->no_cck)
 210                        scan.max_tx_rate = WSM_TRANSMIT_RATE_6;
 211                else
 212                        scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
 213                scan.num_probes =
 214                        (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
 215                scan.num_ssids = priv->scan.n_ssids;
 216                scan.ssids = &priv->scan.ssids[0];
 217                scan.num_channels = it - priv->scan.curr;
 218                /* TODO: Is it optimal? */
 219                scan.probe_delay = 100;
 220                /* It is not stated in WSM specification, however
 221                 * FW team says that driver may not use FG scan
 222                 * when joined.
 223                 */
 224                if (priv->join_status == CW1200_JOIN_STATUS_STA) {
 225                        scan.type = WSM_SCAN_TYPE_BACKGROUND;
 226                        scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
 227                }
 228                scan.ch = kzalloc(
 229                        sizeof(struct wsm_scan_ch) * (it - priv->scan.curr),
 230                        GFP_KERNEL);
 231                if (!scan.ch) {
 232                        priv->scan.status = -ENOMEM;
 233                        goto fail;
 234                }
 235                for (i = 0; i < scan.num_channels; ++i) {
 236                        scan.ch[i].number = priv->scan.curr[i]->hw_value;
 237                        if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
 238                                scan.ch[i].min_chan_time = 50;
 239                                scan.ch[i].max_chan_time = 100;
 240                        } else {
 241                                scan.ch[i].min_chan_time = 10;
 242                                scan.ch[i].max_chan_time = 25;
 243                        }
 244                }
 245                if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
 246                    priv->scan.output_power != first->max_power) {
 247                        priv->scan.output_power = first->max_power;
 248                        wsm_set_output_power(priv,
 249                                             priv->scan.output_power * 10);
 250                }
 251                priv->scan.status = cw1200_scan_start(priv, &scan);
 252                kfree(scan.ch);
 253                if (priv->scan.status)
 254                        goto fail;
 255                priv->scan.curr = it;
 256        }
 257        mutex_unlock(&priv->conf_mutex);
 258        return;
 259
 260fail:
 261        priv->scan.curr = priv->scan.end;
 262        mutex_unlock(&priv->conf_mutex);
 263        queue_work(priv->workqueue, &priv->scan.work);
 264        return;
 265}
 266
 267static void cw1200_scan_restart_delayed(struct cw1200_common *priv)
 268{
 269        /* FW bug: driver has to restart p2p-dev mode after scan. */
 270        if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) {
 271                cw1200_enable_listening(priv);
 272                cw1200_update_filtering(priv);
 273        }
 274
 275        if (priv->delayed_unjoin) {
 276                priv->delayed_unjoin = false;
 277                if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0)
 278                        wsm_unlock_tx(priv);
 279        } else if (priv->delayed_link_loss) {
 280                        wiphy_dbg(priv->hw->wiphy, "[CQM] Requeue BSS loss.\n");
 281                        priv->delayed_link_loss = 0;
 282                        cw1200_cqm_bssloss_sm(priv, 1, 0, 0);
 283        }
 284}
 285
 286static void cw1200_scan_complete(struct cw1200_common *priv)
 287{
 288        queue_delayed_work(priv->workqueue, &priv->clear_recent_scan_work, HZ);
 289        if (priv->scan.direct_probe) {
 290                wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe complete.\n");
 291                cw1200_scan_restart_delayed(priv);
 292                priv->scan.direct_probe = 0;
 293                up(&priv->scan.lock);
 294                wsm_unlock_tx(priv);
 295        } else {
 296                cw1200_scan_work(&priv->scan.work);
 297        }
 298}
 299
 300void cw1200_scan_failed_cb(struct cw1200_common *priv)
 301{
 302        if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
 303                /* STA is stopped. */
 304                return;
 305
 306        if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
 307                priv->scan.status = -EIO;
 308                queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
 309        }
 310}
 311
 312
 313void cw1200_scan_complete_cb(struct cw1200_common *priv,
 314                                struct wsm_scan_complete *arg)
 315{
 316        if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
 317                /* STA is stopped. */
 318                return;
 319
 320        if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
 321                priv->scan.status = 1;
 322                queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
 323        }
 324}
 325
 326void cw1200_clear_recent_scan_work(struct work_struct *work)
 327{
 328        struct cw1200_common *priv =
 329                container_of(work, struct cw1200_common,
 330                             clear_recent_scan_work.work);
 331        atomic_xchg(&priv->recent_scan, 0);
 332}
 333
 334void cw1200_scan_timeout(struct work_struct *work)
 335{
 336        struct cw1200_common *priv =
 337                container_of(work, struct cw1200_common, scan.timeout.work);
 338        if (atomic_xchg(&priv->scan.in_progress, 0)) {
 339                if (priv->scan.status > 0) {
 340                        priv->scan.status = 0;
 341                } else if (!priv->scan.status) {
 342                        wiphy_warn(priv->hw->wiphy,
 343                                   "Timeout waiting for scan complete notification.\n");
 344                        priv->scan.status = -ETIMEDOUT;
 345                        priv->scan.curr = priv->scan.end;
 346                        wsm_stop_scan(priv);
 347                }
 348                cw1200_scan_complete(priv);
 349        }
 350}
 351
 352void cw1200_probe_work(struct work_struct *work)
 353{
 354        struct cw1200_common *priv =
 355                container_of(work, struct cw1200_common, scan.probe_work.work);
 356        u8 queue_id = cw1200_queue_get_queue_id(priv->pending_frame_id);
 357        struct cw1200_queue *queue = &priv->tx_queue[queue_id];
 358        const struct cw1200_txpriv *txpriv;
 359        struct wsm_tx *wsm;
 360        struct wsm_template_frame frame = {
 361                .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
 362        };
 363        struct wsm_ssid ssids[1] = {{
 364                .length = 0,
 365        } };
 366        struct wsm_scan_ch ch[1] = {{
 367                .min_chan_time = 0,
 368                .max_chan_time = 10,
 369        } };
 370        struct wsm_scan scan = {
 371                .type = WSM_SCAN_TYPE_FOREGROUND,
 372                .num_probes = 1,
 373                .probe_delay = 0,
 374                .num_channels = 1,
 375                .ssids = ssids,
 376                .ch = ch,
 377        };
 378        u8 *ies;
 379        size_t ies_len;
 380        int ret;
 381
 382        wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe work.\n");
 383
 384        mutex_lock(&priv->conf_mutex);
 385        if (down_trylock(&priv->scan.lock)) {
 386                /* Scan is already in progress. Requeue self. */
 387                schedule();
 388                queue_delayed_work(priv->workqueue,
 389                                   &priv->scan.probe_work, HZ / 10);
 390                mutex_unlock(&priv->conf_mutex);
 391                return;
 392        }
 393
 394        /* Make sure we still have a pending probe req */
 395        if (cw1200_queue_get_skb(queue, priv->pending_frame_id,
 396                                 &frame.skb, &txpriv)) {
 397                up(&priv->scan.lock);
 398                mutex_unlock(&priv->conf_mutex);
 399                wsm_unlock_tx(priv);
 400                return;
 401        }
 402        wsm = (struct wsm_tx *)frame.skb->data;
 403        scan.max_tx_rate = wsm->max_tx_rate;
 404        scan.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ?
 405                WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G;
 406        if (priv->join_status == CW1200_JOIN_STATUS_STA ||
 407            priv->join_status == CW1200_JOIN_STATUS_IBSS) {
 408                scan.type = WSM_SCAN_TYPE_BACKGROUND;
 409                scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
 410        }
 411        ch[0].number = priv->channel->hw_value;
 412
 413        skb_pull(frame.skb, txpriv->offset);
 414
 415        ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)];
 416        ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr);
 417
 418        if (ies_len) {
 419                u8 *ssidie =
 420                        (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
 421                if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) {
 422                        u8 *nextie = &ssidie[2 + ssidie[1]];
 423                        /* Remove SSID from the IE list. It has to be provided
 424                         * as a separate argument in cw1200_scan_start call
 425                         */
 426
 427                        /* Store SSID localy */
 428                        ssids[0].length = ssidie[1];
 429                        memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length);
 430                        scan.num_ssids = 1;
 431
 432                        /* Remove SSID from IE list */
 433                        ssidie[1] = 0;
 434                        memmove(&ssidie[2], nextie, &ies[ies_len] - nextie);
 435                        skb_trim(frame.skb, frame.skb->len - ssids[0].length);
 436                }
 437        }
 438
 439        /* FW bug: driver has to restart p2p-dev mode after scan */
 440        if (priv->join_status == CW1200_JOIN_STATUS_MONITOR)
 441                cw1200_disable_listening(priv);
 442        ret = wsm_set_template_frame(priv, &frame);
 443        priv->scan.direct_probe = 1;
 444        if (!ret) {
 445                wsm_flush_tx(priv);
 446                ret = cw1200_scan_start(priv, &scan);
 447        }
 448        mutex_unlock(&priv->conf_mutex);
 449
 450        skb_push(frame.skb, txpriv->offset);
 451        if (!ret)
 452                IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK;
 453        BUG_ON(cw1200_queue_remove(queue, priv->pending_frame_id));
 454
 455        if (ret) {
 456                priv->scan.direct_probe = 0;
 457                up(&priv->scan.lock);
 458                wsm_unlock_tx(priv);
 459        }
 460
 461        return;
 462}
 463