diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 190 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 19 |
9 files changed, 127 insertions, 215 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index ad3bdba6beed..1d7572f9887f 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -111,20 +111,3 @@ config IWLWIFI_DEVICE_SVTOOL | |||
111 | NL80211_TESTMODE. svtool is a software validation tool that runs in | 111 | NL80211_TESTMODE. svtool is a software validation tool that runs in |
112 | the user space and interacts with the device in the kernel space | 112 | the user space and interacts with the device in the kernel space |
113 | through the generic netlink message via NL80211_TESTMODE channel. | 113 | through the generic netlink message via NL80211_TESTMODE channel. |
114 | |||
115 | config IWL_P2P | ||
116 | bool "iwlwifi experimental P2P support" | ||
117 | depends on IWLAGN | ||
118 | help | ||
119 | This option enables experimental P2P support for some devices | ||
120 | based on microcode support. Since P2P support is still under | ||
121 | development, this option may even enable it for some devices | ||
122 | now that turn out to not support it in the future due to | ||
123 | microcode restrictions. | ||
124 | |||
125 | To determine if your microcode supports the experimental P2P | ||
126 | offered by this option, check if the driver advertises AP | ||
127 | support when it is loaded. | ||
128 | |||
129 | Say Y only if you want to experiment with P2P. | ||
130 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3bee0f119bcd..4edb6cfc5488 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -753,18 +753,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
753 | return added; | 753 | return added; |
754 | } | 754 | } |
755 | 755 | ||
756 | static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen) | ||
757 | { | ||
758 | struct sk_buff *skb = priv->offchan_tx_skb; | ||
759 | |||
760 | if (skb->len < maxlen) | ||
761 | maxlen = skb->len; | ||
762 | |||
763 | memcpy(data, skb->data, maxlen); | ||
764 | |||
765 | return maxlen; | ||
766 | } | ||
767 | |||
768 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | 756 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) |
769 | { | 757 | { |
770 | struct iwl_host_cmd cmd = { | 758 | struct iwl_host_cmd cmd = { |
@@ -807,7 +795,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
807 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 795 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
808 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | 796 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; |
809 | 797 | ||
810 | if (priv->scan_type != IWL_SCAN_OFFCH_TX && | 798 | if (priv->scan_type != IWL_SCAN_ROC && |
811 | iwl_is_any_associated(priv)) { | 799 | iwl_is_any_associated(priv)) { |
812 | u16 interval = 0; | 800 | u16 interval = 0; |
813 | u32 extra; | 801 | u32 extra; |
@@ -816,7 +804,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
816 | 804 | ||
817 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 805 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
818 | switch (priv->scan_type) { | 806 | switch (priv->scan_type) { |
819 | case IWL_SCAN_OFFCH_TX: | 807 | case IWL_SCAN_ROC: |
820 | WARN_ON(1); | 808 | WARN_ON(1); |
821 | break; | 809 | break; |
822 | case IWL_SCAN_RADIO_RESET: | 810 | case IWL_SCAN_RADIO_RESET: |
@@ -838,10 +826,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
838 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | 826 | scan->suspend_time = cpu_to_le32(scan_suspend_time); |
839 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | 827 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", |
840 | scan_suspend_time, interval); | 828 | scan_suspend_time, interval); |
841 | } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) { | 829 | } else if (priv->scan_type == IWL_SCAN_ROC) { |
842 | scan->suspend_time = 0; | 830 | scan->suspend_time = 0; |
843 | scan->max_out_time = | 831 | scan->max_out_time = 0; |
844 | cpu_to_le32(1024 * priv->offchan_tx_timeout); | 832 | scan->quiet_time = 0; |
833 | scan->quiet_plcp_th = 0; | ||
845 | } | 834 | } |
846 | 835 | ||
847 | switch (priv->scan_type) { | 836 | switch (priv->scan_type) { |
@@ -869,8 +858,8 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
869 | } else | 858 | } else |
870 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | 859 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); |
871 | break; | 860 | break; |
872 | case IWL_SCAN_OFFCH_TX: | 861 | case IWL_SCAN_ROC: |
873 | IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n"); | 862 | IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); |
874 | break; | 863 | break; |
875 | } | 864 | } |
876 | 865 | ||
@@ -988,19 +977,13 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
988 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 977 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
989 | break; | 978 | break; |
990 | case IWL_SCAN_RADIO_RESET: | 979 | case IWL_SCAN_RADIO_RESET: |
980 | case IWL_SCAN_ROC: | ||
991 | /* use bcast addr, will not be transmitted but must be valid */ | 981 | /* use bcast addr, will not be transmitted but must be valid */ |
992 | cmd_len = iwl_fill_probe_req(priv, | 982 | cmd_len = iwl_fill_probe_req(priv, |
993 | (struct ieee80211_mgmt *)scan->data, | 983 | (struct ieee80211_mgmt *)scan->data, |
994 | iwl_bcast_addr, NULL, 0, | 984 | iwl_bcast_addr, NULL, 0, |
995 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 985 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
996 | break; | 986 | break; |
997 | case IWL_SCAN_OFFCH_TX: | ||
998 | cmd_len = iwl_fill_offch_tx(priv, scan->data, | ||
999 | IWL_MAX_SCAN_SIZE | ||
1000 | - sizeof(*scan) | ||
1001 | - sizeof(struct iwl_scan_channel)); | ||
1002 | scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX; | ||
1003 | break; | ||
1004 | default: | 987 | default: |
1005 | BUG(); | 988 | BUG(); |
1006 | } | 989 | } |
@@ -1021,18 +1004,18 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1021 | is_active, n_probes, | 1004 | is_active, n_probes, |
1022 | (void *)&scan->data[cmd_len]); | 1005 | (void *)&scan->data[cmd_len]); |
1023 | break; | 1006 | break; |
1024 | case IWL_SCAN_OFFCH_TX: { | 1007 | case IWL_SCAN_ROC: { |
1025 | struct iwl_scan_channel *scan_ch; | 1008 | struct iwl_scan_channel *scan_ch; |
1026 | 1009 | ||
1027 | scan->channel_count = 1; | 1010 | scan->channel_count = 1; |
1028 | 1011 | ||
1029 | scan_ch = (void *)&scan->data[cmd_len]; | 1012 | scan_ch = (void *)&scan->data[cmd_len]; |
1030 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 1013 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
1031 | scan_ch->channel = | 1014 | scan_ch->channel = |
1032 | cpu_to_le16(priv->offchan_tx_chan->hw_value); | 1015 | cpu_to_le16(priv->hw_roc_channel->hw_value); |
1033 | scan_ch->active_dwell = | 1016 | scan_ch->active_dwell = |
1034 | cpu_to_le16(priv->offchan_tx_timeout); | 1017 | scan_ch->passive_dwell = |
1035 | scan_ch->passive_dwell = 0; | 1018 | cpu_to_le16(priv->hw_roc_duration); |
1036 | 1019 | ||
1037 | /* Set txpower levels to defaults */ | 1020 | /* Set txpower levels to defaults */ |
1038 | scan_ch->dsp_atten = 110; | 1021 | scan_ch->dsp_atten = 110; |
@@ -1041,7 +1024,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1041 | * power level: | 1024 | * power level: |
1042 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | 1025 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; |
1043 | */ | 1026 | */ |
1044 | if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ) | 1027 | if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) |
1045 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | 1028 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; |
1046 | else | 1029 | else |
1047 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | 1030 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index d42ef1763a71..d562e9359d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -337,10 +337,10 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
337 | cmd.slots[0].type = 0; /* BSS */ | 337 | cmd.slots[0].type = 0; /* BSS */ |
338 | cmd.slots[1].type = 1; /* PAN */ | 338 | cmd.slots[1].type = 1; /* PAN */ |
339 | 339 | ||
340 | if (priv->hw_roc_channel) { | 340 | if (priv->hw_roc_setup) { |
341 | /* both contexts must be used for this to happen */ | 341 | /* both contexts must be used for this to happen */ |
342 | slot1 = priv->hw_roc_duration; | 342 | slot1 = IWL_MIN_SLOT_TIME; |
343 | slot0 = IWL_MIN_SLOT_TIME; | 343 | slot0 = 3000; |
344 | } else if (ctx_bss->vif && ctx_pan->vif) { | 344 | } else if (ctx_bss->vif && ctx_pan->vif) { |
345 | int bcnint = ctx_pan->beacon_int; | 345 | int bcnint = ctx_pan->beacon_int; |
346 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; | 346 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; |
@@ -437,23 +437,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
437 | /* always get timestamp with Rx frame */ | 437 | /* always get timestamp with Rx frame */ |
438 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; | 438 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; |
439 | 439 | ||
440 | if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) { | ||
441 | struct ieee80211_channel *chan = priv->hw_roc_channel; | ||
442 | |||
443 | iwl_set_rxon_channel(priv, chan, ctx); | ||
444 | iwl_set_flags_for_band(priv, ctx, chan->band, NULL); | ||
445 | ctx->staging.filter_flags |= | ||
446 | RXON_FILTER_ASSOC_MSK | | ||
447 | RXON_FILTER_PROMISC_MSK | | ||
448 | RXON_FILTER_CTL2HOST_MSK; | ||
449 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
450 | new_assoc = true; | ||
451 | |||
452 | if (memcmp(&ctx->staging, &ctx->active, | ||
453 | sizeof(ctx->staging)) == 0) | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | /* | 440 | /* |
458 | * force CTS-to-self frames protection if RTS-CTS is not preferred | 441 | * force CTS-to-self frames protection if RTS-CTS is not preferred |
459 | * one aggregation protection method | 442 | * one aggregation protection method |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 53bb59ee719d..9bc26da62768 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -128,11 +128,10 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | |||
128 | * handle build REPLY_TX command notification. | 128 | * handle build REPLY_TX command notification. |
129 | */ | 129 | */ |
130 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | 130 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, |
131 | struct sk_buff *skb, | 131 | struct sk_buff *skb, |
132 | struct iwl_tx_cmd *tx_cmd, | 132 | struct iwl_tx_cmd *tx_cmd, |
133 | struct ieee80211_tx_info *info, | 133 | struct ieee80211_tx_info *info, |
134 | struct ieee80211_hdr *hdr, | 134 | struct ieee80211_hdr *hdr, u8 sta_id) |
135 | u8 std_id) | ||
136 | { | 135 | { |
137 | __le16 fc = hdr->frame_control; | 136 | __le16 fc = hdr->frame_control; |
138 | __le32 tx_flags = tx_cmd->tx_flags; | 137 | __le32 tx_flags = tx_cmd->tx_flags; |
@@ -157,7 +156,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
157 | tx_flags |= TX_CMD_FLG_IGNORE_BT; | 156 | tx_flags |= TX_CMD_FLG_IGNORE_BT; |
158 | 157 | ||
159 | 158 | ||
160 | tx_cmd->sta_id = std_id; | 159 | tx_cmd->sta_id = sta_id; |
161 | if (ieee80211_has_morefrags(fc)) | 160 | if (ieee80211_has_morefrags(fc)) |
162 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | 161 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; |
163 | 162 | ||
@@ -189,9 +188,9 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
189 | #define RTS_DFAULT_RETRY_LIMIT 60 | 188 | #define RTS_DFAULT_RETRY_LIMIT 60 |
190 | 189 | ||
191 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | 190 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, |
192 | struct iwl_tx_cmd *tx_cmd, | 191 | struct iwl_tx_cmd *tx_cmd, |
193 | struct ieee80211_tx_info *info, | 192 | struct ieee80211_tx_info *info, |
194 | __le16 fc) | 193 | __le16 fc) |
195 | { | 194 | { |
196 | u32 rate_flags; | 195 | u32 rate_flags; |
197 | int rate_idx; | 196 | int rate_idx; |
@@ -334,14 +333,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
334 | unsigned long flags; | 333 | unsigned long flags; |
335 | bool is_agg = false; | 334 | bool is_agg = false; |
336 | 335 | ||
337 | /* | 336 | if (info->control.vif) |
338 | * If the frame needs to go out off-channel, then | ||
339 | * we'll have put the PAN context to that channel, | ||
340 | * so make the frame go out there. | ||
341 | */ | ||
342 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
343 | ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
344 | else if (info->control.vif) | ||
345 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); | 337 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); |
346 | 338 | ||
347 | spin_lock_irqsave(&priv->lock, flags); | 339 | spin_lock_irqsave(&priv->lock, flags); |
@@ -407,7 +399,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
407 | */ | 399 | */ |
408 | hdr->frame_control |= | 400 | hdr->frame_control |= |
409 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 401 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
410 | } else | 402 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) |
403 | txq_id = IWL_AUX_QUEUE; | ||
404 | else | ||
411 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | 405 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; |
412 | 406 | ||
413 | /* irqs already disabled/saved above when locking priv->lock */ | 407 | /* irqs already disabled/saved above when locking priv->lock */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d5242fba8756..33894dde1ae3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -680,10 +680,12 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
680 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | 680 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; |
681 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = | 681 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = |
682 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); | 682 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); |
683 | #ifdef CONFIG_IWL_P2P | 683 | |
684 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes |= | 684 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P) |
685 | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); | 685 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes |= |
686 | #endif | 686 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
687 | BIT(NL80211_IFTYPE_P2P_GO); | ||
688 | |||
687 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; | 689 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; |
688 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; | 690 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; |
689 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; | 691 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; |
@@ -1234,6 +1236,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1234 | if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) | 1236 | if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) |
1235 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | 1237 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; |
1236 | 1238 | ||
1239 | /* | ||
1240 | * if not PAN, then don't support P2P -- might be a uCode | ||
1241 | * packaging bug or due to the eeprom check above | ||
1242 | */ | ||
1243 | if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) | ||
1244 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | ||
1245 | |||
1237 | if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { | 1246 | if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { |
1238 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | 1247 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; |
1239 | priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | 1248 | priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; |
@@ -1855,6 +1864,13 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1855 | 1864 | ||
1856 | iwl_scan_cancel_timeout(priv, 200); | 1865 | iwl_scan_cancel_timeout(priv, 200); |
1857 | 1866 | ||
1867 | /* | ||
1868 | * If active, scanning won't cancel it, so say it expired. | ||
1869 | * No race since we hold the mutex here and a new one | ||
1870 | * can't come in at this time. | ||
1871 | */ | ||
1872 | ieee80211_remain_on_channel_expired(priv->hw); | ||
1873 | |||
1858 | exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); | 1874 | exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); |
1859 | 1875 | ||
1860 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set | 1876 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set |
@@ -2045,94 +2061,6 @@ static void iwl_bg_restart(struct work_struct *data) | |||
2045 | } | 2061 | } |
2046 | } | 2062 | } |
2047 | 2063 | ||
2048 | static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
2049 | struct ieee80211_channel *chan, | ||
2050 | enum nl80211_channel_type channel_type, | ||
2051 | unsigned int wait) | ||
2052 | { | ||
2053 | struct iwl_priv *priv = hw->priv; | ||
2054 | int ret; | ||
2055 | |||
2056 | /* Not supported if we don't have PAN */ | ||
2057 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) { | ||
2058 | ret = -EOPNOTSUPP; | ||
2059 | goto free; | ||
2060 | } | ||
2061 | |||
2062 | /* Not supported on pre-P2P firmware */ | ||
2063 | if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes & | ||
2064 | BIT(NL80211_IFTYPE_P2P_CLIENT))) { | ||
2065 | ret = -EOPNOTSUPP; | ||
2066 | goto free; | ||
2067 | } | ||
2068 | |||
2069 | mutex_lock(&priv->mutex); | ||
2070 | |||
2071 | if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) { | ||
2072 | /* | ||
2073 | * If the PAN context is free, use the normal | ||
2074 | * way of doing remain-on-channel offload + TX. | ||
2075 | */ | ||
2076 | ret = 1; | ||
2077 | goto out; | ||
2078 | } | ||
2079 | |||
2080 | /* TODO: queue up if scanning? */ | ||
2081 | if (test_bit(STATUS_SCANNING, &priv->status) || | ||
2082 | priv->offchan_tx_skb) { | ||
2083 | ret = -EBUSY; | ||
2084 | goto out; | ||
2085 | } | ||
2086 | |||
2087 | /* | ||
2088 | * max_scan_ie_len doesn't include the blank SSID or the header, | ||
2089 | * so need to add that again here. | ||
2090 | */ | ||
2091 | if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) { | ||
2092 | ret = -ENOBUFS; | ||
2093 | goto out; | ||
2094 | } | ||
2095 | |||
2096 | priv->offchan_tx_skb = skb; | ||
2097 | priv->offchan_tx_timeout = wait; | ||
2098 | priv->offchan_tx_chan = chan; | ||
2099 | |||
2100 | ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif, | ||
2101 | IWL_SCAN_OFFCH_TX, chan->band); | ||
2102 | if (ret) | ||
2103 | priv->offchan_tx_skb = NULL; | ||
2104 | out: | ||
2105 | mutex_unlock(&priv->mutex); | ||
2106 | free: | ||
2107 | if (ret < 0) | ||
2108 | kfree_skb(skb); | ||
2109 | |||
2110 | return ret; | ||
2111 | } | ||
2112 | |||
2113 | static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw) | ||
2114 | { | ||
2115 | struct iwl_priv *priv = hw->priv; | ||
2116 | int ret; | ||
2117 | |||
2118 | mutex_lock(&priv->mutex); | ||
2119 | |||
2120 | if (!priv->offchan_tx_skb) { | ||
2121 | ret = -EINVAL; | ||
2122 | goto unlock; | ||
2123 | } | ||
2124 | |||
2125 | priv->offchan_tx_skb = NULL; | ||
2126 | |||
2127 | ret = iwl_scan_cancel_timeout(priv, 200); | ||
2128 | if (ret) | ||
2129 | ret = -EIO; | ||
2130 | unlock: | ||
2131 | mutex_unlock(&priv->mutex); | ||
2132 | |||
2133 | return ret; | ||
2134 | } | ||
2135 | |||
2136 | /***************************************************************************** | 2064 | /***************************************************************************** |
2137 | * | 2065 | * |
2138 | * mac80211 entry point functions | 2066 | * mac80211 entry point functions |
@@ -3288,35 +3216,34 @@ done: | |||
3288 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3216 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3289 | } | 3217 | } |
3290 | 3218 | ||
3291 | static void iwlagn_disable_roc(struct iwl_priv *priv) | 3219 | void iwlagn_disable_roc(struct iwl_priv *priv) |
3292 | { | 3220 | { |
3293 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | 3221 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; |
3294 | struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel); | ||
3295 | 3222 | ||
3296 | lockdep_assert_held(&priv->mutex); | 3223 | lockdep_assert_held(&priv->mutex); |
3297 | 3224 | ||
3298 | if (!ctx->is_active) | 3225 | if (!priv->hw_roc_setup) |
3299 | return; | 3226 | return; |
3300 | 3227 | ||
3301 | ctx->staging.dev_type = RXON_DEV_TYPE_2STA; | 3228 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; |
3302 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3229 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3303 | iwl_set_rxon_channel(priv, chan, ctx); | ||
3304 | iwl_set_flags_for_band(priv, ctx, chan->band, NULL); | ||
3305 | 3230 | ||
3306 | priv->hw_roc_channel = NULL; | 3231 | priv->hw_roc_channel = NULL; |
3307 | 3232 | ||
3233 | memset(ctx->staging.node_addr, 0, ETH_ALEN); | ||
3234 | |||
3308 | iwlagn_commit_rxon(priv, ctx); | 3235 | iwlagn_commit_rxon(priv, ctx); |
3309 | 3236 | ||
3310 | ctx->is_active = false; | 3237 | ctx->is_active = false; |
3238 | priv->hw_roc_setup = false; | ||
3311 | } | 3239 | } |
3312 | 3240 | ||
3313 | static void iwlagn_bg_roc_done(struct work_struct *work) | 3241 | static void iwlagn_disable_roc_work(struct work_struct *work) |
3314 | { | 3242 | { |
3315 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 3243 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
3316 | hw_roc_work.work); | 3244 | hw_roc_disable_work.work); |
3317 | 3245 | ||
3318 | mutex_lock(&priv->mutex); | 3246 | mutex_lock(&priv->mutex); |
3319 | ieee80211_remain_on_channel_expired(priv->hw); | ||
3320 | iwlagn_disable_roc(priv); | 3247 | iwlagn_disable_roc(priv); |
3321 | mutex_unlock(&priv->mutex); | 3248 | mutex_unlock(&priv->mutex); |
3322 | } | 3249 | } |
@@ -3327,33 +3254,63 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
3327 | int duration) | 3254 | int duration) |
3328 | { | 3255 | { |
3329 | struct iwl_priv *priv = hw->priv; | 3256 | struct iwl_priv *priv = hw->priv; |
3257 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
3330 | int err = 0; | 3258 | int err = 0; |
3331 | 3259 | ||
3332 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | 3260 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) |
3333 | return -EOPNOTSUPP; | 3261 | return -EOPNOTSUPP; |
3334 | 3262 | ||
3335 | if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes & | 3263 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) |
3336 | BIT(NL80211_IFTYPE_P2P_CLIENT))) | ||
3337 | return -EOPNOTSUPP; | 3264 | return -EOPNOTSUPP; |
3338 | 3265 | ||
3339 | mutex_lock(&priv->mutex); | 3266 | mutex_lock(&priv->mutex); |
3340 | 3267 | ||
3341 | if (priv->contexts[IWL_RXON_CTX_PAN].is_active || | 3268 | /* |
3342 | test_bit(STATUS_SCAN_HW, &priv->status)) { | 3269 | * TODO: Remove this hack! Firmware needs to be updated |
3270 | * to allow longer off-channel periods in scanning for | ||
3271 | * this use case, based on a flag (and we'll need an API | ||
3272 | * flag in the firmware when it has that). | ||
3273 | */ | ||
3274 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) | ||
3275 | duration = 80; | ||
3276 | |||
3277 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
3343 | err = -EBUSY; | 3278 | err = -EBUSY; |
3344 | goto out; | 3279 | goto out; |
3345 | } | 3280 | } |
3346 | 3281 | ||
3347 | priv->contexts[IWL_RXON_CTX_PAN].is_active = true; | ||
3348 | priv->hw_roc_channel = channel; | 3282 | priv->hw_roc_channel = channel; |
3349 | priv->hw_roc_chantype = channel_type; | 3283 | priv->hw_roc_chantype = channel_type; |
3350 | priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); | 3284 | priv->hw_roc_duration = duration; |
3351 | iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); | 3285 | cancel_delayed_work(&priv->hw_roc_disable_work); |
3352 | queue_delayed_work(priv->workqueue, &priv->hw_roc_work, | 3286 | |
3353 | msecs_to_jiffies(duration + 20)); | 3287 | if (!ctx->is_active) { |
3288 | ctx->is_active = true; | ||
3289 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
3290 | memcpy(ctx->staging.node_addr, | ||
3291 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
3292 | ETH_ALEN); | ||
3293 | memcpy(ctx->staging.bssid_addr, | ||
3294 | priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr, | ||
3295 | ETH_ALEN); | ||
3296 | err = iwlagn_commit_rxon(priv, ctx); | ||
3297 | if (err) | ||
3298 | goto out; | ||
3299 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK | | ||
3300 | RXON_FILTER_PROMISC_MSK | | ||
3301 | RXON_FILTER_CTL2HOST_MSK; | ||
3302 | |||
3303 | err = iwlagn_commit_rxon(priv, ctx); | ||
3304 | if (err) { | ||
3305 | iwlagn_disable_roc(priv); | ||
3306 | goto out; | ||
3307 | } | ||
3308 | priv->hw_roc_setup = true; | ||
3309 | } | ||
3354 | 3310 | ||
3355 | msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */ | 3311 | err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band); |
3356 | ieee80211_ready_on_channel(priv->hw); | 3312 | if (err) |
3313 | iwlagn_disable_roc(priv); | ||
3357 | 3314 | ||
3358 | out: | 3315 | out: |
3359 | mutex_unlock(&priv->mutex); | 3316 | mutex_unlock(&priv->mutex); |
@@ -3368,9 +3325,8 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
3368 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | 3325 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) |
3369 | return -EOPNOTSUPP; | 3326 | return -EOPNOTSUPP; |
3370 | 3327 | ||
3371 | cancel_delayed_work_sync(&priv->hw_roc_work); | ||
3372 | |||
3373 | mutex_lock(&priv->mutex); | 3328 | mutex_lock(&priv->mutex); |
3329 | iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); | ||
3374 | iwlagn_disable_roc(priv); | 3330 | iwlagn_disable_roc(priv); |
3375 | mutex_unlock(&priv->mutex); | 3331 | mutex_unlock(&priv->mutex); |
3376 | 3332 | ||
@@ -3395,7 +3351,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3395 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); | 3351 | INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); |
3396 | INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); | 3352 | INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); |
3397 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); | 3353 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); |
3398 | INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done); | 3354 | INIT_DELAYED_WORK(&priv->hw_roc_disable_work, |
3355 | iwlagn_disable_roc_work); | ||
3399 | 3356 | ||
3400 | iwl_setup_scan_deferred_work(priv); | 3357 | iwl_setup_scan_deferred_work(priv); |
3401 | 3358 | ||
@@ -3427,6 +3384,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3427 | 3384 | ||
3428 | cancel_work_sync(&priv->bt_full_concurrency); | 3385 | cancel_work_sync(&priv->bt_full_concurrency); |
3429 | cancel_work_sync(&priv->bt_runtime_config); | 3386 | cancel_work_sync(&priv->bt_runtime_config); |
3387 | cancel_delayed_work_sync(&priv->hw_roc_disable_work); | ||
3430 | 3388 | ||
3431 | del_timer_sync(&priv->statistics_periodic); | 3389 | del_timer_sync(&priv->statistics_periodic); |
3432 | del_timer_sync(&priv->ucode_trace); | 3390 | del_timer_sync(&priv->ucode_trace); |
@@ -3579,8 +3537,6 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
3579 | .tx_last_beacon = iwl_mac_tx_last_beacon, | 3537 | .tx_last_beacon = iwl_mac_tx_last_beacon, |
3580 | .remain_on_channel = iwl_mac_remain_on_channel, | 3538 | .remain_on_channel = iwl_mac_remain_on_channel, |
3581 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, | 3539 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, |
3582 | .offchannel_tx = iwl_mac_offchannel_tx, | ||
3583 | .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, | ||
3584 | .rssi_callback = iwl_mac_rssi_callback, | 3540 | .rssi_callback = iwl_mac_rssi_callback, |
3585 | CFG80211_TESTMODE_CMD(iwl_testmode_cmd) | 3541 | CFG80211_TESTMODE_CMD(iwl_testmode_cmd) |
3586 | CFG80211_TESTMODE_DUMP(iwl_testmode_dump) | 3542 | CFG80211_TESTMODE_DUMP(iwl_testmode_dump) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d941c4c98e4b..df2960ae92aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -209,6 +209,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); | |||
209 | /* scan */ | 209 | /* scan */ |
210 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | 210 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); |
211 | void iwlagn_post_scan(struct iwl_priv *priv); | 211 | void iwlagn_post_scan(struct iwl_priv *priv); |
212 | void iwlagn_disable_roc(struct iwl_priv *priv); | ||
212 | 213 | ||
213 | /* station mgmt */ | 214 | /* station mgmt */ |
214 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 215 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cf376f62b2f6..e269987cd64c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "iwl-io.h" | 40 | #include "iwl-io.h" |
41 | #include "iwl-power.h" | 41 | #include "iwl-power.h" |
42 | #include "iwl-sta.h" | 42 | #include "iwl-sta.h" |
43 | #include "iwl-agn.h" | ||
43 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
44 | #include "iwl-agn.h" | 45 | #include "iwl-agn.h" |
45 | #include "iwl-trans.h" | 46 | #include "iwl-trans.h" |
@@ -1273,8 +1274,12 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1273 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", | 1274 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
1274 | viftype, vif->addr); | 1275 | viftype, vif->addr); |
1275 | 1276 | ||
1277 | cancel_delayed_work_sync(&priv->hw_roc_disable_work); | ||
1278 | |||
1276 | mutex_lock(&priv->mutex); | 1279 | mutex_lock(&priv->mutex); |
1277 | 1280 | ||
1281 | iwlagn_disable_roc(priv); | ||
1282 | |||
1278 | if (!iwl_is_ready_rf(priv)) { | 1283 | if (!iwl_is_ready_rf(priv)) { |
1279 | IWL_WARN(priv, "Try to add interface when device not ready\n"); | 1284 | IWL_WARN(priv, "Try to add interface when device not ready\n"); |
1280 | err = -EINVAL; | 1285 | err = -EINVAL; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 233baf60ed63..dd34c7c502fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -575,11 +575,13 @@ enum iwl_ucode_tlv_type { | |||
575 | * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, | 575 | * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, |
576 | * treats good CRC threshold as a boolean | 576 | * treats good CRC threshold as a boolean |
577 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | 577 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). |
578 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | ||
578 | */ | 579 | */ |
579 | enum iwl_ucode_tlv_flag { | 580 | enum iwl_ucode_tlv_flag { |
580 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 581 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
581 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | 582 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), |
582 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 583 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
584 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | ||
583 | }; | 585 | }; |
584 | 586 | ||
585 | struct iwl_ucode_tlv { | 587 | struct iwl_ucode_tlv { |
@@ -1179,7 +1181,7 @@ struct iwl_rxon_context { | |||
1179 | enum iwl_scan_type { | 1181 | enum iwl_scan_type { |
1180 | IWL_SCAN_NORMAL, | 1182 | IWL_SCAN_NORMAL, |
1181 | IWL_SCAN_RADIO_RESET, | 1183 | IWL_SCAN_RADIO_RESET, |
1182 | IWL_SCAN_OFFCH_TX, | 1184 | IWL_SCAN_ROC, |
1183 | }; | 1185 | }; |
1184 | 1186 | ||
1185 | enum iwlagn_ucode_type { | 1187 | enum iwlagn_ucode_type { |
@@ -1449,15 +1451,11 @@ struct iwl_priv { | |||
1449 | 1451 | ||
1450 | /* remain-on-channel offload support */ | 1452 | /* remain-on-channel offload support */ |
1451 | struct ieee80211_channel *hw_roc_channel; | 1453 | struct ieee80211_channel *hw_roc_channel; |
1452 | struct delayed_work hw_roc_work; | 1454 | struct delayed_work hw_roc_disable_work; |
1453 | enum nl80211_channel_type hw_roc_chantype; | 1455 | enum nl80211_channel_type hw_roc_chantype; |
1454 | int hw_roc_duration; | 1456 | int hw_roc_duration; |
1455 | bool hw_roc_setup; | 1457 | bool hw_roc_setup; |
1456 | 1458 | ||
1457 | struct sk_buff *offchan_tx_skb; | ||
1458 | int offchan_tx_timeout; | ||
1459 | struct ieee80211_channel *offchan_tx_chan; | ||
1460 | |||
1461 | /* bt coex */ | 1459 | /* bt coex */ |
1462 | u8 bt_enable_flag; | 1460 | u8 bt_enable_flag; |
1463 | u8 bt_status; | 1461 | u8 bt_status; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd6937e97055..28e59319f581 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -103,6 +103,12 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | |||
103 | ieee80211_scan_completed(priv->hw, aborted); | 103 | ieee80211_scan_completed(priv->hw, aborted); |
104 | } | 104 | } |
105 | 105 | ||
106 | if (priv->scan_type == IWL_SCAN_ROC) { | ||
107 | ieee80211_remain_on_channel_expired(priv->hw); | ||
108 | priv->hw_roc_channel = NULL; | ||
109 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
110 | } | ||
111 | |||
106 | priv->scan_type = IWL_SCAN_NORMAL; | 112 | priv->scan_type = IWL_SCAN_NORMAL; |
107 | priv->scan_vif = NULL; | 113 | priv->scan_vif = NULL; |
108 | priv->scan_request = NULL; | 114 | priv->scan_request = NULL; |
@@ -211,6 +217,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | |||
211 | le32_to_cpu(notif->tsf_high), | 217 | le32_to_cpu(notif->tsf_high), |
212 | le32_to_cpu(notif->tsf_low), | 218 | le32_to_cpu(notif->tsf_low), |
213 | notif->status, notif->beacon_timer); | 219 | notif->status, notif->beacon_timer); |
220 | |||
221 | if (priv->scan_type == IWL_SCAN_ROC) | ||
222 | ieee80211_ready_on_channel(priv->hw); | ||
214 | } | 223 | } |
215 | 224 | ||
216 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ | 225 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ |
@@ -370,7 +379,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
370 | 379 | ||
371 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", | 380 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", |
372 | scan_type == IWL_SCAN_NORMAL ? "" : | 381 | scan_type == IWL_SCAN_NORMAL ? "" : |
373 | scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " : | 382 | scan_type == IWL_SCAN_ROC ? "remain-on-channel " : |
374 | "internal short "); | 383 | "internal short "); |
375 | 384 | ||
376 | set_bit(STATUS_SCANNING, &priv->status); | 385 | set_bit(STATUS_SCANNING, &priv->status); |
@@ -565,10 +574,10 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
565 | goto out_settings; | 574 | goto out_settings; |
566 | } | 575 | } |
567 | 576 | ||
568 | if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) { | 577 | if (priv->scan_type == IWL_SCAN_ROC) { |
569 | ieee80211_tx_status_irqsafe(priv->hw, | 578 | ieee80211_remain_on_channel_expired(priv->hw); |
570 | priv->offchan_tx_skb); | 579 | priv->hw_roc_channel = NULL; |
571 | priv->offchan_tx_skb = NULL; | 580 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); |
572 | } | 581 | } |
573 | 582 | ||
574 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | 583 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { |