* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
+#include <linux/slab.h>
#include <linux/types.h>
#include <linux/etherdevice.h>
#include <net/mac80211.h>
EXPORT_SYMBOL(iwl_get_active_dwell_time);
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
- enum ieee80211_band band)
+ enum ieee80211_band band,
+ struct ieee80211_vif *vif)
{
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
/* If we're associated, we clamp the maximum passive
* dwell time to be 98% of the beacon interval (minus
* 2 * channel tune time) */
- passive = priv->beacon_int;
+ passive = vif ? vif->bss_conf.beacon_int : 0;
if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
passive = IWL_PASSIVE_DWELL_BASE;
passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
}
EXPORT_SYMBOL(iwl_init_scan_params);
-static int iwl_scan_initiate(struct iwl_priv *priv)
+static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
WARN_ON(!mutex_is_locked(&priv->mutex));
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
return -EOPNOTSUPP;
- priv->cfg->ops->utils->request_scan(priv);
+ priv->cfg->ops->utils->request_scan(priv, vif);
return 0;
}
goto out_unlock;
}
- if (test_bit(STATUS_SCANNING, &priv->status)) {
+ if (test_bit(STATUS_SCANNING, &priv->status) &&
+ !priv->is_internal_short_scan) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
ret = -EAGAIN;
goto out_unlock;
/* mac80211 will only ask for one band at a time */
priv->scan_band = req->channels[0]->band;
priv->scan_request = req;
+ priv->scan_vif = vif;
- ret = iwl_scan_initiate(priv);
+ /*
+ * If an internal scan is in progress, just set
+ * up the scan_request as per above.
+ */
+ if (priv->is_internal_short_scan)
+ ret = 0;
+ else
+ ret = iwl_scan_initiate(priv, vif);
IWL_DEBUG_MAC80211(priv, "leave\n");
queue_work(priv->workqueue, &priv->start_internal_scan);
}
-static void iwl_bg_start_internal_scan(struct work_struct *work)
+void iwl_bg_start_internal_scan(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, start_internal_scan);
mutex_lock(&priv->mutex);
+ if (priv->is_internal_short_scan == true) {
+ IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
+ goto unlock;
+ }
+
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
goto unlock;
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
goto unlock;
- priv->cfg->ops->utils->request_scan(priv);
+ priv->cfg->ops->utils->request_scan(priv, NULL);
unlock:
mutex_unlock(&priv->mutex);
}
+EXPORT_SYMBOL(iwl_bg_start_internal_scan);
void iwl_bg_scan_check(struct work_struct *data)
{
*/
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
- const u8 *ies, int ie_len, int left)
+ const u8 *ta, const u8 *ies, int ie_len, int left)
{
int len = 0;
u8 *pos = NULL;
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
- memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
+ memcpy(frame->sa, ta, ETH_ALEN);
memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
frame->seq_ctrl = 0;
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, scan_completed);
+ bool internal = false;
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
cancel_delayed_work(&priv->scan_check);
- if (!priv->is_internal_short_scan)
- ieee80211_scan_completed(priv->hw, false);
- else {
+ mutex_lock(&priv->mutex);
+ if (priv->is_internal_short_scan) {
priv->is_internal_short_scan = false;
IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
+ internal = true;
+ } else {
+ priv->scan_request = NULL;
+ priv->scan_vif = NULL;
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
+ goto out;
+
+ if (internal && priv->scan_request)
+ iwl_scan_initiate(priv, priv->scan_vif);
/* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */
- mutex_lock(&priv->mutex);
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+ out:
mutex_unlock(&priv->mutex);
+
+ /*
+ * Do not hold mutex here since this will cause mac80211 to call
+ * into driver again into functions that will attempt to take
+ * mutex.
+ */
+ if (!internal)
+ ieee80211_scan_completed(priv->hw, false);
}
EXPORT_SYMBOL(iwl_bg_scan_completed);