int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req) { /* * cfg80211 should guarantee that we don't get more channels * than what we have registered. */ BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); if (wl->scan.state != WL1271_SCAN_STATE_IDLE) return -EBUSY; wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE; if (ssid_len && ssid) { wl->scan.ssid_len = ssid_len; memcpy(wl->scan.ssid, ssid, ssid_len); } else { wl->scan.ssid_len = 0; } wl->scan_vif = vif; wl->scan.req = req; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); /* we assume failure so that timeout scenarios are handled correctly */ wl->scan.failed = true; ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); wl1271_scan_send(wl, vif, req); return 0; }
void wl1271_scan_stm(struct wl1271 *wl) { int ret = 0; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: break; case WL1271_SCAN_STATE_2GHZ_ACTIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; else wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_DONE: wl->scan.failed = false; cancel_delayed_work(&wl->scan_complete_work); ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(0)); break; default: wl1271_error("invalid scan state"); break; } if (ret < 0) { cancel_delayed_work(&wl->scan_complete_work); ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(0)); } }
void wl1271_scan_stm(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret = 0; enum ieee80211_band band; u32 rate, mask; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: break; case WL1271_SCAN_STATE_2GHZ_ACTIVE: band = IEEE80211_BAND_2GHZ; mask = wlvif->bitrate_masks[band]; if (wl->scan.req->no_cck) { mask &= ~CONF_TX_CCK_RATES; if (!mask) mask = CONF_TX_RATE_MASK_BASIC_P2P; } rate = wl1271_tx_min_rate_get(wl, mask); ret = wl1271_scan_send(wl, wlvif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl1271_scan_stm(wl, wlvif); } break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: band = IEEE80211_BAND_2GHZ; mask = wlvif->bitrate_masks[band]; if (wl->scan.req->no_cck) { mask &= ~CONF_TX_CCK_RATES; if (!mask) mask = CONF_TX_RATE_MASK_BASIC_P2P; } rate = wl1271_tx_min_rate_get(wl, mask); ret = wl1271_scan_send(wl, wlvif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; else wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl, wlvif); } break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: band = IEEE80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, wlvif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl1271_scan_stm(wl, wlvif); } break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: band = IEEE80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, wlvif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl, wlvif); } break; case WL1271_SCAN_STATE_DONE: wl->scan.failed = false; cancel_delayed_work(&wl->scan_complete_work); ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(0)); break; default: wl1271_error("invalid scan state"); break; } if (ret < 0) { cancel_delayed_work(&wl->scan_complete_work); ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(0)); } }
void wl1271_scan_stm(struct wl1271 *wl) { int ret; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: break; case WL1271_SCAN_STATE_2GHZ_ACTIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, wl->conf.tx.basic_rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl1271_11a_enabled()) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; else wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, wl->conf.tx.basic_rate_5); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_DONE: mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); mutex_lock(&wl->mutex); kfree(wl->scan.scanned_ch); wl->scan.scanned_ch = NULL; wl->scan.state = WL1271_SCAN_STATE_IDLE; break; default: wl1271_error("invalid scan state"); break; } }