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