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                if (priv->scan.output_power != priv->output_power)
 171                        wsm_set_output_power(priv, priv->output_power * 10);
 172                if (priv->join_status == CW1200_JOIN_STATUS_STA &&
 173                    !(priv->powersave_mode.mode & WSM_PSM_PS))
 174                        cw1200_set_pm(priv, &priv->powersave_mode);
 175
 176                if (priv->scan.status < 0)
 177                        wiphy_warn(priv->hw->wiphy,
 178                                   "[SCAN] Scan failed (%d).\n",
 179                                   priv->scan.status);
 180                else if (priv->scan.req)
 181                        wiphy_dbg(priv->hw->wiphy,
 182                                  "[SCAN] Scan completed.\n");
 183                else
 184                        wiphy_dbg(priv->hw->wiphy,
 185                                  "[SCAN] Scan canceled.\n");
 186
 187                priv->scan.req = NULL;
 188                cw1200_scan_restart_delayed(priv);
 189                wsm_unlock_tx(priv);
 190                mutex_unlock(&priv->conf_mutex);
 191                ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0);
 192                up(&priv->scan.lock);
 193                return;
 194        } else {
 195                struct ieee80211_channel *first = *priv->scan.curr;
 196                for (it = priv->scan.curr + 1, i = 1;
 197                     it != priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS;
 198                     ++it, ++i) {
 199                        if ((*it)->band != first->band)
 200                                break;
 201                        if (((*it)->flags ^ first->flags) &
 202                                        IEEE80211_CHAN_NO_IR)
 203                                break;
 204                        if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
 205                            (*it)->max_power != first->max_power)
 206                                break;
 207                }
 208                scan.band = first->band;
 209
 210                if (priv->scan.req->no_cck)
 211                        scan.max_tx_rate = WSM_TRANSMIT_RATE_6;
 212                else
 213                        scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
 214                scan.num_probes =
 215                        (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
 216                scan.num_ssids = priv->scan.n_ssids;
 217                scan.ssids = &priv->scan.ssids[0];
 218                scan.num_channels = it - priv->scan.curr;
 219                /* TODO: Is it optimal? */
 220                scan.probe_delay = 100;
 221                /* It is not stated in WSM specification, however
 222                 * FW team says that driver may not use FG scan
 223                 * when joined.
 224                 */
 225                if (priv->join_status == CW1200_JOIN_STATUS_STA) {
 226                        scan.type = WSM_SCAN_TYPE_BACKGROUND;
 227                        scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
 228                }
 229                scan.ch = kzalloc(
 230                        sizeof(struct wsm_scan_ch) * (it - priv->scan.curr),
 231                        GFP_KERNEL);
 232                if (!scan.ch) {
 233                        priv->scan.status = -ENOMEM;
 234                        goto fail;
 235                }
 236                for (i = 0; i < scan.num_channels; ++i) {
 237                        scan.ch[i].number = priv->scan.curr[i]->hw_value;
 238                        if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
 239                                scan.ch[i].min_chan_time = 50;
 240                                scan.ch[i].max_chan_time = 100;
 241                        } else {
 242                                scan.ch[i].min_chan_time = 10;
 243                                scan.ch[i].max_chan_time = 25;
 244                        }
 245                }
 246                if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
 247                    priv->scan.output_power != first->max_power) {
 248                        priv->scan.output_power = first->max_power;
 249                        wsm_set_output_power(priv,
 250                                             priv->scan.output_power * 10);
 251                }
 252                priv->scan.status = cw1200_scan_start(priv, &scan);
 253                kfree(scan.ch);
 254                if (priv->scan.status)
 255                        goto fail;
 256                priv->scan.curr = it;
 257        }
 258        mutex_unlock(&priv->conf_mutex);
 259        return;
 260
 261fail:
 262        priv->scan.curr = priv->scan.end;
 263        mutex_unlock(&priv->conf_mutex);
 264        queue_work(priv->workqueue, &priv->scan.work);
 265        return;
 266}
 267
 268static void cw1200_scan_restart_delayed(struct cw1200_common *priv)
 269{
 270        /* FW bug: driver has to restart p2p-dev mode after scan. */
 271        if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) {
 272                cw1200_enable_listening(priv);
 273                cw1200_update_filtering(priv);
 274        }
 275
 276        if (priv->delayed_unjoin) {
 277                priv->delayed_unjoin = false;
 278                if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0)
 279                        wsm_unlock_tx(priv);
 280        } else if (priv->delayed_link_loss) {
 281                        wiphy_dbg(priv->hw->wiphy, "[CQM] Requeue BSS loss.\n");
 282                        priv->delayed_link_loss = 0;
 283                        cw1200_cqm_bssloss_sm(priv, 1, 0, 0);
 284        }
 285}
 286
 287static void cw1200_scan_complete(struct cw1200_common *priv)
 288{
 289        queue_delayed_work(priv->workqueue, &priv->clear_recent_scan_work, HZ);
 290        if (priv->scan.direct_probe) {
 291                wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe complete.\n");
 292                cw1200_scan_restart_delayed(priv);
 293                priv->scan.direct_probe = 0;
 294                up(&priv->scan.lock);
 295                wsm_unlock_tx(priv);
 296        } else {
 297                cw1200_scan_work(&priv->scan.work);
 298        }
 299}
 300
 301void cw1200_scan_failed_cb(struct cw1200_common *priv)
 302{
 303        if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
 304                /* STA is stopped. */
 305                return;
 306
 307        if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
 308                priv->scan.status = -EIO;
 309                queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
 310        }
 311}
 312
 313
 314void cw1200_scan_complete_cb(struct cw1200_common *priv,
 315                                struct wsm_scan_complete *arg)
 316{
 317        if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
 318                /* STA is stopped. */
 319                return;
 320
 321        if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
 322                priv->scan.status = 1;
 323                queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
 324        }
 325}
 326
 327void cw1200_clear_recent_scan_work(struct work_struct *work)
 328{
 329        struct cw1200_common *priv =
 330                container_of(work, struct cw1200_common,
 331                             clear_recent_scan_work.work);
 332        atomic_xchg(&priv->recent_scan, 0);
 333}
 334
 335void cw1200_scan_timeout(struct work_struct *work)
 336{
 337        struct cw1200_common *priv =
 338                container_of(work, struct cw1200_common, scan.timeout.work);
 339        if (atomic_xchg(&priv->scan.in_progress, 0)) {
 340                if (priv->scan.status > 0) {
 341                        priv->scan.status = 0;
 342                } else if (!priv->scan.status) {
 343                        wiphy_warn(priv->hw->wiphy,
 344                                   "Timeout waiting for scan complete notification.\n");
 345                        priv->scan.status = -ETIMEDOUT;
 346                        priv->scan.curr = priv->scan.end;
 347                        wsm_stop_scan(priv);
 348                }
 349                cw1200_scan_complete(priv);
 350        }
 351}
 352
 353void cw1200_probe_work(struct work_struct *work)
 354{
 355        struct cw1200_common *priv =
 356                container_of(work, struct cw1200_common, scan.probe_work.work);
 357        u8 queue_id = cw1200_queue_get_queue_id(priv->pending_frame_id);
 358        struct cw1200_queue *queue = &priv->tx_queue[queue_id];
 359        const struct cw1200_txpriv *txpriv;
 360        struct wsm_tx *wsm;
 361        struct wsm_template_frame frame = {
 362                .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
 363        };
 364        struct wsm_ssid ssids[1] = {{
 365                .length = 0,
 366        } };
 367        struct wsm_scan_ch ch[1] = {{
 368                .min_chan_time = 0,
 369                .max_chan_time = 10,
 370        } };
 371        struct wsm_scan scan = {
 372                .type = WSM_SCAN_TYPE_FOREGROUND,
 373                .num_probes = 1,
 374                .probe_delay = 0,
 375                .num_channels = 1,
 376                .ssids = ssids,
 377                .ch = ch,
 378        };
 379        u8 *ies;
 380        size_t ies_len;
 381        int ret;
 382
 383        wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe work.\n");
 384
 385        mutex_lock(&priv->conf_mutex);
 386        if (down_trylock(&priv->scan.lock)) {
 387                /* Scan is already in progress. Requeue self. */
 388                schedule();
 389                queue_delayed_work(priv->workqueue, &priv->scan.probe_work,
 390                                   msecs_to_jiffies(100));
 391                mutex_unlock(&priv->conf_mutex);
 392                return;
 393        }
 394
 395        /* Make sure we still have a pending probe req */
 396        if (cw1200_queue_get_skb(queue, priv->pending_frame_id,
 397                                 &frame.skb, &txpriv)) {
 398                up(&priv->scan.lock);
 399                mutex_unlock(&priv->conf_mutex);
 400                wsm_unlock_tx(priv);
 401                return;
 402        }
 403        wsm = (struct wsm_tx *)frame.skb->data;
 404        scan.max_tx_rate = wsm->max_tx_rate;
 405        scan.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ?
 406                WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G;
 407        if (priv->join_status == CW1200_JOIN_STATUS_STA ||
 408            priv->join_status == CW1200_JOIN_STATUS_IBSS) {
 409                scan.type = WSM_SCAN_TYPE_BACKGROUND;
 410                scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
 411        }
 412        ch[0].number = priv->channel->hw_value;
 413
 414        skb_pull(frame.skb, txpriv->offset);
 415
 416        ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)];
 417        ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr);
 418
 419        if (ies_len) {
 420                u8 *ssidie =
 421                        (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
 422                if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) {
 423                        u8 *nextie = &ssidie[2 + ssidie[1]];
 424                        /* Remove SSID from the IE list. It has to be provided
 425                         * as a separate argument in cw1200_scan_start call
 426                         */
 427
 428                        /* Store SSID localy */
 429                        ssids[0].length = ssidie[1];
 430                        memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length);
 431                        scan.num_ssids = 1;
 432
 433                        /* Remove SSID from IE list */
 434                        ssidie[1] = 0;
 435                        memmove(&ssidie[2], nextie, &ies[ies_len] - nextie);
 436                        skb_trim(frame.skb, frame.skb->len - ssids[0].length);
 437                }
 438        }
 439
 440        /* FW bug: driver has to restart p2p-dev mode after scan */
 441        if (priv->join_status == CW1200_JOIN_STATUS_MONITOR)
 442                cw1200_disable_listening(priv);
 443        ret = wsm_set_template_frame(priv, &frame);
 444        priv->scan.direct_probe = 1;
 445        if (!ret) {
 446                wsm_flush_tx(priv);
 447                ret = cw1200_scan_start(priv, &scan);
 448        }
 449        mutex_unlock(&priv->conf_mutex);
 450
 451        skb_push(frame.skb, txpriv->offset);
 452        if (!ret)
 453                IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK;
 454        BUG_ON(cw1200_queue_remove(queue, priv->pending_frame_id));
 455
 456        if (ret) {
 457                priv->scan.direct_probe = 0;
 458                up(&priv->scan.lock);
 459                wsm_unlock_tx(priv);
 460        }
 461
 462        return;
 463}
 464