/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses
* from more than one AP. */ #define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ #define IWL_ACTIVE_DWELL_TIME_52 (20)
/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. * Must be set longer than active dwell time.
* For the most reliable scan, set > AP beacon interval (typically 100msec). */ #define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ #define IWL_PASSIVE_DWELL_TIME_52 (10) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 #define MAX_SCAN_CHANNEL 50
/* For reset radio, need minimal dwell time only */ #define IWL_RADIO_RESET_DWELL_TIME 5
/* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform
* hardware scan currently */ if (!test_bit(STATUS_READY, &priv->status) ||
!test_bit(STATUS_SCAN_HW, &priv->status) ||
test_bit(STATUS_FW_ERROR, &priv->status)) return -EIO;
ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) return ret;
status = (void *)cmd.resp_pkt->data; if (*status != CAN_ABORT_STATUS) { /* The scan abort will return 1 for success or * 2 for "failure". A failure condition can be * due to simply not being in an active scan which * can occur if we send the scan abort before we * the microcode has notified us that a scan is
* completed. */
IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n",
le32_to_cpu(*status));
ret = -EIO;
}
/* check if scan was requested from mac80211 */ if (priv->scan_request) {
IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
ieee80211_scan_completed(priv->hw, &info);
}
/* * iwl_scan_cancel - Cancel any currently executing HW scan
*/ int iwl_scan_cancel(struct iwl_priv *priv)
{
IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
queue_work(priv->workqueue, &priv->abort_scan); return 0;
}
/* * iwl_scan_cancel_timeout - Cancel any currently executing HW scan * @ms: amount of time to wait (in milliseconds) for scan to abort
*/ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsignedlong ms)
{ unsignedlong timeout = jiffies + msecs_to_jiffies(ms);
lockdep_assert_held(&priv->mutex);
IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
iwl_do_scan_abort(priv);
while (time_before_eq(jiffies, timeout)) { if (!test_bit(STATUS_SCAN_HW, &priv->status)) goto finished;
msleep(20);
}
return;
finished: /* * Now STATUS_SCAN_HW is clear. This means that the * device finished, but the background work is going * to execute at best as soon as we release the mutex. * Since we need to be able to issue a new scan right * after this function returns, run the complete here. * The STATUS_SCAN_COMPLETE bit will then be cleared * and prevent the background work from "completing" * a possible new scan.
*/
iwl_process_scan_complete(priv);
}
IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
(priv->scan_band == NL80211_BAND_2GHZ) ? "2.4" : "5.2",
jiffies_to_msecs(jiffies - priv->scan_start));
/* * When aborting, we run the scan completed background work inline * and the background work must then do nothing. The SCAN_COMPLETE * bit helps implement that logic and thus needs to be set before * queueing the work. Also, since the scan abort waits for SCAN_HW * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW * to avoid a race there.
*/
set_bit(STATUS_SCAN_COMPLETE, &priv->status);
clear_bit(STATUS_SCAN_HW, &priv->status);
queue_work(priv->workqueue, &priv->scan_completed);
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
iwl_advanced_bt_coexist(priv) &&
priv->bt_status != scan_notif->bt_status) { if (scan_notif->bt_status) { /* BT on */ if (!priv->bt_ch_announce)
priv->bt_traffic_load =
IWL_BT_COEX_TRAFFIC_LOAD_HIGH; /* * otherwise, no traffic load information provided * no changes made
*/
} else { /* BT off */
priv->bt_traffic_load =
IWL_BT_COEX_TRAFFIC_LOAD_NONE;
}
priv->bt_status = scan_notif->bt_status;
queue_work(priv->workqueue,
&priv->bt_traffic_change_work);
}
}
/* * If we're associated, we clamp the dwell time 98% * of the beacon interval (minus 2 * channel tune time) * If both contexts are active, we have to restrict to * 1/2 of the minimum of them, because they might be in * lock-step with the time inbetween only half of what * time we'd have in each of them.
*/
for_each_context(priv, ctx) { switch (ctx->staging.dev_type) { case RXON_DEV_TYPE_P2P: /* no timing constraints */ continue; case RXON_DEV_TYPE_ESS: default: /* timing constraints if associated */ if (!iwl_is_associated_ctx(ctx)) continue; break; case RXON_DEV_TYPE_CP: case RXON_DEV_TYPE_2STA: /* * These seem to always have timers for TBTT * active in uCode even when not associated yet.
*/ break;
}
IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); return added;
}
/* * iwl_fill_probe_req - fill in all required fields and IE for probe request
*/ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, const u8 *ies, int ie_len, const u8 *ssid,
u8 ssid_len, int left)
{ int len = 0;
u8 *pos = NULL;
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
left -= 24; if (left < 0) return 0;
switch (priv->scan_type) { case IWL_SCAN_RADIO_RESET:
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); /* * Override quiet time as firmware checks that active * dwell is >= quiet; since we use passive scan it'll * not actually be used.
*/
scan->quiet_time = cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME); break; case IWL_SCAN_NORMAL: if (priv->scan_request->n_ssids) { int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); /* * The highest priority SSID is inserted to the * probe request template.
*/
ssid_len = priv->scan_request->ssids[0].ssid_len;
ssid = priv->scan_request->ssids[0].ssid;
/* * Invert the order of ssids, the firmware will invert * it back.
*/ for (i = priv->scan_request->n_ssids - 1; i >= 1; i--) {
scan->direct_scan[p].id = WLAN_EID_SSID;
scan->direct_scan[p].len =
priv->scan_request->ssids[i].ssid_len;
memcpy(scan->direct_scan[p].ssid,
priv->scan_request->ssids[i].ssid,
priv->scan_request->ssids[i].ssid_len);
n_probes++;
p++;
}
is_active = true;
} else
IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); break;
}
switch (priv->scan_band) { case NL80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
chan_mod = le32_to_cpu(
priv->contexts[IWL_RXON_CTX_BSS].active.flags &
RXON_FLG_CHANNEL_MODE_MSK)
>> RXON_FLG_CHANNEL_MODE_POS; if ((priv->scan_request && priv->scan_request->no_cck) ||
chan_mod == CHANNEL_MODE_PURE_40) {
rate = IWL_RATE_6M_PLCP;
} else {
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
} /* * Internal scans are passive, so we can indiscriminately set * the BT ignore flag on 2.4 GHz since it applies to TX only.
*/ if (priv->lib->bt_params &&
priv->lib->bt_params->advanced_bt_coexist)
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; break; case NL80211_BAND_5GHZ:
rate = IWL_RATE_6M_PLCP; break; default:
IWL_WARN(priv, "Invalid scan band\n"); return -EIO;
}
/* * If active scanning is requested but a certain channel is * marked passive, we can do active scanning if we detect * transmissions. * * There is an issue with some firmware versions that triggers * a sysassert on a "good CRC threshold" of zero (== disabled), * on a radar channel even though this means that we should NOT * send probes. * * The "good CRC threshold" is the number of frames that we * need to receive during our dwell time on a channel before * sending out probes -- setting this to a huge value will * mean we never reach it, but at the same time work around * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER * here instead of IWL_GOOD_CRC_TH_DISABLED. * * This was fixed in later versions along with some other * scan changes, and the threshold behaves as a flag in those * versions.
*/ if (priv->new_scan_threshold_behaviour)
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
IWL_GOOD_CRC_TH_DISABLED; else
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
IWL_GOOD_CRC_TH_NEVER;
band = priv->scan_band;
if (band == NL80211_BAND_2GHZ &&
priv->lib->bt_params &&
priv->lib->bt_params->advanced_bt_coexist) { /* transmit 2.4 GHz probes only on first antenna */
scan_tx_antennas = first_antenna(scan_tx_antennas);
}
/* * In power save mode while associated use one chain, * otherwise use all chains
*/ if (test_bit(STATUS_POWER_PMI, &priv->status) &&
!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) { /* rx_ant has been set to all valid chains previously */
active_chains = rx_ant &
((u8)(priv->chain_noise_data.active_chains)); if (!active_chains)
active_chains = rx_ant;
/* * internal short scan, this function should only been called while associated. * It will reset and tune the radio to prevent possible RF related problem
*/ void iwl_internal_short_hw_scan(struct iwl_priv *priv)
{
queue_work(priv->workqueue, &priv->start_internal_scan);
}
if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); goto unlock;
}
if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); goto unlock;
}
if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
unlock:
mutex_unlock(&priv->mutex);
}
/* Since we are here firmware does not finish scan and * most likely is in bad shape, so we don't bother to
* send abort command, just force scan complete to mac80211 */
mutex_lock(&priv->mutex);
iwl_force_scan_end(priv);
mutex_unlock(&priv->mutex);
}
/* We keep scan_check work queued in case when firmware will not
* report back scan completed notification */
mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 200);
mutex_unlock(&priv->mutex);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.