aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c99
3 files changed, 62 insertions, 49 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index fcfb410aca90..baaf48616cc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2770,15 +2770,6 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
2770 2770
2771 mutex_lock(&priv->shrd->mutex); 2771 mutex_lock(&priv->shrd->mutex);
2772 2772
2773 /*
2774 * TODO: Remove this hack! Firmware needs to be updated
2775 * to allow longer off-channel periods in scanning for
2776 * this use case, based on a flag (and we'll need an API
2777 * flag in the firmware when it has that).
2778 */
2779 if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80)
2780 duration = 80;
2781
2782 if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { 2773 if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
2783 err = -EBUSY; 2774 err = -EBUSY;
2784 goto out; 2775 goto out;
@@ -2787,6 +2778,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
2787 priv->hw_roc_channel = channel; 2778 priv->hw_roc_channel = channel;
2788 priv->hw_roc_chantype = channel_type; 2779 priv->hw_roc_chantype = channel_type;
2789 priv->hw_roc_duration = duration; 2780 priv->hw_roc_duration = duration;
2781 priv->hw_roc_start_notified = false;
2790 cancel_delayed_work(&priv->hw_roc_disable_work); 2782 cancel_delayed_work(&priv->hw_roc_disable_work);
2791 2783
2792 if (!ctx->is_active) { 2784 if (!ctx->is_active) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index fabfc8bf4971..7f534c45d1fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1029,7 +1029,7 @@ struct iwl_priv {
1029 struct delayed_work hw_roc_disable_work; 1029 struct delayed_work hw_roc_disable_work;
1030 enum nl80211_channel_type hw_roc_chantype; 1030 enum nl80211_channel_type hw_roc_chantype;
1031 int hw_roc_duration; 1031 int hw_roc_duration;
1032 bool hw_roc_setup; 1032 bool hw_roc_setup, hw_roc_start_notified;
1033 1033
1034 /* bt coex */ 1034 /* bt coex */
1035 u8 bt_enable_flag; 1035 u8 bt_enable_flag;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 8ac6b05c6c78..8386a86e2ca2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -218,8 +218,11 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
218 le32_to_cpu(notif->tsf_low), 218 le32_to_cpu(notif->tsf_low),
219 notif->status, notif->beacon_timer); 219 notif->status, notif->beacon_timer);
220 220
221 if (priv->scan_type == IWL_SCAN_ROC) 221 if (priv->scan_type == IWL_SCAN_ROC &&
222 !priv->hw_roc_start_notified) {
222 ieee80211_ready_on_channel(priv->hw); 223 ieee80211_ready_on_channel(priv->hw);
224 priv->hw_roc_start_notified = true;
225 }
223} 226}
224 227
225/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ 228/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
@@ -310,34 +313,38 @@ static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
310 IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); 313 IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
311} 314}
312 315
316static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
317{
318 struct iwl_rxon_context *ctx;
319
320 /*
321 * If we're associated, we clamp the dwell time 98%
322 * of the smallest beacon interval (minus 2 * channel
323 * tune time)
324 */
325 for_each_context(priv, ctx) {
326 u16 value;
327
328 if (!iwl_is_associated_ctx(ctx))
329 continue;
330 value = ctx->beacon_int;
331 if (!value)
332 value = IWL_PASSIVE_DWELL_BASE;
333 value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
334 dwell_time = min(value, dwell_time);
335 }
336
337 return dwell_time;
338}
339
313static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, 340static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
314 enum ieee80211_band band) 341 enum ieee80211_band band)
315{ 342{
316 struct iwl_rxon_context *ctx;
317 u16 passive = (band == IEEE80211_BAND_2GHZ) ? 343 u16 passive = (band == IEEE80211_BAND_2GHZ) ?
318 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : 344 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
319 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; 345 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
320 346
321 if (iwl_is_any_associated(priv)) { 347 return iwl_limit_dwell(priv, passive);
322 /*
323 * If we're associated, we clamp the maximum passive
324 * dwell time to be 98% of the smallest beacon interval
325 * (minus 2 * channel tune time)
326 */
327 for_each_context(priv, ctx) {
328 u16 value;
329
330 if (!iwl_is_associated_ctx(ctx))
331 continue;
332 value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
333 if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
334 value = IWL_PASSIVE_DWELL_BASE;
335 value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
336 passive = min(value, passive);
337 }
338 }
339
340 return passive;
341} 348}
342 349
343static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, 350static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
@@ -716,29 +723,43 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
716 break; 723 break;
717 case IWL_SCAN_ROC: { 724 case IWL_SCAN_ROC: {
718 struct iwl_scan_channel *scan_ch; 725 struct iwl_scan_channel *scan_ch;
726 int n_chan, i;
727 u16 dwell;
728
729 dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
730 n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
719 731
720 scan->channel_count = 1; 732 scan->channel_count = n_chan;
721 733
722 scan_ch = (void *)&scan->data[cmd_len]; 734 scan_ch = (void *)&scan->data[cmd_len];
723 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
724 scan_ch->channel =
725 cpu_to_le16(priv->hw_roc_channel->hw_value);
726 scan_ch->active_dwell =
727 scan_ch->passive_dwell =
728 cpu_to_le16(priv->hw_roc_duration);
729 735
730 /* Set txpower levels to defaults */ 736 for (i = 0; i < n_chan; i++) {
731 scan_ch->dsp_atten = 110; 737 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
738 scan_ch->channel =
739 cpu_to_le16(priv->hw_roc_channel->hw_value);
732 740
733 /* NOTE: if we were doing 6Mb OFDM for scans we'd use 741 if (i == n_chan - 1)
734 * power level: 742 dwell = priv->hw_roc_duration - i * dwell;
735 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; 743
736 */ 744 scan_ch->active_dwell =
737 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) 745 scan_ch->passive_dwell = cpu_to_le16(dwell);
738 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; 746
739 else 747 /* Set txpower levels to defaults */
740 scan_ch->tx_gain = ((1 << 5) | (5 << 3)); 748 scan_ch->dsp_atten = 110;
749
750 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
751 * power level:
752 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
753 */
754 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
755 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
756 else
757 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
758
759 scan_ch++;
741 } 760 }
761 }
762
742 break; 763 break;
743 } 764 }
744 765