aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-23 13:24:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-08 16:04:04 -0400
commitc6baf7fb40cb141c4b510372f7dac829621ccf3f (patch)
tree7ba06f858ef0e7f904f4fd20ca1f15d0687b0784 /drivers/net/wireless
parent4d2a5d0ecd3d5350957ed8afc4cee2dbc606c7e2 (diff)
iwlagn: support new P2P implementation
The previous P2P implementation turned out to not work well and new uCode capabilities were added to support P2P. Modify the driver to take advantage of those, and also discover P2P support automatically based on a uCode flag instead of having a Kconfig symbol for P2P. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c47
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c190
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c19
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
115config 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
756static 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
768int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) 756int 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 */
130static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, 130static 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
191static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, 190static 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
2048static 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
2113static 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;
2130unlock:
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
3291static void iwlagn_disable_roc(struct iwl_priv *priv) 3219void 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
3313static void iwlagn_bg_roc_done(struct work_struct *work) 3241static 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 */
210int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); 210int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
211void iwlagn_post_scan(struct iwl_priv *priv); 211void iwlagn_post_scan(struct iwl_priv *priv);
212void iwlagn_disable_roc(struct iwl_priv *priv);
212 213
213/* station mgmt */ 214/* station mgmt */
214int iwlagn_manage_ibss_station(struct iwl_priv *priv, 215int 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 */
579enum iwl_ucode_tlv_flag { 580enum 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
585struct iwl_ucode_tlv { 587struct iwl_ucode_tlv {
@@ -1179,7 +1181,7 @@ struct iwl_rxon_context {
1179enum iwl_scan_type { 1181enum 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
1185enum iwlagn_ucode_type { 1187enum 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) {