diff options
161 files changed, 7162 insertions, 6258 deletions
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt index 9551622d0a7b..356f791af574 100644 --- a/Documentation/networking/regulatory.txt +++ b/Documentation/networking/regulatory.txt | |||
@@ -159,10 +159,10 @@ struct ieee80211_regdomain mydriver_jp_regdom = { | |||
159 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), | 159 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), |
160 | /* IEEE 802.11a, channels 34..48 */ | 160 | /* IEEE 802.11a, channels 34..48 */ |
161 | REG_RULE(5170-20, 5240+20, 40, 6, 20, | 161 | REG_RULE(5170-20, 5240+20, 40, 6, 20, |
162 | NL80211_RRF_PASSIVE_SCAN), | 162 | NL80211_RRF_NO_IR), |
163 | /* IEEE 802.11a, channels 52..64 */ | 163 | /* IEEE 802.11a, channels 52..64 */ |
164 | REG_RULE(5260-20, 5320+20, 40, 6, 20, | 164 | REG_RULE(5260-20, 5320+20, 40, 6, 20, |
165 | NL80211_RRF_NO_IBSS | | 165 | NL80211_RRF_NO_IR| |
166 | NL80211_RRF_DFS), | 166 | NL80211_RRF_DFS), |
167 | } | 167 | } |
168 | }; | 168 | }; |
diff --git a/MAINTAINERS b/MAINTAINERS index 4afcfb4c892b..b9ea9321adde 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1458,17 +1458,6 @@ T: git git://github.com/kvalo/ath.git | |||
1458 | S: Supported | 1458 | S: Supported |
1459 | F: drivers/net/wireless/ath/ath6kl/ | 1459 | F: drivers/net/wireless/ath/ath6kl/ |
1460 | 1460 | ||
1461 | ATHEROS ATH9K WIRELESS DRIVER | ||
1462 | M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com> | ||
1463 | M: Jouni Malinen <jouni@qca.qualcomm.com> | ||
1464 | M: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | ||
1465 | M: Senthil Balasubramanian <senthilb@qca.qualcomm.com> | ||
1466 | L: linux-wireless@vger.kernel.org | ||
1467 | L: ath9k-devel@lists.ath9k.org | ||
1468 | W: http://wireless.kernel.org/en/users/Drivers/ath9k | ||
1469 | S: Supported | ||
1470 | F: drivers/net/wireless/ath/ath9k/ | ||
1471 | |||
1472 | WILOCITY WIL6210 WIRELESS DRIVER | 1461 | WILOCITY WIL6210 WIRELESS DRIVER |
1473 | M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 1462 | M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> |
1474 | L: linux-wireless@vger.kernel.org | 1463 | L: linux-wireless@vger.kernel.org |
@@ -6928,6 +6917,14 @@ T: git git://linuxtv.org/anttip/media_tree.git | |||
6928 | S: Maintained | 6917 | S: Maintained |
6929 | F: drivers/media/tuners/qt1010* | 6918 | F: drivers/media/tuners/qt1010* |
6930 | 6919 | ||
6920 | QUALCOMM ATHEROS ATH9K WIRELESS DRIVER | ||
6921 | M: QCA ath9k Development <ath9k-devel@qca.qualcomm.com> | ||
6922 | L: linux-wireless@vger.kernel.org | ||
6923 | L: ath9k-devel@lists.ath9k.org | ||
6924 | W: http://wireless.kernel.org/en/users/Drivers/ath9k | ||
6925 | S: Supported | ||
6926 | F: drivers/net/wireless/ath/ath9k/ | ||
6927 | |||
6931 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER | 6928 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
6932 | M: Kalle Valo <kvalo@qca.qualcomm.com> | 6929 | M: Kalle Valo <kvalo@qca.qualcomm.com> |
6933 | L: ath10k@lists.infradead.org | 6930 | L: ath10k@lists.infradead.org |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 6fb98b53533f..12a4ff751359 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -238,7 +238,6 @@ static void bcma_host_pci_remove(struct pci_dev *dev) | |||
238 | pci_release_regions(dev); | 238 | pci_release_regions(dev); |
239 | pci_disable_device(dev); | 239 | pci_disable_device(dev); |
240 | kfree(bus); | 240 | kfree(bus); |
241 | pci_set_drvdata(dev, NULL); | ||
242 | } | 241 | } |
243 | 242 | ||
244 | #ifdef CONFIG_PM_SLEEP | 243 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 97ac8c87cba2..06fe2b8fa22d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -1351,12 +1351,12 @@ static int ath10k_update_channel_list(struct ath10k *ar) | |||
1351 | ch->allow_vht = true; | 1351 | ch->allow_vht = true; |
1352 | 1352 | ||
1353 | ch->allow_ibss = | 1353 | ch->allow_ibss = |
1354 | !(channel->flags & IEEE80211_CHAN_NO_IBSS); | 1354 | !(channel->flags & IEEE80211_CHAN_NO_IR); |
1355 | 1355 | ||
1356 | ch->ht40plus = | 1356 | ch->ht40plus = |
1357 | !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); | 1357 | !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); |
1358 | 1358 | ||
1359 | passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN; | 1359 | passive = channel->flags & IEEE80211_CHAN_NO_IR; |
1360 | ch->passive = passive; | 1360 | ch->passive = passive; |
1361 | 1361 | ||
1362 | ch->freq = channel->center_freq; | 1362 | ch->freq = channel->center_freq; |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 2437ad26949d..fd4c89df67e1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | |||
1109 | (mode == WMI_11G_HT20) ? | 1109 | (mode == WMI_11G_HT20) ? |
1110 | NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); | 1110 | NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); |
1111 | 1111 | ||
1112 | mutex_lock(&vif->wdev.mtx); | ||
1112 | cfg80211_ch_switch_notify(vif->ndev, &chandef); | 1113 | cfg80211_ch_switch_notify(vif->ndev, &chandef); |
1114 | mutex_unlock(&vif->wdev.mtx); | ||
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 1117 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
@@ -3169,12 +3171,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len) | |||
3169 | } | 3171 | } |
3170 | 3172 | ||
3171 | static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 3173 | static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
3172 | struct ieee80211_channel *chan, bool offchan, | 3174 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) |
3173 | unsigned int wait, const u8 *buf, size_t len, | ||
3174 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
3175 | { | 3175 | { |
3176 | struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); | 3176 | struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); |
3177 | struct ath6kl *ar = ath6kl_priv(vif->ndev); | 3177 | struct ath6kl *ar = ath6kl_priv(vif->ndev); |
3178 | struct ieee80211_channel *chan = params->chan; | ||
3179 | const u8 *buf = params->buf; | ||
3180 | size_t len = params->len; | ||
3181 | unsigned int wait = params->wait; | ||
3182 | bool no_cck = params->no_cck; | ||
3178 | u32 id, freq; | 3183 | u32 id, freq; |
3179 | const struct ieee80211_mgmt *mgmt; | 3184 | const struct ieee80211_mgmt *mgmt; |
3180 | bool more_data, queued; | 3185 | bool more_data, queued; |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 32f139e2e897..30d273c61bff 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -86,7 +86,7 @@ config ATH9K_DFS_CERTIFIED | |||
86 | 86 | ||
87 | config ATH9K_TX99 | 87 | config ATH9K_TX99 |
88 | bool "Atheros ath9k TX99 testing support" | 88 | bool "Atheros ath9k TX99 testing support" |
89 | depends on CFG80211_CERTIFICATION_ONUS | 89 | depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS |
90 | default n | 90 | default n |
91 | ---help--- | 91 | ---help--- |
92 | Say N. This should only be enabled on systems undergoing | 92 | Say N. This should only be enabled on systems undergoing |
@@ -104,6 +104,14 @@ config ATH9K_TX99 | |||
104 | be evaluated to meet the RF exposure limits set forth in the | 104 | be evaluated to meet the RF exposure limits set forth in the |
105 | governmental SAR regulations. | 105 | governmental SAR regulations. |
106 | 106 | ||
107 | config ATH9K_WOW | ||
108 | bool "Wake on Wireless LAN support (EXPERIMENTAL)" | ||
109 | depends on ATH9K && PM | ||
110 | default n | ||
111 | ---help--- | ||
112 | This option enables Wake on Wireless LAN support for certain cards. | ||
113 | Currently, AR9462 is supported. | ||
114 | |||
107 | config ATH9K_LEGACY_RATE_CONTROL | 115 | config ATH9K_LEGACY_RATE_CONTROL |
108 | bool "Atheros ath9k rate control" | 116 | bool "Atheros ath9k rate control" |
109 | depends on ATH9K | 117 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 6205ef5a9321..337c459eda28 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -13,9 +13,9 @@ ath9k-$(CONFIG_ATH9K_PCI) += pci.o | |||
13 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 13 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | 15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o |
16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ | 16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o |
17 | dfs.o | 17 | ath9k-$(CONFIG_ATH9K_TX99) += tx99.o |
18 | ath9k-$(CONFIG_PM_SLEEP) += wow.o | 18 | ath9k-$(CONFIG_ATH9K_WOW) += wow.o |
19 | 19 | ||
20 | obj-$(CONFIG_ATH9K) += ath9k.o | 20 | obj-$(CONFIG_ATH9K) += ath9k.o |
21 | 21 | ||
@@ -41,6 +41,8 @@ ath9k_hw-y:= \ | |||
41 | ar9003_eeprom.o \ | 41 | ar9003_eeprom.o \ |
42 | ar9003_paprd.o | 42 | ar9003_paprd.o |
43 | 43 | ||
44 | ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o | ||
45 | |||
44 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ | 46 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ |
45 | ar9003_mci.o | 47 | ar9003_mci.o |
46 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 48 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 7546b9a7dcbf..e7cdf1100f56 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -352,7 +352,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { | |||
352 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 352 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
353 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 353 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
354 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 354 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, |
355 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, | 355 | {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, |
356 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 356 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
357 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 357 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
358 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 358 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
@@ -378,9 +378,9 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
378 | {0x00009814, 0x9280c00a}, | 378 | {0x00009814, 0x9280c00a}, |
379 | {0x00009818, 0x00000000}, | 379 | {0x00009818, 0x00000000}, |
380 | {0x0000981c, 0x00020028}, | 380 | {0x0000981c, 0x00020028}, |
381 | {0x00009834, 0x6400a290}, | 381 | {0x00009834, 0x6400a190}, |
382 | {0x00009838, 0x0108ecff}, | 382 | {0x00009838, 0x0108ecff}, |
383 | {0x0000983c, 0x0d000600}, | 383 | {0x0000983c, 0x14000600}, |
384 | {0x00009880, 0x201fff00}, | 384 | {0x00009880, 0x201fff00}, |
385 | {0x00009884, 0x00001042}, | 385 | {0x00009884, 0x00001042}, |
386 | {0x000098a4, 0x00200400}, | 386 | {0x000098a4, 0x00200400}, |
@@ -401,7 +401,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
401 | {0x00009d04, 0x40206c10}, | 401 | {0x00009d04, 0x40206c10}, |
402 | {0x00009d08, 0x009c4060}, | 402 | {0x00009d08, 0x009c4060}, |
403 | {0x00009d0c, 0x9883800a}, | 403 | {0x00009d0c, 0x9883800a}, |
404 | {0x00009d10, 0x01834061}, | 404 | {0x00009d10, 0x01884061}, |
405 | {0x00009d14, 0x00c0040b}, | 405 | {0x00009d14, 0x00c0040b}, |
406 | {0x00009d18, 0x00000000}, | 406 | {0x00009d18, 0x00000000}, |
407 | {0x00009e08, 0x0038230c}, | 407 | {0x00009e08, 0x0038230c}, |
@@ -459,7 +459,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
459 | {0x0000a3e8, 0x20202020}, | 459 | {0x0000a3e8, 0x20202020}, |
460 | {0x0000a3ec, 0x20202020}, | 460 | {0x0000a3ec, 0x20202020}, |
461 | {0x0000a3f0, 0x00000000}, | 461 | {0x0000a3f0, 0x00000000}, |
462 | {0x0000a3f4, 0x00000246}, | 462 | {0x0000a3f4, 0x00000000}, |
463 | {0x0000a3f8, 0x0c9bd380}, | 463 | {0x0000a3f8, 0x0c9bd380}, |
464 | {0x0000a3fc, 0x000f0f01}, | 464 | {0x0000a3fc, 0x000f0f01}, |
465 | {0x0000a400, 0x8fa91f01}, | 465 | {0x0000a400, 0x8fa91f01}, |
@@ -644,7 +644,7 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | |||
644 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | 644 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
645 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | 645 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
646 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 646 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
647 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 647 | {0x0000a410, 0x000050d4, 0x000050d4, 0x000050d9, 0x000050d9}, |
648 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 648 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
649 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 649 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
650 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, | 650 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
@@ -1086,8 +1086,8 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | |||
1086 | {0x0000b074, 0x00000000}, | 1086 | {0x0000b074, 0x00000000}, |
1087 | {0x0000b078, 0x00000000}, | 1087 | {0x0000b078, 0x00000000}, |
1088 | {0x0000b07c, 0x00000000}, | 1088 | {0x0000b07c, 0x00000000}, |
1089 | {0x0000b080, 0x2a2d2f32}, | 1089 | {0x0000b080, 0x23232323}, |
1090 | {0x0000b084, 0x21232328}, | 1090 | {0x0000b084, 0x21232323}, |
1091 | {0x0000b088, 0x19191c1e}, | 1091 | {0x0000b088, 0x19191c1e}, |
1092 | {0x0000b08c, 0x12141417}, | 1092 | {0x0000b08c, 0x12141417}, |
1093 | {0x0000b090, 0x07070e0e}, | 1093 | {0x0000b090, 0x07070e0e}, |
@@ -1385,9 +1385,9 @@ static const u32 ar9300_2p2_mac_core[][2] = { | |||
1385 | {0x000081f8, 0x00000000}, | 1385 | {0x000081f8, 0x00000000}, |
1386 | {0x000081fc, 0x00000000}, | 1386 | {0x000081fc, 0x00000000}, |
1387 | {0x00008240, 0x00100000}, | 1387 | {0x00008240, 0x00100000}, |
1388 | {0x00008244, 0x0010f424}, | 1388 | {0x00008244, 0x0010f400}, |
1389 | {0x00008248, 0x00000800}, | 1389 | {0x00008248, 0x00000800}, |
1390 | {0x0000824c, 0x0001e848}, | 1390 | {0x0000824c, 0x0001e800}, |
1391 | {0x00008250, 0x00000000}, | 1391 | {0x00008250, 0x00000000}, |
1392 | {0x00008254, 0x00000000}, | 1392 | {0x00008254, 0x00000000}, |
1393 | {0x00008258, 0x00000000}, | 1393 | {0x00008258, 0x00000000}, |
@@ -1726,16 +1726,23 @@ static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { | |||
1726 | 1726 | ||
1727 | static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { | 1727 | static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { |
1728 | /* Addr allmodes */ | 1728 | /* Addr allmodes */ |
1729 | {0x00004040, 0x08253e5e}, | 1729 | {0x00004040, 0x0825365e}, |
1730 | {0x00004040, 0x0008003b}, | 1730 | {0x00004040, 0x0008003b}, |
1731 | {0x00004044, 0x00000000}, | 1731 | {0x00004044, 0x00000000}, |
1732 | }; | 1732 | }; |
1733 | 1733 | ||
1734 | static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { | 1734 | static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { |
1735 | /* Addr allmodes */ | 1735 | /* Addr allmodes */ |
1736 | {0x00004040, 0x08213e5e}, | 1736 | {0x00004040, 0x0821365e}, |
1737 | {0x00004040, 0x0008003b}, | 1737 | {0x00004040, 0x0008003b}, |
1738 | {0x00004044, 0x00000000}, | 1738 | {0x00004044, 0x00000000}, |
1739 | }; | 1739 | }; |
1740 | 1740 | ||
1741 | static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = { | ||
1742 | /* Addr allmodes */ | ||
1743 | {0x0000a398, 0x00000000}, | ||
1744 | {0x0000a39c, 0x6f7f0301}, | ||
1745 | {0x0000a3a0, 0xca9228ee}, | ||
1746 | }; | ||
1747 | |||
1741 | #endif /* INITVALS_9003_2P2_H */ | 1748 | #endif /* INITVALS_9003_2P2_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 22934d3ca544..aa0127265746 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1040,14 +1040,14 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
1040 | } | 1040 | } |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 1043 | static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, |
1044 | struct ath9k_channel *chan) | 1044 | struct ath9k_channel *chan) |
1045 | { | 1045 | { |
1046 | struct ath_common *common = ath9k_hw_common(ah); | 1046 | struct ath_common *common = ath9k_hw_common(ah); |
1047 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 1047 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
1048 | bool txiqcal_done = false; | 1048 | bool txiqcal_done = false; |
1049 | bool is_reusable = true, status = true; | 1049 | bool is_reusable = true, status = true; |
1050 | bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; | 1050 | bool run_rtt_cal = false, run_agc_cal; |
1051 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | 1051 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); |
1052 | u32 rx_delay = 0; | 1052 | u32 rx_delay = 0; |
1053 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | 1053 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | |
@@ -1119,22 +1119,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1119 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | 1119 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, |
1120 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | 1120 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); |
1121 | txiqcal_done = run_agc_cal = true; | 1121 | txiqcal_done = run_agc_cal = true; |
1122 | } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) { | ||
1123 | run_agc_cal = true; | ||
1124 | sep_iq_cal = true; | ||
1125 | } | 1122 | } |
1126 | 1123 | ||
1127 | skip_tx_iqcal: | 1124 | skip_tx_iqcal: |
1128 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) | 1125 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
1129 | ar9003_mci_init_cal_req(ah, &is_reusable); | 1126 | ar9003_mci_init_cal_req(ah, &is_reusable); |
1130 | 1127 | ||
1131 | if (sep_iq_cal) { | ||
1132 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | ||
1133 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
1134 | udelay(5); | ||
1135 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
1136 | } | ||
1137 | |||
1138 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { | 1128 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { |
1139 | rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); | 1129 | rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); |
1140 | /* Disable BB_active */ | 1130 | /* Disable BB_active */ |
@@ -1228,13 +1218,109 @@ skip_tx_iqcal: | |||
1228 | return true; | 1218 | return true; |
1229 | } | 1219 | } |
1230 | 1220 | ||
1221 | static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, | ||
1222 | struct ath9k_channel *chan) | ||
1223 | { | ||
1224 | struct ath_common *common = ath9k_hw_common(ah); | ||
1225 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
1226 | bool txiqcal_done = false; | ||
1227 | bool is_reusable = true, status = true; | ||
1228 | bool run_agc_cal = false, sep_iq_cal = false; | ||
1229 | |||
1230 | /* Use chip chainmask only for calibration */ | ||
1231 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); | ||
1232 | |||
1233 | if (ah->enabled_cals & TX_CL_CAL) { | ||
1234 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
1235 | run_agc_cal = true; | ||
1236 | } | ||
1237 | |||
1238 | if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) | ||
1239 | goto skip_tx_iqcal; | ||
1240 | |||
1241 | /* Do Tx IQ Calibration */ | ||
1242 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, | ||
1243 | AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, | ||
1244 | DELPT); | ||
1245 | |||
1246 | /* | ||
1247 | * For AR9485 or later chips, TxIQ cal runs as part of | ||
1248 | * AGC calibration. Specifically, AR9550 in SoC chips. | ||
1249 | */ | ||
1250 | if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { | ||
1251 | txiqcal_done = true; | ||
1252 | run_agc_cal = true; | ||
1253 | } else { | ||
1254 | sep_iq_cal = true; | ||
1255 | run_agc_cal = true; | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | * In the SoC family, this will run for AR9300, AR9331 and AR9340. | ||
1260 | */ | ||
1261 | if (sep_iq_cal) { | ||
1262 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | ||
1263 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
1264 | udelay(5); | ||
1265 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
1266 | } | ||
1267 | |||
1268 | skip_tx_iqcal: | ||
1269 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | ||
1270 | /* Calibrate the AGC */ | ||
1271 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
1272 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
1273 | AR_PHY_AGC_CONTROL_CAL); | ||
1274 | |||
1275 | /* Poll for offset calibration complete */ | ||
1276 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
1277 | AR_PHY_AGC_CONTROL_CAL, | ||
1278 | 0, AH_WAIT_TIMEOUT); | ||
1279 | } | ||
1280 | |||
1281 | if (!status) { | ||
1282 | ath_dbg(common, CALIBRATE, | ||
1283 | "offset calibration failed to complete in %d ms; noisy environment?\n", | ||
1284 | AH_WAIT_TIMEOUT / 1000); | ||
1285 | return false; | ||
1286 | } | ||
1287 | |||
1288 | if (txiqcal_done) | ||
1289 | ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); | ||
1290 | |||
1291 | /* Revert chainmask to runtime parameters */ | ||
1292 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | ||
1293 | |||
1294 | /* Initialize list pointers */ | ||
1295 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | ||
1296 | |||
1297 | INIT_CAL(&ah->iq_caldata); | ||
1298 | INSERT_CAL(ah, &ah->iq_caldata); | ||
1299 | ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); | ||
1300 | |||
1301 | /* Initialize current pointer to first element in list */ | ||
1302 | ah->cal_list_curr = ah->cal_list; | ||
1303 | |||
1304 | if (ah->cal_list_curr) | ||
1305 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | ||
1306 | |||
1307 | if (caldata) | ||
1308 | caldata->CalValid = 0; | ||
1309 | |||
1310 | return true; | ||
1311 | } | ||
1312 | |||
1231 | void ar9003_hw_attach_calib_ops(struct ath_hw *ah) | 1313 | void ar9003_hw_attach_calib_ops(struct ath_hw *ah) |
1232 | { | 1314 | { |
1233 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1315 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1234 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 1316 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
1235 | 1317 | ||
1318 | if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
1319 | priv_ops->init_cal = ar9003_hw_init_cal_pcoem; | ||
1320 | else | ||
1321 | priv_ops->init_cal = ar9003_hw_init_cal_soc; | ||
1322 | |||
1236 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; | 1323 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; |
1237 | priv_ops->init_cal = ar9003_hw_init_cal; | ||
1238 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; | 1324 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; |
1239 | 1325 | ||
1240 | ops->calibrate = ar9003_hw_calibrate; | 1326 | ops->calibrate = ar9003_hw_calibrate; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 20e49095db2a..d8c1eee8ea53 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "ar9462_2p0_initvals.h" | 26 | #include "ar9462_2p0_initvals.h" |
27 | #include "ar9462_2p1_initvals.h" | 27 | #include "ar9462_2p1_initvals.h" |
28 | #include "ar9565_1p0_initvals.h" | 28 | #include "ar9565_1p0_initvals.h" |
29 | #include "ar9565_1p1_initvals.h" | ||
29 | 30 | ||
30 | /* General hardware code for the AR9003 hadware family */ | 31 | /* General hardware code for the AR9003 hadware family */ |
31 | 32 | ||
@@ -148,7 +149,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
148 | ar9340Modes_high_ob_db_tx_gain_table_1p0); | 149 | ar9340Modes_high_ob_db_tx_gain_table_1p0); |
149 | 150 | ||
150 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 151 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
151 | ar9340Modes_fast_clock_1p0); | 152 | ar9340Modes_fast_clock_1p0); |
153 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
154 | ar9340_1p0_baseband_core_txfir_coeff_japan_2484); | ||
152 | 155 | ||
153 | if (!ah->is_clk_25mhz) | 156 | if (!ah->is_clk_25mhz) |
154 | INIT_INI_ARRAY(&ah->iniAdditional, | 157 | INIT_INI_ARRAY(&ah->iniAdditional, |
@@ -223,6 +226,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
223 | ar9462_2p1_modes_fast_clock); | 226 | ar9462_2p1_modes_fast_clock); |
224 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | 227 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
225 | ar9462_2p1_baseband_core_txfir_coeff_japan_2484); | 228 | ar9462_2p1_baseband_core_txfir_coeff_japan_2484); |
229 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
230 | ar9462_2p1_pciephy_clkreq_disable_L1); | ||
231 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
232 | ar9462_2p1_pciephy_clkreq_disable_L1); | ||
226 | } else if (AR_SREV_9462_20(ah)) { | 233 | } else if (AR_SREV_9462_20(ah)) { |
227 | 234 | ||
228 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); | 235 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); |
@@ -247,18 +254,18 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
247 | ar9462_2p0_soc_postamble); | 254 | ar9462_2p0_soc_postamble); |
248 | 255 | ||
249 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 256 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
250 | ar9462_common_rx_gain_table_2p0); | 257 | ar9462_2p0_common_rx_gain); |
251 | 258 | ||
252 | /* Awake -> Sleep Setting */ | 259 | /* Awake -> Sleep Setting */ |
253 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 260 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
254 | ar9462_pciephy_clkreq_disable_L1_2p0); | 261 | ar9462_2p0_pciephy_clkreq_disable_L1); |
255 | /* Sleep -> Awake Setting */ | 262 | /* Sleep -> Awake Setting */ |
256 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 263 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
257 | ar9462_pciephy_clkreq_disable_L1_2p0); | 264 | ar9462_2p0_pciephy_clkreq_disable_L1); |
258 | 265 | ||
259 | /* Fast clock modal settings */ | 266 | /* Fast clock modal settings */ |
260 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 267 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
261 | ar9462_modes_fast_clock_2p0); | 268 | ar9462_2p0_modes_fast_clock); |
262 | 269 | ||
263 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | 270 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
264 | ar9462_2p0_baseband_core_txfir_coeff_japan_2484); | 271 | ar9462_2p0_baseband_core_txfir_coeff_japan_2484); |
@@ -330,7 +337,44 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
330 | ar9580_1p0_low_ob_db_tx_gain_table); | 337 | ar9580_1p0_low_ob_db_tx_gain_table); |
331 | 338 | ||
332 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 339 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
333 | ar9580_1p0_modes_fast_clock); | 340 | ar9580_1p0_modes_fast_clock); |
341 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
342 | ar9580_1p0_baseband_core_txfir_coeff_japan_2484); | ||
343 | } else if (AR_SREV_9565_11_OR_LATER(ah)) { | ||
344 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
345 | ar9565_1p1_mac_core); | ||
346 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
347 | ar9565_1p1_mac_postamble); | ||
348 | |||
349 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
350 | ar9565_1p1_baseband_core); | ||
351 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
352 | ar9565_1p1_baseband_postamble); | ||
353 | |||
354 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
355 | ar9565_1p1_radio_core); | ||
356 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
357 | ar9565_1p1_radio_postamble); | ||
358 | |||
359 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
360 | ar9565_1p1_soc_preamble); | ||
361 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
362 | ar9565_1p1_soc_postamble); | ||
363 | |||
364 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
365 | ar9565_1p1_Common_rx_gain_table); | ||
366 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
367 | ar9565_1p1_Modes_lowest_ob_db_tx_gain_table); | ||
368 | |||
369 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
370 | ar9565_1p1_pciephy_clkreq_disable_L1); | ||
371 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
372 | ar9565_1p1_pciephy_clkreq_disable_L1); | ||
373 | |||
374 | INIT_INI_ARRAY(&ah->iniModesFastClock, | ||
375 | ar9565_1p1_modes_fast_clock); | ||
376 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
377 | ar9565_1p1_baseband_core_txfir_coeff_japan_2484); | ||
334 | } else if (AR_SREV_9565(ah)) { | 378 | } else if (AR_SREV_9565(ah)) { |
335 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 379 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
336 | ar9565_1p0_mac_core); | 380 | ar9565_1p0_mac_core); |
@@ -411,7 +455,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
411 | 455 | ||
412 | /* Fast clock modal settings */ | 456 | /* Fast clock modal settings */ |
413 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 457 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
414 | ar9300Modes_fast_clock_2p2); | 458 | ar9300Modes_fast_clock_2p2); |
459 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
460 | ar9300_2p2_baseband_core_txfir_coeff_japan_2484); | ||
415 | } | 461 | } |
416 | } | 462 | } |
417 | 463 | ||
@@ -440,7 +486,10 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) | |||
440 | ar9462_2p1_modes_low_ob_db_tx_gain); | 486 | ar9462_2p1_modes_low_ob_db_tx_gain); |
441 | else if (AR_SREV_9462_20(ah)) | 487 | else if (AR_SREV_9462_20(ah)) |
442 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 488 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
443 | ar9462_modes_low_ob_db_tx_gain_table_2p0); | 489 | ar9462_2p0_modes_low_ob_db_tx_gain); |
490 | else if (AR_SREV_9565_11(ah)) | ||
491 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
492 | ar9565_1p1_modes_low_ob_db_tx_gain_table); | ||
444 | else if (AR_SREV_9565(ah)) | 493 | else if (AR_SREV_9565(ah)) |
445 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 494 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
446 | ar9565_1p0_modes_low_ob_db_tx_gain_table); | 495 | ar9565_1p0_modes_low_ob_db_tx_gain_table); |
@@ -474,7 +523,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) | |||
474 | ar9462_2p1_modes_high_ob_db_tx_gain); | 523 | ar9462_2p1_modes_high_ob_db_tx_gain); |
475 | else if (AR_SREV_9462_20(ah)) | 524 | else if (AR_SREV_9462_20(ah)) |
476 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 525 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
477 | ar9462_modes_high_ob_db_tx_gain_table_2p0); | 526 | ar9462_2p0_modes_high_ob_db_tx_gain); |
527 | else if (AR_SREV_9565_11(ah)) | ||
528 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
529 | ar9565_1p1_modes_high_ob_db_tx_gain_table); | ||
478 | else if (AR_SREV_9565(ah)) | 530 | else if (AR_SREV_9565(ah)) |
479 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 531 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
480 | ar9565_1p0_modes_high_ob_db_tx_gain_table); | 532 | ar9565_1p0_modes_high_ob_db_tx_gain_table); |
@@ -500,6 +552,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) | |||
500 | else if (AR_SREV_9580(ah)) | 552 | else if (AR_SREV_9580(ah)) |
501 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 553 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
502 | ar9580_1p0_low_ob_db_tx_gain_table); | 554 | ar9580_1p0_low_ob_db_tx_gain_table); |
555 | else if (AR_SREV_9565_11(ah)) | ||
556 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
557 | ar9565_1p1_modes_low_ob_db_tx_gain_table); | ||
503 | else if (AR_SREV_9565(ah)) | 558 | else if (AR_SREV_9565(ah)) |
504 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 559 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
505 | ar9565_1p0_modes_low_ob_db_tx_gain_table); | 560 | ar9565_1p0_modes_low_ob_db_tx_gain_table); |
@@ -525,6 +580,9 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah) | |||
525 | else if (AR_SREV_9580(ah)) | 580 | else if (AR_SREV_9580(ah)) |
526 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 581 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
527 | ar9580_1p0_high_power_tx_gain_table); | 582 | ar9580_1p0_high_power_tx_gain_table); |
583 | else if (AR_SREV_9565_11(ah)) | ||
584 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
585 | ar9565_1p1_modes_high_power_tx_gain_table); | ||
528 | else if (AR_SREV_9565(ah)) | 586 | else if (AR_SREV_9565(ah)) |
529 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 587 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
530 | ar9565_1p0_modes_high_power_tx_gain_table); | 588 | ar9565_1p0_modes_high_power_tx_gain_table); |
@@ -546,7 +604,7 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) | |||
546 | ar9462_2p1_modes_mix_ob_db_tx_gain); | 604 | ar9462_2p1_modes_mix_ob_db_tx_gain); |
547 | else if (AR_SREV_9462_20(ah)) | 605 | else if (AR_SREV_9462_20(ah)) |
548 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 606 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
549 | ar9462_modes_mix_ob_db_tx_gain_table_2p0); | 607 | ar9462_2p0_modes_mix_ob_db_tx_gain); |
550 | else | 608 | else |
551 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 609 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
552 | ar9300Modes_mixed_ob_db_tx_gain_table_2p2); | 610 | ar9300Modes_mixed_ob_db_tx_gain_table_2p2); |
@@ -581,6 +639,13 @@ static void ar9003_tx_gain_table_mode6(struct ath_hw *ah) | |||
581 | ar9580_1p0_type6_tx_gain_table); | 639 | ar9580_1p0_type6_tx_gain_table); |
582 | } | 640 | } |
583 | 641 | ||
642 | static void ar9003_tx_gain_table_mode7(struct ath_hw *ah) | ||
643 | { | ||
644 | if (AR_SREV_9340(ah)) | ||
645 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
646 | ar9340_cus227_tx_gain_table_1p0); | ||
647 | } | ||
648 | |||
584 | typedef void (*ath_txgain_tab)(struct ath_hw *ah); | 649 | typedef void (*ath_txgain_tab)(struct ath_hw *ah); |
585 | 650 | ||
586 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | 651 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) |
@@ -593,6 +658,7 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | |||
593 | ar9003_tx_gain_table_mode4, | 658 | ar9003_tx_gain_table_mode4, |
594 | ar9003_tx_gain_table_mode5, | 659 | ar9003_tx_gain_table_mode5, |
595 | ar9003_tx_gain_table_mode6, | 660 | ar9003_tx_gain_table_mode6, |
661 | ar9003_tx_gain_table_mode7, | ||
596 | }; | 662 | }; |
597 | int idx = ar9003_hw_get_tx_gain_idx(ah); | 663 | int idx = ar9003_hw_get_tx_gain_idx(ah); |
598 | 664 | ||
@@ -629,7 +695,10 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | |||
629 | ar9462_2p1_common_rx_gain); | 695 | ar9462_2p1_common_rx_gain); |
630 | else if (AR_SREV_9462_20(ah)) | 696 | else if (AR_SREV_9462_20(ah)) |
631 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 697 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
632 | ar9462_common_rx_gain_table_2p0); | 698 | ar9462_2p0_common_rx_gain); |
699 | else if (AR_SREV_9565_11(ah)) | ||
700 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
701 | ar9565_1p1_Common_rx_gain_table); | ||
633 | else if (AR_SREV_9565(ah)) | 702 | else if (AR_SREV_9565(ah)) |
634 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 703 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
635 | ar9565_1p0_Common_rx_gain_table); | 704 | ar9565_1p0_Common_rx_gain_table); |
@@ -657,7 +726,7 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
657 | ar9462_2p1_common_wo_xlna_rx_gain); | 726 | ar9462_2p1_common_wo_xlna_rx_gain); |
658 | else if (AR_SREV_9462_20(ah)) | 727 | else if (AR_SREV_9462_20(ah)) |
659 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 728 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
660 | ar9462_common_wo_xlna_rx_gain_table_2p0); | 729 | ar9462_2p0_common_wo_xlna_rx_gain); |
661 | else if (AR_SREV_9550(ah)) { | 730 | else if (AR_SREV_9550(ah)) { |
662 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 731 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
663 | ar955x_1p0_common_wo_xlna_rx_gain_table); | 732 | ar955x_1p0_common_wo_xlna_rx_gain_table); |
@@ -666,6 +735,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
666 | } else if (AR_SREV_9580(ah)) | 735 | } else if (AR_SREV_9580(ah)) |
667 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 736 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
668 | ar9580_1p0_wo_xlna_rx_gain_table); | 737 | ar9580_1p0_wo_xlna_rx_gain_table); |
738 | else if (AR_SREV_9565_11(ah)) | ||
739 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
740 | ar9565_1p1_common_wo_xlna_rx_gain_table); | ||
669 | else if (AR_SREV_9565(ah)) | 741 | else if (AR_SREV_9565(ah)) |
670 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 742 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
671 | ar9565_1p0_common_wo_xlna_rx_gain_table); | 743 | ar9565_1p0_common_wo_xlna_rx_gain_table); |
@@ -687,7 +759,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) | |||
687 | ar9462_2p1_baseband_postamble_5g_xlna); | 759 | ar9462_2p1_baseband_postamble_5g_xlna); |
688 | } else if (AR_SREV_9462_20(ah)) { | 760 | } else if (AR_SREV_9462_20(ah)) { |
689 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 761 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
690 | ar9462_common_mixed_rx_gain_table_2p0); | 762 | ar9462_2p0_common_mixed_rx_gain); |
691 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, | 763 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, |
692 | ar9462_2p0_baseband_core_mix_rxgain); | 764 | ar9462_2p0_baseband_core_mix_rxgain); |
693 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, | 765 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, |
@@ -701,12 +773,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) | |||
701 | { | 773 | { |
702 | if (AR_SREV_9462_21(ah)) { | 774 | if (AR_SREV_9462_21(ah)) { |
703 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 775 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
704 | ar9462_2p1_common_5g_xlna_only_rx_gain); | 776 | ar9462_2p1_common_5g_xlna_only_rxgain); |
705 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, | 777 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, |
706 | ar9462_2p1_baseband_postamble_5g_xlna); | 778 | ar9462_2p1_baseband_postamble_5g_xlna); |
707 | } else if (AR_SREV_9462_20(ah)) { | 779 | } else if (AR_SREV_9462_20(ah)) { |
708 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 780 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
709 | ar9462_2p0_5g_xlna_only_rxgain); | 781 | ar9462_2p0_common_5g_xlna_only_rxgain); |
710 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, | 782 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, |
711 | ar9462_2p0_baseband_postamble_5g_xlna); | 783 | ar9462_2p0_baseband_postamble_5g_xlna); |
712 | } | 784 | } |
@@ -750,6 +822,9 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
750 | static void ar9003_hw_configpcipowersave(struct ath_hw *ah, | 822 | static void ar9003_hw_configpcipowersave(struct ath_hw *ah, |
751 | bool power_off) | 823 | bool power_off) |
752 | { | 824 | { |
825 | unsigned int i; | ||
826 | struct ar5416IniArray *array; | ||
827 | |||
753 | /* | 828 | /* |
754 | * Increase L1 Entry Latency. Some WB222 boards don't have | 829 | * Increase L1 Entry Latency. Some WB222 boards don't have |
755 | * this change in eeprom/OTP. | 830 | * this change in eeprom/OTP. |
@@ -775,18 +850,13 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, | |||
775 | * Configire PCIE after Ini init. SERDES values now come from ini file | 850 | * Configire PCIE after Ini init. SERDES values now come from ini file |
776 | * This enables PCIe low power mode. | 851 | * This enables PCIe low power mode. |
777 | */ | 852 | */ |
778 | if (ah->config.pcieSerDesWrite) { | 853 | array = power_off ? &ah->iniPcieSerdes : |
779 | unsigned int i; | 854 | &ah->iniPcieSerdesLowPower; |
780 | struct ar5416IniArray *array; | ||
781 | 855 | ||
782 | array = power_off ? &ah->iniPcieSerdes : | 856 | for (i = 0; i < array->ia_rows; i++) { |
783 | &ah->iniPcieSerdesLowPower; | 857 | REG_WRITE(ah, |
784 | 858 | INI_RA(array, i, 0), | |
785 | for (i = 0; i < array->ia_rows; i++) { | 859 | INI_RA(array, i, 1)); |
786 | REG_WRITE(ah, | ||
787 | INI_RA(array, i, 0), | ||
788 | INI_RA(array, i, 1)); | ||
789 | } | ||
790 | } | 860 | } |
791 | } | 861 | } |
792 | 862 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d39b79f5e841..39b71b3d6919 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -641,11 +641,12 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
641 | else | 641 | else |
642 | ah->enabled_cals &= ~TX_IQ_CAL; | 642 | ah->enabled_cals &= ~TX_IQ_CAL; |
643 | 643 | ||
644 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) | ||
645 | ah->enabled_cals |= TX_CL_CAL; | ||
646 | else | ||
647 | ah->enabled_cals &= ~TX_CL_CAL; | ||
648 | } | 644 | } |
645 | |||
646 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) | ||
647 | ah->enabled_cals |= TX_CL_CAL; | ||
648 | else | ||
649 | ah->enabled_cals &= ~TX_CL_CAL; | ||
649 | } | 650 | } |
650 | 651 | ||
651 | static void ar9003_hw_prog_ini(struct ath_hw *ah, | 652 | static void ar9003_hw_prog_ini(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c new file mode 100644 index 000000000000..81c88dd606dc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/export.h> | ||
18 | #include "ath9k.h" | ||
19 | #include "reg.h" | ||
20 | #include "hw-ops.h" | ||
21 | |||
22 | const char *ath9k_hw_wow_event_to_string(u32 wow_event) | ||
23 | { | ||
24 | if (wow_event & AH_WOW_MAGIC_PATTERN_EN) | ||
25 | return "Magic pattern"; | ||
26 | if (wow_event & AH_WOW_USER_PATTERN_EN) | ||
27 | return "User pattern"; | ||
28 | if (wow_event & AH_WOW_LINK_CHANGE) | ||
29 | return "Link change"; | ||
30 | if (wow_event & AH_WOW_BEACON_MISS) | ||
31 | return "Beacon miss"; | ||
32 | |||
33 | return "unknown reason"; | ||
34 | } | ||
35 | EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); | ||
36 | |||
37 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | ||
38 | { | ||
39 | struct ath_common *common = ath9k_hw_common(ah); | ||
40 | |||
41 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
42 | |||
43 | /* set rx disable bit */ | ||
44 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
45 | |||
46 | if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { | ||
47 | ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | ||
48 | REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); | ||
53 | } | ||
54 | |||
55 | static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | ||
56 | { | ||
57 | struct ath_common *common = ath9k_hw_common(ah); | ||
58 | u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; | ||
59 | u32 ctl[13] = {0}; | ||
60 | u32 data_word[KAL_NUM_DATA_WORDS]; | ||
61 | u8 i; | ||
62 | u32 wow_ka_data_word0; | ||
63 | |||
64 | memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); | ||
65 | memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); | ||
66 | |||
67 | /* set the transmit buffer */ | ||
68 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); | ||
69 | ctl[1] = 0; | ||
70 | ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ | ||
71 | ctl[4] = 0; | ||
72 | ctl[7] = (ah->txchainmask) << 2; | ||
73 | ctl[2] = 0xf << 16; /* tx_tries 0 */ | ||
74 | |||
75 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) | ||
76 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | ||
77 | |||
78 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | ||
79 | |||
80 | data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | | ||
81 | (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); | ||
82 | data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | | ||
83 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); | ||
84 | data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | | ||
85 | (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); | ||
86 | data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | | ||
87 | (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); | ||
88 | data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | | ||
89 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); | ||
90 | data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); | ||
91 | |||
92 | if (AR_SREV_9462_20(ah)) { | ||
93 | /* AR9462 2.0 has an extra descriptor word (time based | ||
94 | * discard) compared to other chips */ | ||
95 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); | ||
96 | wow_ka_data_word0 = AR_WOW_TXBUF(13); | ||
97 | } else { | ||
98 | wow_ka_data_word0 = AR_WOW_TXBUF(12); | ||
99 | } | ||
100 | |||
101 | for (i = 0; i < KAL_NUM_DATA_WORDS; i++) | ||
102 | REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); | ||
103 | |||
104 | } | ||
105 | |||
106 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | ||
107 | u8 *user_mask, int pattern_count, | ||
108 | int pattern_len) | ||
109 | { | ||
110 | int i; | ||
111 | u32 pattern_val, mask_val; | ||
112 | u32 set, clr; | ||
113 | |||
114 | /* FIXME: should check count by querying the hardware capability */ | ||
115 | if (pattern_count >= MAX_NUM_PATTERN) | ||
116 | return; | ||
117 | |||
118 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | ||
119 | |||
120 | /* set the registers for pattern */ | ||
121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { | ||
122 | memcpy(&pattern_val, user_pattern, 4); | ||
123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), | ||
124 | pattern_val); | ||
125 | user_pattern += 4; | ||
126 | } | ||
127 | |||
128 | /* set the registers for mask */ | ||
129 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { | ||
130 | memcpy(&mask_val, user_mask, 4); | ||
131 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); | ||
132 | user_mask += 4; | ||
133 | } | ||
134 | |||
135 | /* set the pattern length to be matched | ||
136 | * | ||
137 | * AR_WOW_LENGTH1_REG1 | ||
138 | * bit 31:24 pattern 0 length | ||
139 | * bit 23:16 pattern 1 length | ||
140 | * bit 15:8 pattern 2 length | ||
141 | * bit 7:0 pattern 3 length | ||
142 | * | ||
143 | * AR_WOW_LENGTH1_REG2 | ||
144 | * bit 31:24 pattern 4 length | ||
145 | * bit 23:16 pattern 5 length | ||
146 | * bit 15:8 pattern 6 length | ||
147 | * bit 7:0 pattern 7 length | ||
148 | * | ||
149 | * the below logic writes out the new | ||
150 | * pattern length for the corresponding | ||
151 | * pattern_count, while masking out the | ||
152 | * other fields | ||
153 | */ | ||
154 | |||
155 | ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); | ||
156 | |||
157 | if (pattern_count < 4) { | ||
158 | /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ | ||
159 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
160 | AR_WOW_LEN1_SHIFT(pattern_count); | ||
161 | clr = AR_WOW_LENGTH1_MASK(pattern_count); | ||
162 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); | ||
163 | } else { | ||
164 | /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ | ||
165 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
166 | AR_WOW_LEN2_SHIFT(pattern_count); | ||
167 | clr = AR_WOW_LENGTH2_MASK(pattern_count); | ||
168 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); | ||
169 | } | ||
170 | |||
171 | } | ||
172 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); | ||
173 | |||
174 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | ||
175 | { | ||
176 | u32 wow_status = 0; | ||
177 | u32 val = 0, rval; | ||
178 | |||
179 | /* | ||
180 | * read the WoW status register to know | ||
181 | * the wakeup reason | ||
182 | */ | ||
183 | rval = REG_READ(ah, AR_WOW_PATTERN); | ||
184 | val = AR_WOW_STATUS(rval); | ||
185 | |||
186 | /* | ||
187 | * mask only the WoW events that we have enabled. Sometimes | ||
188 | * we have spurious WoW events from the AR_WOW_PATTERN | ||
189 | * register. This mask will clean it up. | ||
190 | */ | ||
191 | |||
192 | val &= ah->wow_event_mask; | ||
193 | |||
194 | if (val) { | ||
195 | if (val & AR_WOW_MAGIC_PAT_FOUND) | ||
196 | wow_status |= AH_WOW_MAGIC_PATTERN_EN; | ||
197 | if (AR_WOW_PATTERN_FOUND(val)) | ||
198 | wow_status |= AH_WOW_USER_PATTERN_EN; | ||
199 | if (val & AR_WOW_KEEP_ALIVE_FAIL) | ||
200 | wow_status |= AH_WOW_LINK_CHANGE; | ||
201 | if (val & AR_WOW_BEACON_FAIL) | ||
202 | wow_status |= AH_WOW_BEACON_MISS; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * set and clear WOW_PME_CLEAR registers for the chip to | ||
207 | * generate next wow signal. | ||
208 | * disable D3 before accessing other registers ? | ||
209 | */ | ||
210 | |||
211 | /* do we need to check the bit value 0x01000000 (7-10) ?? */ | ||
212 | REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, | ||
213 | AR_PMCTRL_PWR_STATE_D1D3); | ||
214 | |||
215 | /* | ||
216 | * clear all events | ||
217 | */ | ||
218 | REG_WRITE(ah, AR_WOW_PATTERN, | ||
219 | AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); | ||
220 | |||
221 | /* | ||
222 | * restore the beacon threshold to init value | ||
223 | */ | ||
224 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
225 | |||
226 | /* | ||
227 | * Restore the way the PCI-E reset, Power-On-Reset, external | ||
228 | * PCIE_POR_SHORT pins are tied to its original value. | ||
229 | * Previously just before WoW sleep, we untie the PCI-E | ||
230 | * reset to our Chip's Power On Reset so that any PCI-E | ||
231 | * reset from the bus will not reset our chip | ||
232 | */ | ||
233 | if (ah->is_pciexpress) | ||
234 | ath9k_hw_configpcipowersave(ah, false); | ||
235 | |||
236 | ah->wow_event_mask = 0; | ||
237 | |||
238 | return wow_status; | ||
239 | } | ||
240 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); | ||
241 | |||
242 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) | ||
243 | { | ||
244 | u32 wow_event_mask; | ||
245 | u32 set, clr; | ||
246 | |||
247 | /* | ||
248 | * wow_event_mask is a mask to the AR_WOW_PATTERN register to | ||
249 | * indicate which WoW events we have enabled. The WoW events | ||
250 | * are from the 'pattern_enable' in this function and | ||
251 | * 'pattern_count' of ath9k_hw_wow_apply_pattern() | ||
252 | */ | ||
253 | wow_event_mask = ah->wow_event_mask; | ||
254 | |||
255 | /* | ||
256 | * Untie Power-on-Reset from the PCI-E-Reset. When we are in | ||
257 | * WOW sleep, we do want the Reset from the PCI-E to disturb | ||
258 | * our hw state | ||
259 | */ | ||
260 | if (ah->is_pciexpress) { | ||
261 | /* | ||
262 | * we need to untie the internal POR (power-on-reset) | ||
263 | * to the external PCI-E reset. We also need to tie | ||
264 | * the PCI-E Phy reset to the PCI-E reset. | ||
265 | */ | ||
266 | set = AR_WA_RESET_EN | AR_WA_POR_SHORT; | ||
267 | clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; | ||
268 | REG_RMW(ah, AR_WA, set, clr); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * set the power states appropriately and enable PME | ||
273 | */ | ||
274 | set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | | ||
275 | AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; | ||
276 | |||
277 | /* | ||
278 | * set and clear WOW_PME_CLEAR registers for the chip | ||
279 | * to generate next wow signal. | ||
280 | */ | ||
281 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | ||
282 | clr = AR_PMCTRL_WOW_PME_CLR; | ||
283 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | ||
284 | |||
285 | /* | ||
286 | * Setup for: | ||
287 | * - beacon misses | ||
288 | * - magic pattern | ||
289 | * - keep alive timeout | ||
290 | * - pattern matching | ||
291 | */ | ||
292 | |||
293 | /* | ||
294 | * Program default values for pattern backoff, aifs/slot/KAL count, | ||
295 | * beacon miss timeout, KAL timeout, etc. | ||
296 | */ | ||
297 | set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); | ||
298 | REG_SET_BIT(ah, AR_WOW_PATTERN, set); | ||
299 | |||
300 | set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | ||
301 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | ||
302 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); | ||
303 | REG_SET_BIT(ah, AR_WOW_COUNT, set); | ||
304 | |||
305 | if (pattern_enable & AH_WOW_BEACON_MISS) | ||
306 | set = AR_WOW_BEACON_TIMO; | ||
307 | /* We are not using beacon miss, program a large value */ | ||
308 | else | ||
309 | set = AR_WOW_BEACON_TIMO_MAX; | ||
310 | |||
311 | REG_WRITE(ah, AR_WOW_BCN_TIMO, set); | ||
312 | |||
313 | /* | ||
314 | * Keep alive timo in ms except AR9280 | ||
315 | */ | ||
316 | if (!pattern_enable) | ||
317 | set = AR_WOW_KEEP_ALIVE_NEVER; | ||
318 | else | ||
319 | set = KAL_TIMEOUT * 32; | ||
320 | |||
321 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); | ||
322 | |||
323 | /* | ||
324 | * Keep alive delay in us. based on 'power on clock', | ||
325 | * therefore in usec | ||
326 | */ | ||
327 | set = KAL_DELAY * 1000; | ||
328 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); | ||
329 | |||
330 | /* | ||
331 | * Create keep alive pattern to respond to beacons | ||
332 | */ | ||
333 | ath9k_wow_create_keep_alive_pattern(ah); | ||
334 | |||
335 | /* | ||
336 | * Configure MAC WoW Registers | ||
337 | */ | ||
338 | set = 0; | ||
339 | /* Send keep alive timeouts anyway */ | ||
340 | clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; | ||
341 | |||
342 | if (pattern_enable & AH_WOW_LINK_CHANGE) | ||
343 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; | ||
344 | else | ||
345 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | ||
346 | |||
347 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | ||
348 | REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); | ||
349 | |||
350 | /* | ||
351 | * we are relying on a bmiss failure. ensure we have | ||
352 | * enough threshold to prevent false positives | ||
353 | */ | ||
354 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, | ||
355 | AR_WOW_BMISSTHRESHOLD); | ||
356 | |||
357 | set = 0; | ||
358 | clr = 0; | ||
359 | |||
360 | if (pattern_enable & AH_WOW_BEACON_MISS) { | ||
361 | set = AR_WOW_BEACON_FAIL_EN; | ||
362 | wow_event_mask |= AR_WOW_BEACON_FAIL; | ||
363 | } else { | ||
364 | clr = AR_WOW_BEACON_FAIL_EN; | ||
365 | } | ||
366 | |||
367 | REG_RMW(ah, AR_WOW_BCN_EN, set, clr); | ||
368 | |||
369 | set = 0; | ||
370 | clr = 0; | ||
371 | /* | ||
372 | * Enable the magic packet registers | ||
373 | */ | ||
374 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { | ||
375 | set = AR_WOW_MAGIC_EN; | ||
376 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; | ||
377 | } else { | ||
378 | clr = AR_WOW_MAGIC_EN; | ||
379 | } | ||
380 | set |= AR_WOW_MAC_INTR_EN; | ||
381 | REG_RMW(ah, AR_WOW_PATTERN, set, clr); | ||
382 | |||
383 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, | ||
384 | AR_WOW_PATTERN_SUPPORTED); | ||
385 | |||
386 | /* | ||
387 | * Set the power states appropriately and enable PME | ||
388 | */ | ||
389 | clr = 0; | ||
390 | set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | | ||
391 | AR_PMCTRL_PWR_PM_CTRL_ENA; | ||
392 | |||
393 | clr = AR_PCIE_PM_CTRL_ENA; | ||
394 | REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); | ||
395 | |||
396 | /* | ||
397 | * this is needed to prevent the chip waking up | ||
398 | * the host within 3-4 seconds with certain | ||
399 | * platform/BIOS. The fix is to enable | ||
400 | * D1 & D3 to match original definition and | ||
401 | * also match the OTP value. Anyway this | ||
402 | * is more related to SW WOW. | ||
403 | */ | ||
404 | clr = AR_PMCTRL_PWR_STATE_D1D3; | ||
405 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | ||
406 | |||
407 | set = AR_PMCTRL_PWR_STATE_D1D3_REAL; | ||
408 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | ||
409 | |||
410 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); | ||
411 | |||
412 | /* to bring down WOW power low margin */ | ||
413 | set = BIT(13); | ||
414 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); | ||
415 | /* HW WoW */ | ||
416 | clr = BIT(5); | ||
417 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); | ||
418 | |||
419 | ath9k_hw_set_powermode_wow_sleep(ah); | ||
420 | ah->wow_event_mask = wow_event_mask; | ||
421 | } | ||
422 | EXPORT_SYMBOL(ath9k_hw_wow_enable); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index 25db9215985a..7f22cb2a4941 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h | |||
@@ -18,6 +18,18 @@ | |||
18 | #ifndef INITVALS_9340_H | 18 | #ifndef INITVALS_9340_H |
19 | #define INITVALS_9340_H | 19 | #define INITVALS_9340_H |
20 | 20 | ||
21 | #define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble | ||
22 | |||
23 | #define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
24 | |||
25 | #define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2 | ||
26 | |||
27 | #define ar9340Common_rx_gain_table_1p0 ar9300Common_rx_gain_table_2p2 | ||
28 | |||
29 | #define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
30 | |||
31 | #define ar9340_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 | ||
32 | |||
21 | static const u32 ar9340_1p0_radio_postamble[][5] = { | 33 | static const u32 ar9340_1p0_radio_postamble[][5] = { |
22 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 34 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
23 | {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, | 35 | {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, |
@@ -100,8 +112,6 @@ static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { | |||
100 | {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, | 112 | {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
101 | }; | 113 | }; |
102 | 114 | ||
103 | #define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2 | ||
104 | |||
105 | static const u32 ar9340_1p0_radio_core[][2] = { | 115 | static const u32 ar9340_1p0_radio_core[][2] = { |
106 | /* Addr allmodes */ | 116 | /* Addr allmodes */ |
107 | {0x00016000, 0x36db6db6}, | 117 | {0x00016000, 0x36db6db6}, |
@@ -215,16 +225,12 @@ static const u32 ar9340_1p0_radio_core_40M[][2] = { | |||
215 | {0x0000824c, 0x0001e800}, | 225 | {0x0000824c, 0x0001e800}, |
216 | }; | 226 | }; |
217 | 227 | ||
218 | #define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble | ||
219 | |||
220 | #define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
221 | |||
222 | static const u32 ar9340_1p0_baseband_postamble[][5] = { | 228 | static const u32 ar9340_1p0_baseband_postamble[][5] = { |
223 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 229 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
224 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | 230 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, |
225 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, | 231 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, |
226 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, | 232 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, |
227 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, | 233 | {0x00009828, 0x06903081, 0x06903081, 0x09103881, 0x09103881}, |
228 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 234 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
229 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 235 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
230 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 236 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
@@ -340,9 +346,9 @@ static const u32 ar9340_1p0_baseband_core[][2] = { | |||
340 | {0x0000a370, 0x00000000}, | 346 | {0x0000a370, 0x00000000}, |
341 | {0x0000a390, 0x00000001}, | 347 | {0x0000a390, 0x00000001}, |
342 | {0x0000a394, 0x00000444}, | 348 | {0x0000a394, 0x00000444}, |
343 | {0x0000a398, 0x001f0e0f}, | 349 | {0x0000a398, 0x00000000}, |
344 | {0x0000a39c, 0x0075393f}, | 350 | {0x0000a39c, 0x210d0401}, |
345 | {0x0000a3a0, 0xb79f6427}, | 351 | {0x0000a3a0, 0xab9a7144}, |
346 | {0x0000a3a4, 0x00000000}, | 352 | {0x0000a3a4, 0x00000000}, |
347 | {0x0000a3a8, 0xaaaaaaaa}, | 353 | {0x0000a3a8, 0xaaaaaaaa}, |
348 | {0x0000a3ac, 0x3c466478}, | 354 | {0x0000a3ac, 0x3c466478}, |
@@ -714,266 +720,6 @@ static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { | |||
714 | {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000}, | 720 | {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000}, |
715 | }; | 721 | }; |
716 | 722 | ||
717 | static const u32 ar9340Common_rx_gain_table_1p0[][2] = { | ||
718 | /* Addr allmodes */ | ||
719 | {0x0000a000, 0x00010000}, | ||
720 | {0x0000a004, 0x00030002}, | ||
721 | {0x0000a008, 0x00050004}, | ||
722 | {0x0000a00c, 0x00810080}, | ||
723 | {0x0000a010, 0x00830082}, | ||
724 | {0x0000a014, 0x01810180}, | ||
725 | {0x0000a018, 0x01830182}, | ||
726 | {0x0000a01c, 0x01850184}, | ||
727 | {0x0000a020, 0x01890188}, | ||
728 | {0x0000a024, 0x018b018a}, | ||
729 | {0x0000a028, 0x018d018c}, | ||
730 | {0x0000a02c, 0x01910190}, | ||
731 | {0x0000a030, 0x01930192}, | ||
732 | {0x0000a034, 0x01950194}, | ||
733 | {0x0000a038, 0x038a0196}, | ||
734 | {0x0000a03c, 0x038c038b}, | ||
735 | {0x0000a040, 0x0390038d}, | ||
736 | {0x0000a044, 0x03920391}, | ||
737 | {0x0000a048, 0x03940393}, | ||
738 | {0x0000a04c, 0x03960395}, | ||
739 | {0x0000a050, 0x00000000}, | ||
740 | {0x0000a054, 0x00000000}, | ||
741 | {0x0000a058, 0x00000000}, | ||
742 | {0x0000a05c, 0x00000000}, | ||
743 | {0x0000a060, 0x00000000}, | ||
744 | {0x0000a064, 0x00000000}, | ||
745 | {0x0000a068, 0x00000000}, | ||
746 | {0x0000a06c, 0x00000000}, | ||
747 | {0x0000a070, 0x00000000}, | ||
748 | {0x0000a074, 0x00000000}, | ||
749 | {0x0000a078, 0x00000000}, | ||
750 | {0x0000a07c, 0x00000000}, | ||
751 | {0x0000a080, 0x22222229}, | ||
752 | {0x0000a084, 0x1d1d1d1d}, | ||
753 | {0x0000a088, 0x1d1d1d1d}, | ||
754 | {0x0000a08c, 0x1d1d1d1d}, | ||
755 | {0x0000a090, 0x171d1d1d}, | ||
756 | {0x0000a094, 0x11111717}, | ||
757 | {0x0000a098, 0x00030311}, | ||
758 | {0x0000a09c, 0x00000000}, | ||
759 | {0x0000a0a0, 0x00000000}, | ||
760 | {0x0000a0a4, 0x00000000}, | ||
761 | {0x0000a0a8, 0x00000000}, | ||
762 | {0x0000a0ac, 0x00000000}, | ||
763 | {0x0000a0b0, 0x00000000}, | ||
764 | {0x0000a0b4, 0x00000000}, | ||
765 | {0x0000a0b8, 0x00000000}, | ||
766 | {0x0000a0bc, 0x00000000}, | ||
767 | {0x0000a0c0, 0x001f0000}, | ||
768 | {0x0000a0c4, 0x01000101}, | ||
769 | {0x0000a0c8, 0x011e011f}, | ||
770 | {0x0000a0cc, 0x011c011d}, | ||
771 | {0x0000a0d0, 0x02030204}, | ||
772 | {0x0000a0d4, 0x02010202}, | ||
773 | {0x0000a0d8, 0x021f0200}, | ||
774 | {0x0000a0dc, 0x0302021e}, | ||
775 | {0x0000a0e0, 0x03000301}, | ||
776 | {0x0000a0e4, 0x031e031f}, | ||
777 | {0x0000a0e8, 0x0402031d}, | ||
778 | {0x0000a0ec, 0x04000401}, | ||
779 | {0x0000a0f0, 0x041e041f}, | ||
780 | {0x0000a0f4, 0x0502041d}, | ||
781 | {0x0000a0f8, 0x05000501}, | ||
782 | {0x0000a0fc, 0x051e051f}, | ||
783 | {0x0000a100, 0x06010602}, | ||
784 | {0x0000a104, 0x061f0600}, | ||
785 | {0x0000a108, 0x061d061e}, | ||
786 | {0x0000a10c, 0x07020703}, | ||
787 | {0x0000a110, 0x07000701}, | ||
788 | {0x0000a114, 0x00000000}, | ||
789 | {0x0000a118, 0x00000000}, | ||
790 | {0x0000a11c, 0x00000000}, | ||
791 | {0x0000a120, 0x00000000}, | ||
792 | {0x0000a124, 0x00000000}, | ||
793 | {0x0000a128, 0x00000000}, | ||
794 | {0x0000a12c, 0x00000000}, | ||
795 | {0x0000a130, 0x00000000}, | ||
796 | {0x0000a134, 0x00000000}, | ||
797 | {0x0000a138, 0x00000000}, | ||
798 | {0x0000a13c, 0x00000000}, | ||
799 | {0x0000a140, 0x001f0000}, | ||
800 | {0x0000a144, 0x01000101}, | ||
801 | {0x0000a148, 0x011e011f}, | ||
802 | {0x0000a14c, 0x011c011d}, | ||
803 | {0x0000a150, 0x02030204}, | ||
804 | {0x0000a154, 0x02010202}, | ||
805 | {0x0000a158, 0x021f0200}, | ||
806 | {0x0000a15c, 0x0302021e}, | ||
807 | {0x0000a160, 0x03000301}, | ||
808 | {0x0000a164, 0x031e031f}, | ||
809 | {0x0000a168, 0x0402031d}, | ||
810 | {0x0000a16c, 0x04000401}, | ||
811 | {0x0000a170, 0x041e041f}, | ||
812 | {0x0000a174, 0x0502041d}, | ||
813 | {0x0000a178, 0x05000501}, | ||
814 | {0x0000a17c, 0x051e051f}, | ||
815 | {0x0000a180, 0x06010602}, | ||
816 | {0x0000a184, 0x061f0600}, | ||
817 | {0x0000a188, 0x061d061e}, | ||
818 | {0x0000a18c, 0x07020703}, | ||
819 | {0x0000a190, 0x07000701}, | ||
820 | {0x0000a194, 0x00000000}, | ||
821 | {0x0000a198, 0x00000000}, | ||
822 | {0x0000a19c, 0x00000000}, | ||
823 | {0x0000a1a0, 0x00000000}, | ||
824 | {0x0000a1a4, 0x00000000}, | ||
825 | {0x0000a1a8, 0x00000000}, | ||
826 | {0x0000a1ac, 0x00000000}, | ||
827 | {0x0000a1b0, 0x00000000}, | ||
828 | {0x0000a1b4, 0x00000000}, | ||
829 | {0x0000a1b8, 0x00000000}, | ||
830 | {0x0000a1bc, 0x00000000}, | ||
831 | {0x0000a1c0, 0x00000000}, | ||
832 | {0x0000a1c4, 0x00000000}, | ||
833 | {0x0000a1c8, 0x00000000}, | ||
834 | {0x0000a1cc, 0x00000000}, | ||
835 | {0x0000a1d0, 0x00000000}, | ||
836 | {0x0000a1d4, 0x00000000}, | ||
837 | {0x0000a1d8, 0x00000000}, | ||
838 | {0x0000a1dc, 0x00000000}, | ||
839 | {0x0000a1e0, 0x00000000}, | ||
840 | {0x0000a1e4, 0x00000000}, | ||
841 | {0x0000a1e8, 0x00000000}, | ||
842 | {0x0000a1ec, 0x00000000}, | ||
843 | {0x0000a1f0, 0x00000396}, | ||
844 | {0x0000a1f4, 0x00000396}, | ||
845 | {0x0000a1f8, 0x00000396}, | ||
846 | {0x0000a1fc, 0x00000196}, | ||
847 | {0x0000b000, 0x00010000}, | ||
848 | {0x0000b004, 0x00030002}, | ||
849 | {0x0000b008, 0x00050004}, | ||
850 | {0x0000b00c, 0x00810080}, | ||
851 | {0x0000b010, 0x00830082}, | ||
852 | {0x0000b014, 0x01810180}, | ||
853 | {0x0000b018, 0x01830182}, | ||
854 | {0x0000b01c, 0x01850184}, | ||
855 | {0x0000b020, 0x02810280}, | ||
856 | {0x0000b024, 0x02830282}, | ||
857 | {0x0000b028, 0x02850284}, | ||
858 | {0x0000b02c, 0x02890288}, | ||
859 | {0x0000b030, 0x028b028a}, | ||
860 | {0x0000b034, 0x0388028c}, | ||
861 | {0x0000b038, 0x038a0389}, | ||
862 | {0x0000b03c, 0x038c038b}, | ||
863 | {0x0000b040, 0x0390038d}, | ||
864 | {0x0000b044, 0x03920391}, | ||
865 | {0x0000b048, 0x03940393}, | ||
866 | {0x0000b04c, 0x03960395}, | ||
867 | {0x0000b050, 0x00000000}, | ||
868 | {0x0000b054, 0x00000000}, | ||
869 | {0x0000b058, 0x00000000}, | ||
870 | {0x0000b05c, 0x00000000}, | ||
871 | {0x0000b060, 0x00000000}, | ||
872 | {0x0000b064, 0x00000000}, | ||
873 | {0x0000b068, 0x00000000}, | ||
874 | {0x0000b06c, 0x00000000}, | ||
875 | {0x0000b070, 0x00000000}, | ||
876 | {0x0000b074, 0x00000000}, | ||
877 | {0x0000b078, 0x00000000}, | ||
878 | {0x0000b07c, 0x00000000}, | ||
879 | {0x0000b080, 0x23232323}, | ||
880 | {0x0000b084, 0x21232323}, | ||
881 | {0x0000b088, 0x19191c1e}, | ||
882 | {0x0000b08c, 0x12141417}, | ||
883 | {0x0000b090, 0x07070e0e}, | ||
884 | {0x0000b094, 0x03030305}, | ||
885 | {0x0000b098, 0x00000003}, | ||
886 | {0x0000b09c, 0x00000000}, | ||
887 | {0x0000b0a0, 0x00000000}, | ||
888 | {0x0000b0a4, 0x00000000}, | ||
889 | {0x0000b0a8, 0x00000000}, | ||
890 | {0x0000b0ac, 0x00000000}, | ||
891 | {0x0000b0b0, 0x00000000}, | ||
892 | {0x0000b0b4, 0x00000000}, | ||
893 | {0x0000b0b8, 0x00000000}, | ||
894 | {0x0000b0bc, 0x00000000}, | ||
895 | {0x0000b0c0, 0x003f0020}, | ||
896 | {0x0000b0c4, 0x00400041}, | ||
897 | {0x0000b0c8, 0x0140005f}, | ||
898 | {0x0000b0cc, 0x0160015f}, | ||
899 | {0x0000b0d0, 0x017e017f}, | ||
900 | {0x0000b0d4, 0x02410242}, | ||
901 | {0x0000b0d8, 0x025f0240}, | ||
902 | {0x0000b0dc, 0x027f0260}, | ||
903 | {0x0000b0e0, 0x0341027e}, | ||
904 | {0x0000b0e4, 0x035f0340}, | ||
905 | {0x0000b0e8, 0x037f0360}, | ||
906 | {0x0000b0ec, 0x04400441}, | ||
907 | {0x0000b0f0, 0x0460045f}, | ||
908 | {0x0000b0f4, 0x0541047f}, | ||
909 | {0x0000b0f8, 0x055f0540}, | ||
910 | {0x0000b0fc, 0x057f0560}, | ||
911 | {0x0000b100, 0x06400641}, | ||
912 | {0x0000b104, 0x0660065f}, | ||
913 | {0x0000b108, 0x067e067f}, | ||
914 | {0x0000b10c, 0x07410742}, | ||
915 | {0x0000b110, 0x075f0740}, | ||
916 | {0x0000b114, 0x077f0760}, | ||
917 | {0x0000b118, 0x07800781}, | ||
918 | {0x0000b11c, 0x07a0079f}, | ||
919 | {0x0000b120, 0x07c107bf}, | ||
920 | {0x0000b124, 0x000007c0}, | ||
921 | {0x0000b128, 0x00000000}, | ||
922 | {0x0000b12c, 0x00000000}, | ||
923 | {0x0000b130, 0x00000000}, | ||
924 | {0x0000b134, 0x00000000}, | ||
925 | {0x0000b138, 0x00000000}, | ||
926 | {0x0000b13c, 0x00000000}, | ||
927 | {0x0000b140, 0x003f0020}, | ||
928 | {0x0000b144, 0x00400041}, | ||
929 | {0x0000b148, 0x0140005f}, | ||
930 | {0x0000b14c, 0x0160015f}, | ||
931 | {0x0000b150, 0x017e017f}, | ||
932 | {0x0000b154, 0x02410242}, | ||
933 | {0x0000b158, 0x025f0240}, | ||
934 | {0x0000b15c, 0x027f0260}, | ||
935 | {0x0000b160, 0x0341027e}, | ||
936 | {0x0000b164, 0x035f0340}, | ||
937 | {0x0000b168, 0x037f0360}, | ||
938 | {0x0000b16c, 0x04400441}, | ||
939 | {0x0000b170, 0x0460045f}, | ||
940 | {0x0000b174, 0x0541047f}, | ||
941 | {0x0000b178, 0x055f0540}, | ||
942 | {0x0000b17c, 0x057f0560}, | ||
943 | {0x0000b180, 0x06400641}, | ||
944 | {0x0000b184, 0x0660065f}, | ||
945 | {0x0000b188, 0x067e067f}, | ||
946 | {0x0000b18c, 0x07410742}, | ||
947 | {0x0000b190, 0x075f0740}, | ||
948 | {0x0000b194, 0x077f0760}, | ||
949 | {0x0000b198, 0x07800781}, | ||
950 | {0x0000b19c, 0x07a0079f}, | ||
951 | {0x0000b1a0, 0x07c107bf}, | ||
952 | {0x0000b1a4, 0x000007c0}, | ||
953 | {0x0000b1a8, 0x00000000}, | ||
954 | {0x0000b1ac, 0x00000000}, | ||
955 | {0x0000b1b0, 0x00000000}, | ||
956 | {0x0000b1b4, 0x00000000}, | ||
957 | {0x0000b1b8, 0x00000000}, | ||
958 | {0x0000b1bc, 0x00000000}, | ||
959 | {0x0000b1c0, 0x00000000}, | ||
960 | {0x0000b1c4, 0x00000000}, | ||
961 | {0x0000b1c8, 0x00000000}, | ||
962 | {0x0000b1cc, 0x00000000}, | ||
963 | {0x0000b1d0, 0x00000000}, | ||
964 | {0x0000b1d4, 0x00000000}, | ||
965 | {0x0000b1d8, 0x00000000}, | ||
966 | {0x0000b1dc, 0x00000000}, | ||
967 | {0x0000b1e0, 0x00000000}, | ||
968 | {0x0000b1e4, 0x00000000}, | ||
969 | {0x0000b1e8, 0x00000000}, | ||
970 | {0x0000b1ec, 0x00000000}, | ||
971 | {0x0000b1f0, 0x00000396}, | ||
972 | {0x0000b1f4, 0x00000396}, | ||
973 | {0x0000b1f8, 0x00000396}, | ||
974 | {0x0000b1fc, 0x00000196}, | ||
975 | }; | ||
976 | |||
977 | static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { | 723 | static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { |
978 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 724 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
979 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | 725 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
@@ -1437,8 +1183,6 @@ static const u32 ar9340_1p0_mac_core[][2] = { | |||
1437 | {0x000083d0, 0x000101ff}, | 1183 | {0x000083d0, 0x000101ff}, |
1438 | }; | 1184 | }; |
1439 | 1185 | ||
1440 | #define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
1441 | |||
1442 | static const u32 ar9340_1p0_soc_preamble[][2] = { | 1186 | static const u32 ar9340_1p0_soc_preamble[][2] = { |
1443 | /* Addr allmodes */ | 1187 | /* Addr allmodes */ |
1444 | {0x00007008, 0x00000000}, | 1188 | {0x00007008, 0x00000000}, |
@@ -1447,4 +1191,106 @@ static const u32 ar9340_1p0_soc_preamble[][2] = { | |||
1447 | {0x00007038, 0x000004c2}, | 1191 | {0x00007038, 0x000004c2}, |
1448 | }; | 1192 | }; |
1449 | 1193 | ||
1194 | static const u32 ar9340_cus227_tx_gain_table_1p0[][5] = { | ||
1195 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1196 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
1197 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
1198 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
1199 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1200 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
1201 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1202 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
1203 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
1204 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
1205 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
1206 | {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, | ||
1207 | {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, | ||
1208 | {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, | ||
1209 | {0x0000a520, 0x2c022220, 0x2c022220, 0x1b000603, 0x1b000603}, | ||
1210 | {0x0000a524, 0x30022222, 0x30022222, 0x1f000a02, 0x1f000a02}, | ||
1211 | {0x0000a528, 0x35022225, 0x35022225, 0x23000a04, 0x23000a04}, | ||
1212 | {0x0000a52c, 0x3b02222a, 0x3b02222a, 0x26000a20, 0x26000a20}, | ||
1213 | {0x0000a530, 0x3f02222c, 0x3f02222c, 0x2a000e20, 0x2a000e20}, | ||
1214 | {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, | ||
1215 | {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, | ||
1216 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, | ||
1217 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, | ||
1218 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, | ||
1219 | {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, | ||
1220 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, | ||
1221 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, | ||
1222 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, | ||
1223 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, | ||
1224 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, | ||
1225 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, | ||
1226 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1227 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1228 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1229 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1230 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1231 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1232 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, | ||
1233 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
1234 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
1235 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
1236 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
1237 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, | ||
1238 | {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, | ||
1239 | {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, | ||
1240 | {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, | ||
1241 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, | ||
1242 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, | ||
1243 | {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, | ||
1244 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, | ||
1245 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, | ||
1246 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, | ||
1247 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, | ||
1248 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, | ||
1249 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, | ||
1250 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, | ||
1251 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, | ||
1252 | {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, | ||
1253 | {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, | ||
1254 | {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, | ||
1255 | {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, | ||
1256 | {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, | ||
1257 | {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, | ||
1258 | {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1259 | {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1260 | {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1261 | {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1262 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1263 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1264 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1265 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1266 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1267 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1268 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1269 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1270 | {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, | ||
1271 | {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, | ||
1272 | {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, | ||
1273 | {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, | ||
1274 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | ||
1275 | {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, | ||
1276 | {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, | ||
1277 | {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1278 | {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1279 | {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1280 | {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1281 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
1282 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
1283 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
1284 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1285 | {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, | ||
1286 | {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, | ||
1287 | {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015}, | ||
1288 | {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000}, | ||
1289 | {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, | ||
1290 | {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, | ||
1291 | {0x0000a3a4, 0x00000011, 0x00000011, 0x00000011, 0x00000011}, | ||
1292 | {0x0000a3a8, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c}, | ||
1293 | {0x0000a3ac, 0x30303030, 0x30303030, 0x30303030, 0x30303030}, | ||
1294 | }; | ||
1295 | |||
1450 | #endif /* INITVALS_9340_H */ | 1296 | #endif /* INITVALS_9340_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 092b9d412e7f..739094384369 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | /* AR9462 2.0 */ | 21 | /* AR9462 2.0 */ |
22 | 22 | ||
23 | static const u32 ar9462_modes_fast_clock_2p0[][3] = { | 23 | static const u32 ar9462_2p0_modes_fast_clock[][3] = { |
24 | /* Addr 5G_HT20 5G_HT40 */ | 24 | /* Addr 5G_HT20 5G_HT40 */ |
25 | {0x00001030, 0x00000268, 0x000004d0}, | 25 | {0x00001030, 0x00000268, 0x000004d0}, |
26 | {0x00001070, 0x0000018c, 0x00000318}, | 26 | {0x00001070, 0x0000018c, 0x00000318}, |
@@ -33,13 +33,6 @@ static const u32 ar9462_modes_fast_clock_2p0[][3] = { | |||
33 | {0x0000a254, 0x00000898, 0x00001130}, | 33 | {0x0000a254, 0x00000898, 0x00001130}, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { | ||
37 | /* Addr allmodes */ | ||
38 | {0x00018c00, 0x18253ede}, | ||
39 | {0x00018c04, 0x000801d8}, | ||
40 | {0x00018c08, 0x0003780c}, | ||
41 | }; | ||
42 | |||
43 | static const u32 ar9462_2p0_baseband_postamble[][5] = { | 36 | static const u32 ar9462_2p0_baseband_postamble[][5] = { |
44 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 37 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
45 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, | 38 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, |
@@ -99,7 +92,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
99 | {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, | 92 | {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, |
100 | }; | 93 | }; |
101 | 94 | ||
102 | static const u32 ar9462_common_rx_gain_table_2p0[][2] = { | 95 | static const u32 ar9462_2p0_common_rx_gain[][2] = { |
103 | /* Addr allmodes */ | 96 | /* Addr allmodes */ |
104 | {0x0000a000, 0x00010000}, | 97 | {0x0000a000, 0x00010000}, |
105 | {0x0000a004, 0x00030002}, | 98 | {0x0000a004, 0x00030002}, |
@@ -359,20 +352,13 @@ static const u32 ar9462_common_rx_gain_table_2p0[][2] = { | |||
359 | {0x0000b1fc, 0x00000196}, | 352 | {0x0000b1fc, 0x00000196}, |
360 | }; | 353 | }; |
361 | 354 | ||
362 | static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { | 355 | static const u32 ar9462_2p0_pciephy_clkreq_disable_L1[][2] = { |
363 | /* Addr allmodes */ | 356 | /* Addr allmodes */ |
364 | {0x00018c00, 0x18213ede}, | 357 | {0x00018c00, 0x18213ede}, |
365 | {0x00018c04, 0x000801d8}, | 358 | {0x00018c04, 0x000801d8}, |
366 | {0x00018c08, 0x0003780c}, | 359 | {0x00018c08, 0x0003780c}, |
367 | }; | 360 | }; |
368 | 361 | ||
369 | static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { | ||
370 | /* Addr allmodes */ | ||
371 | {0x00018c00, 0x18212ede}, | ||
372 | {0x00018c04, 0x000801d8}, | ||
373 | {0x00018c08, 0x0003780c}, | ||
374 | }; | ||
375 | |||
376 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { | 362 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { |
377 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 363 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
378 | {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, | 364 | {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, |
@@ -380,7 +366,7 @@ static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { | |||
380 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | 366 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, |
381 | }; | 367 | }; |
382 | 368 | ||
383 | static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = { | 369 | static const u32 ar9462_2p0_common_wo_xlna_rx_gain[][2] = { |
384 | /* Addr allmodes */ | 370 | /* Addr allmodes */ |
385 | {0x0000a000, 0x00010000}, | 371 | {0x0000a000, 0x00010000}, |
386 | {0x0000a004, 0x00030002}, | 372 | {0x0000a004, 0x00030002}, |
@@ -647,7 +633,7 @@ static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = { | |||
647 | {0x0000a3a0, 0xca9228ee}, | 633 | {0x0000a3a0, 0xca9228ee}, |
648 | }; | 634 | }; |
649 | 635 | ||
650 | static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = { | 636 | static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][5] = { |
651 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 637 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
652 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | 638 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, |
653 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | 639 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
@@ -879,7 +865,7 @@ static const u32 ar9462_2p0_radio_postamble[][5] = { | |||
879 | {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, | 865 | {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, |
880 | }; | 866 | }; |
881 | 867 | ||
882 | static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = { | 868 | static const u32 ar9462_2p0_modes_mix_ob_db_tx_gain[][5] = { |
883 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 869 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
884 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | 870 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, |
885 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | 871 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, |
@@ -942,7 +928,7 @@ static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = { | |||
942 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 928 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
943 | }; | 929 | }; |
944 | 930 | ||
945 | static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { | 931 | static const u32 ar9462_2p0_modes_high_ob_db_tx_gain[][5] = { |
946 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 932 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
947 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | 933 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, |
948 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | 934 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, |
@@ -1252,7 +1238,7 @@ static const u32 ar9462_2p0_mac_postamble[][5] = { | |||
1252 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | 1238 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, |
1253 | }; | 1239 | }; |
1254 | 1240 | ||
1255 | static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = { | 1241 | static const u32 ar9462_2p0_common_mixed_rx_gain[][2] = { |
1256 | /* Addr allmodes */ | 1242 | /* Addr allmodes */ |
1257 | {0x0000a000, 0x00010000}, | 1243 | {0x0000a000, 0x00010000}, |
1258 | {0x0000a004, 0x00030002}, | 1244 | {0x0000a004, 0x00030002}, |
@@ -1517,7 +1503,7 @@ static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = { | |||
1517 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, | 1503 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, |
1518 | }; | 1504 | }; |
1519 | 1505 | ||
1520 | static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = { | 1506 | static const u32 ar9462_2p0_common_5g_xlna_only_rxgain[][2] = { |
1521 | /* Addr allmodes */ | 1507 | /* Addr allmodes */ |
1522 | {0x0000a000, 0x00010000}, | 1508 | {0x0000a000, 0x00010000}, |
1523 | {0x0000a004, 0x00030002}, | 1509 | {0x0000a004, 0x00030002}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h index 57fc5f459d0a..dc3adda46e8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h | |||
@@ -20,6 +20,44 @@ | |||
20 | 20 | ||
21 | /* AR9462 2.1 */ | 21 | /* AR9462 2.1 */ |
22 | 22 | ||
23 | #define ar9462_2p1_mac_postamble ar9462_2p0_mac_postamble | ||
24 | |||
25 | #define ar9462_2p1_baseband_core ar9462_2p0_baseband_core | ||
26 | |||
27 | #define ar9462_2p1_radio_core ar9462_2p0_radio_core | ||
28 | |||
29 | #define ar9462_2p1_radio_postamble ar9462_2p0_radio_postamble | ||
30 | |||
31 | #define ar9462_2p1_soc_postamble ar9462_2p0_soc_postamble | ||
32 | |||
33 | #define ar9462_2p1_radio_postamble_sys2ant ar9462_2p0_radio_postamble_sys2ant | ||
34 | |||
35 | #define ar9462_2p1_common_rx_gain ar9462_2p0_common_rx_gain | ||
36 | |||
37 | #define ar9462_2p1_common_mixed_rx_gain ar9462_2p0_common_mixed_rx_gain | ||
38 | |||
39 | #define ar9462_2p1_common_5g_xlna_only_rxgain ar9462_2p0_common_5g_xlna_only_rxgain | ||
40 | |||
41 | #define ar9462_2p1_baseband_core_mix_rxgain ar9462_2p0_baseband_core_mix_rxgain | ||
42 | |||
43 | #define ar9462_2p1_baseband_postamble_mix_rxgain ar9462_2p0_baseband_postamble_mix_rxgain | ||
44 | |||
45 | #define ar9462_2p1_baseband_postamble_5g_xlna ar9462_2p0_baseband_postamble_5g_xlna | ||
46 | |||
47 | #define ar9462_2p1_common_wo_xlna_rx_gain ar9462_2p0_common_wo_xlna_rx_gain | ||
48 | |||
49 | #define ar9462_2p1_modes_low_ob_db_tx_gain ar9462_2p0_modes_low_ob_db_tx_gain | ||
50 | |||
51 | #define ar9462_2p1_modes_high_ob_db_tx_gain ar9462_2p0_modes_high_ob_db_tx_gain | ||
52 | |||
53 | #define ar9462_2p1_modes_mix_ob_db_tx_gain ar9462_2p0_modes_mix_ob_db_tx_gain | ||
54 | |||
55 | #define ar9462_2p1_modes_fast_clock ar9462_2p0_modes_fast_clock | ||
56 | |||
57 | #define ar9462_2p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 | ||
58 | |||
59 | #define ar9462_2p1_pciephy_clkreq_disable_L1 ar9462_2p0_pciephy_clkreq_disable_L1 | ||
60 | |||
23 | static const u32 ar9462_2p1_mac_core[][2] = { | 61 | static const u32 ar9462_2p1_mac_core[][2] = { |
24 | /* Addr allmodes */ | 62 | /* Addr allmodes */ |
25 | {0x00000008, 0x00000000}, | 63 | {0x00000008, 0x00000000}, |
@@ -183,168 +221,6 @@ static const u32 ar9462_2p1_mac_core[][2] = { | |||
183 | {0x000083d0, 0x000301ff}, | 221 | {0x000083d0, 0x000301ff}, |
184 | }; | 222 | }; |
185 | 223 | ||
186 | static const u32 ar9462_2p1_mac_postamble[][5] = { | ||
187 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
188 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, | ||
189 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, | ||
190 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, | ||
191 | {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, | ||
192 | {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, | ||
193 | {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, | ||
194 | {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, | ||
195 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | ||
196 | }; | ||
197 | |||
198 | static const u32 ar9462_2p1_baseband_core[][2] = { | ||
199 | /* Addr allmodes */ | ||
200 | {0x00009800, 0xafe68e30}, | ||
201 | {0x00009804, 0xfd14e000}, | ||
202 | {0x00009808, 0x9c0a9f6b}, | ||
203 | {0x0000980c, 0x04900000}, | ||
204 | {0x00009814, 0x9280c00a}, | ||
205 | {0x00009818, 0x00000000}, | ||
206 | {0x0000981c, 0x00020028}, | ||
207 | {0x00009834, 0x6400a290}, | ||
208 | {0x00009838, 0x0108ecff}, | ||
209 | {0x0000983c, 0x0d000600}, | ||
210 | {0x00009880, 0x201fff00}, | ||
211 | {0x00009884, 0x00001042}, | ||
212 | {0x000098a4, 0x00200400}, | ||
213 | {0x000098b0, 0x32440bbe}, | ||
214 | {0x000098d0, 0x004b6a8e}, | ||
215 | {0x000098d4, 0x00000820}, | ||
216 | {0x000098dc, 0x00000000}, | ||
217 | {0x000098e4, 0x01ffffff}, | ||
218 | {0x000098e8, 0x01ffffff}, | ||
219 | {0x000098ec, 0x01ffffff}, | ||
220 | {0x000098f0, 0x00000000}, | ||
221 | {0x000098f4, 0x00000000}, | ||
222 | {0x00009bf0, 0x80000000}, | ||
223 | {0x00009c04, 0xff55ff55}, | ||
224 | {0x00009c08, 0x0320ff55}, | ||
225 | {0x00009c0c, 0x00000000}, | ||
226 | {0x00009c10, 0x00000000}, | ||
227 | {0x00009c14, 0x00046384}, | ||
228 | {0x00009c18, 0x05b6b440}, | ||
229 | {0x00009c1c, 0x00b6b440}, | ||
230 | {0x00009d00, 0xc080a333}, | ||
231 | {0x00009d04, 0x40206c10}, | ||
232 | {0x00009d08, 0x009c4060}, | ||
233 | {0x00009d0c, 0x9883800a}, | ||
234 | {0x00009d10, 0x01834061}, | ||
235 | {0x00009d14, 0x00c0040b}, | ||
236 | {0x00009d18, 0x00000000}, | ||
237 | {0x00009e08, 0x0038230c}, | ||
238 | {0x00009e24, 0x990bb515}, | ||
239 | {0x00009e28, 0x0c6f0000}, | ||
240 | {0x00009e30, 0x06336f77}, | ||
241 | {0x00009e34, 0x6af6532f}, | ||
242 | {0x00009e38, 0x0cc80c00}, | ||
243 | {0x00009e40, 0x15262820}, | ||
244 | {0x00009e4c, 0x00001004}, | ||
245 | {0x00009e50, 0x00ff03f1}, | ||
246 | {0x00009e54, 0xe4c555c2}, | ||
247 | {0x00009e58, 0xfd857722}, | ||
248 | {0x00009e5c, 0xe9198724}, | ||
249 | {0x00009fc0, 0x803e4788}, | ||
250 | {0x00009fc4, 0x0001efb5}, | ||
251 | {0x00009fcc, 0x40000014}, | ||
252 | {0x00009fd0, 0x0a193b93}, | ||
253 | {0x0000a20c, 0x00000000}, | ||
254 | {0x0000a220, 0x00000000}, | ||
255 | {0x0000a224, 0x00000000}, | ||
256 | {0x0000a228, 0x10002310}, | ||
257 | {0x0000a23c, 0x00000000}, | ||
258 | {0x0000a244, 0x0c000000}, | ||
259 | {0x0000a2a0, 0x00000001}, | ||
260 | {0x0000a2c0, 0x00000001}, | ||
261 | {0x0000a2c8, 0x00000000}, | ||
262 | {0x0000a2cc, 0x18c43433}, | ||
263 | {0x0000a2d4, 0x00000000}, | ||
264 | {0x0000a2ec, 0x00000000}, | ||
265 | {0x0000a2f0, 0x00000000}, | ||
266 | {0x0000a2f4, 0x00000000}, | ||
267 | {0x0000a2f8, 0x00000000}, | ||
268 | {0x0000a344, 0x00000000}, | ||
269 | {0x0000a34c, 0x00000000}, | ||
270 | {0x0000a350, 0x0000a000}, | ||
271 | {0x0000a364, 0x00000000}, | ||
272 | {0x0000a370, 0x00000000}, | ||
273 | {0x0000a390, 0x00000001}, | ||
274 | {0x0000a394, 0x00000444}, | ||
275 | {0x0000a398, 0x001f0e0f}, | ||
276 | {0x0000a39c, 0x0075393f}, | ||
277 | {0x0000a3a0, 0xb79f6427}, | ||
278 | {0x0000a3c0, 0x20202020}, | ||
279 | {0x0000a3c4, 0x22222220}, | ||
280 | {0x0000a3c8, 0x20200020}, | ||
281 | {0x0000a3cc, 0x20202020}, | ||
282 | {0x0000a3d0, 0x20202020}, | ||
283 | {0x0000a3d4, 0x20202020}, | ||
284 | {0x0000a3d8, 0x20202020}, | ||
285 | {0x0000a3dc, 0x20202020}, | ||
286 | {0x0000a3e0, 0x20202020}, | ||
287 | {0x0000a3e4, 0x20202020}, | ||
288 | {0x0000a3e8, 0x20202020}, | ||
289 | {0x0000a3ec, 0x20202020}, | ||
290 | {0x0000a3f0, 0x00000000}, | ||
291 | {0x0000a3f4, 0x00000006}, | ||
292 | {0x0000a3f8, 0x0c9bd380}, | ||
293 | {0x0000a3fc, 0x000f0f01}, | ||
294 | {0x0000a400, 0x8fa91f01}, | ||
295 | {0x0000a404, 0x00000000}, | ||
296 | {0x0000a408, 0x0e79e5c6}, | ||
297 | {0x0000a40c, 0x00820820}, | ||
298 | {0x0000a414, 0x1ce739ce}, | ||
299 | {0x0000a418, 0x2d001dce}, | ||
300 | {0x0000a434, 0x00000000}, | ||
301 | {0x0000a438, 0x00001801}, | ||
302 | {0x0000a43c, 0x00100000}, | ||
303 | {0x0000a444, 0x00000000}, | ||
304 | {0x0000a448, 0x05000080}, | ||
305 | {0x0000a44c, 0x00000001}, | ||
306 | {0x0000a450, 0x00010000}, | ||
307 | {0x0000a454, 0x07000000}, | ||
308 | {0x0000a644, 0xbfad9d74}, | ||
309 | {0x0000a648, 0x0048060a}, | ||
310 | {0x0000a64c, 0x00002037}, | ||
311 | {0x0000a670, 0x03020100}, | ||
312 | {0x0000a674, 0x09080504}, | ||
313 | {0x0000a678, 0x0d0c0b0a}, | ||
314 | {0x0000a67c, 0x13121110}, | ||
315 | {0x0000a680, 0x31301514}, | ||
316 | {0x0000a684, 0x35343332}, | ||
317 | {0x0000a688, 0x00000036}, | ||
318 | {0x0000a690, 0x00000838}, | ||
319 | {0x0000a6b0, 0x0000000a}, | ||
320 | {0x0000a6b4, 0x00512c01}, | ||
321 | {0x0000a7c0, 0x00000000}, | ||
322 | {0x0000a7c4, 0xfffffffc}, | ||
323 | {0x0000a7c8, 0x00000000}, | ||
324 | {0x0000a7cc, 0x00000000}, | ||
325 | {0x0000a7d0, 0x00000000}, | ||
326 | {0x0000a7d4, 0x00000004}, | ||
327 | {0x0000a7dc, 0x00000000}, | ||
328 | {0x0000a7f0, 0x80000000}, | ||
329 | {0x0000a8d0, 0x004b6a8e}, | ||
330 | {0x0000a8d4, 0x00000820}, | ||
331 | {0x0000a8dc, 0x00000000}, | ||
332 | {0x0000a8f0, 0x00000000}, | ||
333 | {0x0000a8f4, 0x00000000}, | ||
334 | {0x0000abf0, 0x80000000}, | ||
335 | {0x0000b2d0, 0x00000080}, | ||
336 | {0x0000b2d4, 0x00000000}, | ||
337 | {0x0000b2ec, 0x00000000}, | ||
338 | {0x0000b2f0, 0x00000000}, | ||
339 | {0x0000b2f4, 0x00000000}, | ||
340 | {0x0000b2f8, 0x00000000}, | ||
341 | {0x0000b408, 0x0e79e5c0}, | ||
342 | {0x0000b40c, 0x00820820}, | ||
343 | {0x0000b420, 0x00000000}, | ||
344 | {0x0000b6b0, 0x0000000a}, | ||
345 | {0x0000b6b4, 0x00000001}, | ||
346 | }; | ||
347 | |||
348 | static const u32 ar9462_2p1_baseband_postamble[][5] = { | 224 | static const u32 ar9462_2p1_baseband_postamble[][5] = { |
349 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 225 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
350 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, | 226 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, |
@@ -404,72 +280,6 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { | |||
404 | {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, | 280 | {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, |
405 | }; | 281 | }; |
406 | 282 | ||
407 | static const u32 ar9462_2p1_radio_core[][2] = { | ||
408 | /* Addr allmodes */ | ||
409 | {0x00016000, 0x36db6db6}, | ||
410 | {0x00016004, 0x6db6db40}, | ||
411 | {0x00016008, 0x73f00000}, | ||
412 | {0x0001600c, 0x00000000}, | ||
413 | {0x00016010, 0x6d820001}, | ||
414 | {0x00016040, 0x7f80fff8}, | ||
415 | {0x0001604c, 0x2699e04f}, | ||
416 | {0x00016050, 0x6db6db6c}, | ||
417 | {0x00016058, 0x6c200000}, | ||
418 | {0x00016080, 0x000c0000}, | ||
419 | {0x00016084, 0x9a68048c}, | ||
420 | {0x00016088, 0x54214514}, | ||
421 | {0x0001608c, 0x1203040b}, | ||
422 | {0x00016090, 0x24926490}, | ||
423 | {0x00016098, 0xd2888888}, | ||
424 | {0x000160a0, 0x0a108ffe}, | ||
425 | {0x000160a4, 0x812fc491}, | ||
426 | {0x000160a8, 0x423c8000}, | ||
427 | {0x000160b4, 0x92000000}, | ||
428 | {0x000160b8, 0x0285dddc}, | ||
429 | {0x000160bc, 0x02908888}, | ||
430 | {0x000160c0, 0x00adb6d0}, | ||
431 | {0x000160c4, 0x6db6db60}, | ||
432 | {0x000160c8, 0x6db6db6c}, | ||
433 | {0x000160cc, 0x0de6c1b0}, | ||
434 | {0x00016100, 0x3fffbe04}, | ||
435 | {0x00016104, 0xfff80000}, | ||
436 | {0x00016108, 0x00200400}, | ||
437 | {0x00016110, 0x00000000}, | ||
438 | {0x00016144, 0x02084080}, | ||
439 | {0x00016148, 0x000080c0}, | ||
440 | {0x00016280, 0x050a0001}, | ||
441 | {0x00016284, 0x3d841418}, | ||
442 | {0x00016288, 0x00000000}, | ||
443 | {0x0001628c, 0xe3000000}, | ||
444 | {0x00016290, 0xa1005080}, | ||
445 | {0x00016294, 0x00000020}, | ||
446 | {0x00016298, 0x54a82900}, | ||
447 | {0x00016340, 0x121e4276}, | ||
448 | {0x00016344, 0x00300000}, | ||
449 | {0x00016400, 0x36db6db6}, | ||
450 | {0x00016404, 0x6db6db40}, | ||
451 | {0x00016408, 0x73f00000}, | ||
452 | {0x0001640c, 0x00000000}, | ||
453 | {0x00016410, 0x6c800001}, | ||
454 | {0x00016440, 0x7f80fff8}, | ||
455 | {0x0001644c, 0x4699e04f}, | ||
456 | {0x00016450, 0x6db6db6c}, | ||
457 | {0x00016500, 0x3fffbe04}, | ||
458 | {0x00016504, 0xfff80000}, | ||
459 | {0x00016508, 0x00200400}, | ||
460 | {0x00016510, 0x00000000}, | ||
461 | {0x00016544, 0x02084080}, | ||
462 | {0x00016548, 0x000080c0}, | ||
463 | }; | ||
464 | |||
465 | static const u32 ar9462_2p1_radio_postamble[][5] = { | ||
466 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
467 | {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524}, | ||
468 | {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70}, | ||
469 | {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, | ||
470 | {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, | ||
471 | }; | ||
472 | |||
473 | static const u32 ar9462_2p1_soc_preamble[][2] = { | 283 | static const u32 ar9462_2p1_soc_preamble[][2] = { |
474 | /* Addr allmodes */ | 284 | /* Addr allmodes */ |
475 | {0x000040a4, 0x00a0c9c9}, | 285 | {0x000040a4, 0x00a0c9c9}, |
@@ -478,1297 +288,4 @@ static const u32 ar9462_2p1_soc_preamble[][2] = { | |||
478 | {0x00007038, 0x000004c2}, | 288 | {0x00007038, 0x000004c2}, |
479 | }; | 289 | }; |
480 | 290 | ||
481 | static const u32 ar9462_2p1_soc_postamble[][5] = { | ||
482 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
483 | {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033}, | ||
484 | }; | ||
485 | |||
486 | static const u32 ar9462_2p1_radio_postamble_sys2ant[][5] = { | ||
487 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
488 | {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, | ||
489 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
490 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
491 | }; | ||
492 | |||
493 | static const u32 ar9462_2p1_common_rx_gain[][2] = { | ||
494 | /* Addr allmodes */ | ||
495 | {0x0000a000, 0x00010000}, | ||
496 | {0x0000a004, 0x00030002}, | ||
497 | {0x0000a008, 0x00050004}, | ||
498 | {0x0000a00c, 0x00810080}, | ||
499 | {0x0000a010, 0x00830082}, | ||
500 | {0x0000a014, 0x01810180}, | ||
501 | {0x0000a018, 0x01830182}, | ||
502 | {0x0000a01c, 0x01850184}, | ||
503 | {0x0000a020, 0x01890188}, | ||
504 | {0x0000a024, 0x018b018a}, | ||
505 | {0x0000a028, 0x018d018c}, | ||
506 | {0x0000a02c, 0x01910190}, | ||
507 | {0x0000a030, 0x01930192}, | ||
508 | {0x0000a034, 0x01950194}, | ||
509 | {0x0000a038, 0x038a0196}, | ||
510 | {0x0000a03c, 0x038c038b}, | ||
511 | {0x0000a040, 0x0390038d}, | ||
512 | {0x0000a044, 0x03920391}, | ||
513 | {0x0000a048, 0x03940393}, | ||
514 | {0x0000a04c, 0x03960395}, | ||
515 | {0x0000a050, 0x00000000}, | ||
516 | {0x0000a054, 0x00000000}, | ||
517 | {0x0000a058, 0x00000000}, | ||
518 | {0x0000a05c, 0x00000000}, | ||
519 | {0x0000a060, 0x00000000}, | ||
520 | {0x0000a064, 0x00000000}, | ||
521 | {0x0000a068, 0x00000000}, | ||
522 | {0x0000a06c, 0x00000000}, | ||
523 | {0x0000a070, 0x00000000}, | ||
524 | {0x0000a074, 0x00000000}, | ||
525 | {0x0000a078, 0x00000000}, | ||
526 | {0x0000a07c, 0x00000000}, | ||
527 | {0x0000a080, 0x22222229}, | ||
528 | {0x0000a084, 0x1d1d1d1d}, | ||
529 | {0x0000a088, 0x1d1d1d1d}, | ||
530 | {0x0000a08c, 0x1d1d1d1d}, | ||
531 | {0x0000a090, 0x171d1d1d}, | ||
532 | {0x0000a094, 0x11111717}, | ||
533 | {0x0000a098, 0x00030311}, | ||
534 | {0x0000a09c, 0x00000000}, | ||
535 | {0x0000a0a0, 0x00000000}, | ||
536 | {0x0000a0a4, 0x00000000}, | ||
537 | {0x0000a0a8, 0x00000000}, | ||
538 | {0x0000a0ac, 0x00000000}, | ||
539 | {0x0000a0b0, 0x00000000}, | ||
540 | {0x0000a0b4, 0x00000000}, | ||
541 | {0x0000a0b8, 0x00000000}, | ||
542 | {0x0000a0bc, 0x00000000}, | ||
543 | {0x0000a0c0, 0x001f0000}, | ||
544 | {0x0000a0c4, 0x01000101}, | ||
545 | {0x0000a0c8, 0x011e011f}, | ||
546 | {0x0000a0cc, 0x011c011d}, | ||
547 | {0x0000a0d0, 0x02030204}, | ||
548 | {0x0000a0d4, 0x02010202}, | ||
549 | {0x0000a0d8, 0x021f0200}, | ||
550 | {0x0000a0dc, 0x0302021e}, | ||
551 | {0x0000a0e0, 0x03000301}, | ||
552 | {0x0000a0e4, 0x031e031f}, | ||
553 | {0x0000a0e8, 0x0402031d}, | ||
554 | {0x0000a0ec, 0x04000401}, | ||
555 | {0x0000a0f0, 0x041e041f}, | ||
556 | {0x0000a0f4, 0x0502041d}, | ||
557 | {0x0000a0f8, 0x05000501}, | ||
558 | {0x0000a0fc, 0x051e051f}, | ||
559 | {0x0000a100, 0x06010602}, | ||
560 | {0x0000a104, 0x061f0600}, | ||
561 | {0x0000a108, 0x061d061e}, | ||
562 | {0x0000a10c, 0x07020703}, | ||
563 | {0x0000a110, 0x07000701}, | ||
564 | {0x0000a114, 0x00000000}, | ||
565 | {0x0000a118, 0x00000000}, | ||
566 | {0x0000a11c, 0x00000000}, | ||
567 | {0x0000a120, 0x00000000}, | ||
568 | {0x0000a124, 0x00000000}, | ||
569 | {0x0000a128, 0x00000000}, | ||
570 | {0x0000a12c, 0x00000000}, | ||
571 | {0x0000a130, 0x00000000}, | ||
572 | {0x0000a134, 0x00000000}, | ||
573 | {0x0000a138, 0x00000000}, | ||
574 | {0x0000a13c, 0x00000000}, | ||
575 | {0x0000a140, 0x001f0000}, | ||
576 | {0x0000a144, 0x01000101}, | ||
577 | {0x0000a148, 0x011e011f}, | ||
578 | {0x0000a14c, 0x011c011d}, | ||
579 | {0x0000a150, 0x02030204}, | ||
580 | {0x0000a154, 0x02010202}, | ||
581 | {0x0000a158, 0x021f0200}, | ||
582 | {0x0000a15c, 0x0302021e}, | ||
583 | {0x0000a160, 0x03000301}, | ||
584 | {0x0000a164, 0x031e031f}, | ||
585 | {0x0000a168, 0x0402031d}, | ||
586 | {0x0000a16c, 0x04000401}, | ||
587 | {0x0000a170, 0x041e041f}, | ||
588 | {0x0000a174, 0x0502041d}, | ||
589 | {0x0000a178, 0x05000501}, | ||
590 | {0x0000a17c, 0x051e051f}, | ||
591 | {0x0000a180, 0x06010602}, | ||
592 | {0x0000a184, 0x061f0600}, | ||
593 | {0x0000a188, 0x061d061e}, | ||
594 | {0x0000a18c, 0x07020703}, | ||
595 | {0x0000a190, 0x07000701}, | ||
596 | {0x0000a194, 0x00000000}, | ||
597 | {0x0000a198, 0x00000000}, | ||
598 | {0x0000a19c, 0x00000000}, | ||
599 | {0x0000a1a0, 0x00000000}, | ||
600 | {0x0000a1a4, 0x00000000}, | ||
601 | {0x0000a1a8, 0x00000000}, | ||
602 | {0x0000a1ac, 0x00000000}, | ||
603 | {0x0000a1b0, 0x00000000}, | ||
604 | {0x0000a1b4, 0x00000000}, | ||
605 | {0x0000a1b8, 0x00000000}, | ||
606 | {0x0000a1bc, 0x00000000}, | ||
607 | {0x0000a1c0, 0x00000000}, | ||
608 | {0x0000a1c4, 0x00000000}, | ||
609 | {0x0000a1c8, 0x00000000}, | ||
610 | {0x0000a1cc, 0x00000000}, | ||
611 | {0x0000a1d0, 0x00000000}, | ||
612 | {0x0000a1d4, 0x00000000}, | ||
613 | {0x0000a1d8, 0x00000000}, | ||
614 | {0x0000a1dc, 0x00000000}, | ||
615 | {0x0000a1e0, 0x00000000}, | ||
616 | {0x0000a1e4, 0x00000000}, | ||
617 | {0x0000a1e8, 0x00000000}, | ||
618 | {0x0000a1ec, 0x00000000}, | ||
619 | {0x0000a1f0, 0x00000396}, | ||
620 | {0x0000a1f4, 0x00000396}, | ||
621 | {0x0000a1f8, 0x00000396}, | ||
622 | {0x0000a1fc, 0x00000196}, | ||
623 | {0x0000b000, 0x00010000}, | ||
624 | {0x0000b004, 0x00030002}, | ||
625 | {0x0000b008, 0x00050004}, | ||
626 | {0x0000b00c, 0x00810080}, | ||
627 | {0x0000b010, 0x00830082}, | ||
628 | {0x0000b014, 0x01810180}, | ||
629 | {0x0000b018, 0x01830182}, | ||
630 | {0x0000b01c, 0x01850184}, | ||
631 | {0x0000b020, 0x02810280}, | ||
632 | {0x0000b024, 0x02830282}, | ||
633 | {0x0000b028, 0x02850284}, | ||
634 | {0x0000b02c, 0x02890288}, | ||
635 | {0x0000b030, 0x028b028a}, | ||
636 | {0x0000b034, 0x0388028c}, | ||
637 | {0x0000b038, 0x038a0389}, | ||
638 | {0x0000b03c, 0x038c038b}, | ||
639 | {0x0000b040, 0x0390038d}, | ||
640 | {0x0000b044, 0x03920391}, | ||
641 | {0x0000b048, 0x03940393}, | ||
642 | {0x0000b04c, 0x03960395}, | ||
643 | {0x0000b050, 0x00000000}, | ||
644 | {0x0000b054, 0x00000000}, | ||
645 | {0x0000b058, 0x00000000}, | ||
646 | {0x0000b05c, 0x00000000}, | ||
647 | {0x0000b060, 0x00000000}, | ||
648 | {0x0000b064, 0x00000000}, | ||
649 | {0x0000b068, 0x00000000}, | ||
650 | {0x0000b06c, 0x00000000}, | ||
651 | {0x0000b070, 0x00000000}, | ||
652 | {0x0000b074, 0x00000000}, | ||
653 | {0x0000b078, 0x00000000}, | ||
654 | {0x0000b07c, 0x00000000}, | ||
655 | {0x0000b080, 0x2a2d2f32}, | ||
656 | {0x0000b084, 0x21232328}, | ||
657 | {0x0000b088, 0x19191c1e}, | ||
658 | {0x0000b08c, 0x12141417}, | ||
659 | {0x0000b090, 0x07070e0e}, | ||
660 | {0x0000b094, 0x03030305}, | ||
661 | {0x0000b098, 0x00000003}, | ||
662 | {0x0000b09c, 0x00000000}, | ||
663 | {0x0000b0a0, 0x00000000}, | ||
664 | {0x0000b0a4, 0x00000000}, | ||
665 | {0x0000b0a8, 0x00000000}, | ||
666 | {0x0000b0ac, 0x00000000}, | ||
667 | {0x0000b0b0, 0x00000000}, | ||
668 | {0x0000b0b4, 0x00000000}, | ||
669 | {0x0000b0b8, 0x00000000}, | ||
670 | {0x0000b0bc, 0x00000000}, | ||
671 | {0x0000b0c0, 0x003f0020}, | ||
672 | {0x0000b0c4, 0x00400041}, | ||
673 | {0x0000b0c8, 0x0140005f}, | ||
674 | {0x0000b0cc, 0x0160015f}, | ||
675 | {0x0000b0d0, 0x017e017f}, | ||
676 | {0x0000b0d4, 0x02410242}, | ||
677 | {0x0000b0d8, 0x025f0240}, | ||
678 | {0x0000b0dc, 0x027f0260}, | ||
679 | {0x0000b0e0, 0x0341027e}, | ||
680 | {0x0000b0e4, 0x035f0340}, | ||
681 | {0x0000b0e8, 0x037f0360}, | ||
682 | {0x0000b0ec, 0x04400441}, | ||
683 | {0x0000b0f0, 0x0460045f}, | ||
684 | {0x0000b0f4, 0x0541047f}, | ||
685 | {0x0000b0f8, 0x055f0540}, | ||
686 | {0x0000b0fc, 0x057f0560}, | ||
687 | {0x0000b100, 0x06400641}, | ||
688 | {0x0000b104, 0x0660065f}, | ||
689 | {0x0000b108, 0x067e067f}, | ||
690 | {0x0000b10c, 0x07410742}, | ||
691 | {0x0000b110, 0x075f0740}, | ||
692 | {0x0000b114, 0x077f0760}, | ||
693 | {0x0000b118, 0x07800781}, | ||
694 | {0x0000b11c, 0x07a0079f}, | ||
695 | {0x0000b120, 0x07c107bf}, | ||
696 | {0x0000b124, 0x000007c0}, | ||
697 | {0x0000b128, 0x00000000}, | ||
698 | {0x0000b12c, 0x00000000}, | ||
699 | {0x0000b130, 0x00000000}, | ||
700 | {0x0000b134, 0x00000000}, | ||
701 | {0x0000b138, 0x00000000}, | ||
702 | {0x0000b13c, 0x00000000}, | ||
703 | {0x0000b140, 0x003f0020}, | ||
704 | {0x0000b144, 0x00400041}, | ||
705 | {0x0000b148, 0x0140005f}, | ||
706 | {0x0000b14c, 0x0160015f}, | ||
707 | {0x0000b150, 0x017e017f}, | ||
708 | {0x0000b154, 0x02410242}, | ||
709 | {0x0000b158, 0x025f0240}, | ||
710 | {0x0000b15c, 0x027f0260}, | ||
711 | {0x0000b160, 0x0341027e}, | ||
712 | {0x0000b164, 0x035f0340}, | ||
713 | {0x0000b168, 0x037f0360}, | ||
714 | {0x0000b16c, 0x04400441}, | ||
715 | {0x0000b170, 0x0460045f}, | ||
716 | {0x0000b174, 0x0541047f}, | ||
717 | {0x0000b178, 0x055f0540}, | ||
718 | {0x0000b17c, 0x057f0560}, | ||
719 | {0x0000b180, 0x06400641}, | ||
720 | {0x0000b184, 0x0660065f}, | ||
721 | {0x0000b188, 0x067e067f}, | ||
722 | {0x0000b18c, 0x07410742}, | ||
723 | {0x0000b190, 0x075f0740}, | ||
724 | {0x0000b194, 0x077f0760}, | ||
725 | {0x0000b198, 0x07800781}, | ||
726 | {0x0000b19c, 0x07a0079f}, | ||
727 | {0x0000b1a0, 0x07c107bf}, | ||
728 | {0x0000b1a4, 0x000007c0}, | ||
729 | {0x0000b1a8, 0x00000000}, | ||
730 | {0x0000b1ac, 0x00000000}, | ||
731 | {0x0000b1b0, 0x00000000}, | ||
732 | {0x0000b1b4, 0x00000000}, | ||
733 | {0x0000b1b8, 0x00000000}, | ||
734 | {0x0000b1bc, 0x00000000}, | ||
735 | {0x0000b1c0, 0x00000000}, | ||
736 | {0x0000b1c4, 0x00000000}, | ||
737 | {0x0000b1c8, 0x00000000}, | ||
738 | {0x0000b1cc, 0x00000000}, | ||
739 | {0x0000b1d0, 0x00000000}, | ||
740 | {0x0000b1d4, 0x00000000}, | ||
741 | {0x0000b1d8, 0x00000000}, | ||
742 | {0x0000b1dc, 0x00000000}, | ||
743 | {0x0000b1e0, 0x00000000}, | ||
744 | {0x0000b1e4, 0x00000000}, | ||
745 | {0x0000b1e8, 0x00000000}, | ||
746 | {0x0000b1ec, 0x00000000}, | ||
747 | {0x0000b1f0, 0x00000396}, | ||
748 | {0x0000b1f4, 0x00000396}, | ||
749 | {0x0000b1f8, 0x00000396}, | ||
750 | {0x0000b1fc, 0x00000196}, | ||
751 | }; | ||
752 | |||
753 | static const u32 ar9462_2p1_common_mixed_rx_gain[][2] = { | ||
754 | /* Addr allmodes */ | ||
755 | {0x0000a000, 0x00010000}, | ||
756 | {0x0000a004, 0x00030002}, | ||
757 | {0x0000a008, 0x00050004}, | ||
758 | {0x0000a00c, 0x00810080}, | ||
759 | {0x0000a010, 0x00830082}, | ||
760 | {0x0000a014, 0x01810180}, | ||
761 | {0x0000a018, 0x01830182}, | ||
762 | {0x0000a01c, 0x01850184}, | ||
763 | {0x0000a020, 0x01890188}, | ||
764 | {0x0000a024, 0x018b018a}, | ||
765 | {0x0000a028, 0x018d018c}, | ||
766 | {0x0000a02c, 0x03820190}, | ||
767 | {0x0000a030, 0x03840383}, | ||
768 | {0x0000a034, 0x03880385}, | ||
769 | {0x0000a038, 0x038a0389}, | ||
770 | {0x0000a03c, 0x038c038b}, | ||
771 | {0x0000a040, 0x0390038d}, | ||
772 | {0x0000a044, 0x03920391}, | ||
773 | {0x0000a048, 0x03940393}, | ||
774 | {0x0000a04c, 0x03960395}, | ||
775 | {0x0000a050, 0x00000000}, | ||
776 | {0x0000a054, 0x00000000}, | ||
777 | {0x0000a058, 0x00000000}, | ||
778 | {0x0000a05c, 0x00000000}, | ||
779 | {0x0000a060, 0x00000000}, | ||
780 | {0x0000a064, 0x00000000}, | ||
781 | {0x0000a068, 0x00000000}, | ||
782 | {0x0000a06c, 0x00000000}, | ||
783 | {0x0000a070, 0x00000000}, | ||
784 | {0x0000a074, 0x00000000}, | ||
785 | {0x0000a078, 0x00000000}, | ||
786 | {0x0000a07c, 0x00000000}, | ||
787 | {0x0000a080, 0x29292929}, | ||
788 | {0x0000a084, 0x29292929}, | ||
789 | {0x0000a088, 0x29292929}, | ||
790 | {0x0000a08c, 0x29292929}, | ||
791 | {0x0000a090, 0x22292929}, | ||
792 | {0x0000a094, 0x1d1d2222}, | ||
793 | {0x0000a098, 0x0c111117}, | ||
794 | {0x0000a09c, 0x00030303}, | ||
795 | {0x0000a0a0, 0x00000000}, | ||
796 | {0x0000a0a4, 0x00000000}, | ||
797 | {0x0000a0a8, 0x00000000}, | ||
798 | {0x0000a0ac, 0x00000000}, | ||
799 | {0x0000a0b0, 0x00000000}, | ||
800 | {0x0000a0b4, 0x00000000}, | ||
801 | {0x0000a0b8, 0x00000000}, | ||
802 | {0x0000a0bc, 0x00000000}, | ||
803 | {0x0000a0c0, 0x001f0000}, | ||
804 | {0x0000a0c4, 0x01000101}, | ||
805 | {0x0000a0c8, 0x011e011f}, | ||
806 | {0x0000a0cc, 0x011c011d}, | ||
807 | {0x0000a0d0, 0x02030204}, | ||
808 | {0x0000a0d4, 0x02010202}, | ||
809 | {0x0000a0d8, 0x021f0200}, | ||
810 | {0x0000a0dc, 0x0302021e}, | ||
811 | {0x0000a0e0, 0x03000301}, | ||
812 | {0x0000a0e4, 0x031e031f}, | ||
813 | {0x0000a0e8, 0x0402031d}, | ||
814 | {0x0000a0ec, 0x04000401}, | ||
815 | {0x0000a0f0, 0x041e041f}, | ||
816 | {0x0000a0f4, 0x0502041d}, | ||
817 | {0x0000a0f8, 0x05000501}, | ||
818 | {0x0000a0fc, 0x051e051f}, | ||
819 | {0x0000a100, 0x06010602}, | ||
820 | {0x0000a104, 0x061f0600}, | ||
821 | {0x0000a108, 0x061d061e}, | ||
822 | {0x0000a10c, 0x07020703}, | ||
823 | {0x0000a110, 0x07000701}, | ||
824 | {0x0000a114, 0x00000000}, | ||
825 | {0x0000a118, 0x00000000}, | ||
826 | {0x0000a11c, 0x00000000}, | ||
827 | {0x0000a120, 0x00000000}, | ||
828 | {0x0000a124, 0x00000000}, | ||
829 | {0x0000a128, 0x00000000}, | ||
830 | {0x0000a12c, 0x00000000}, | ||
831 | {0x0000a130, 0x00000000}, | ||
832 | {0x0000a134, 0x00000000}, | ||
833 | {0x0000a138, 0x00000000}, | ||
834 | {0x0000a13c, 0x00000000}, | ||
835 | {0x0000a140, 0x001f0000}, | ||
836 | {0x0000a144, 0x01000101}, | ||
837 | {0x0000a148, 0x011e011f}, | ||
838 | {0x0000a14c, 0x011c011d}, | ||
839 | {0x0000a150, 0x02030204}, | ||
840 | {0x0000a154, 0x02010202}, | ||
841 | {0x0000a158, 0x021f0200}, | ||
842 | {0x0000a15c, 0x0302021e}, | ||
843 | {0x0000a160, 0x03000301}, | ||
844 | {0x0000a164, 0x031e031f}, | ||
845 | {0x0000a168, 0x0402031d}, | ||
846 | {0x0000a16c, 0x04000401}, | ||
847 | {0x0000a170, 0x041e041f}, | ||
848 | {0x0000a174, 0x0502041d}, | ||
849 | {0x0000a178, 0x05000501}, | ||
850 | {0x0000a17c, 0x051e051f}, | ||
851 | {0x0000a180, 0x06010602}, | ||
852 | {0x0000a184, 0x061f0600}, | ||
853 | {0x0000a188, 0x061d061e}, | ||
854 | {0x0000a18c, 0x07020703}, | ||
855 | {0x0000a190, 0x07000701}, | ||
856 | {0x0000a194, 0x00000000}, | ||
857 | {0x0000a198, 0x00000000}, | ||
858 | {0x0000a19c, 0x00000000}, | ||
859 | {0x0000a1a0, 0x00000000}, | ||
860 | {0x0000a1a4, 0x00000000}, | ||
861 | {0x0000a1a8, 0x00000000}, | ||
862 | {0x0000a1ac, 0x00000000}, | ||
863 | {0x0000a1b0, 0x00000000}, | ||
864 | {0x0000a1b4, 0x00000000}, | ||
865 | {0x0000a1b8, 0x00000000}, | ||
866 | {0x0000a1bc, 0x00000000}, | ||
867 | {0x0000a1c0, 0x00000000}, | ||
868 | {0x0000a1c4, 0x00000000}, | ||
869 | {0x0000a1c8, 0x00000000}, | ||
870 | {0x0000a1cc, 0x00000000}, | ||
871 | {0x0000a1d0, 0x00000000}, | ||
872 | {0x0000a1d4, 0x00000000}, | ||
873 | {0x0000a1d8, 0x00000000}, | ||
874 | {0x0000a1dc, 0x00000000}, | ||
875 | {0x0000a1e0, 0x00000000}, | ||
876 | {0x0000a1e4, 0x00000000}, | ||
877 | {0x0000a1e8, 0x00000000}, | ||
878 | {0x0000a1ec, 0x00000000}, | ||
879 | {0x0000a1f0, 0x00000396}, | ||
880 | {0x0000a1f4, 0x00000396}, | ||
881 | {0x0000a1f8, 0x00000396}, | ||
882 | {0x0000a1fc, 0x00000196}, | ||
883 | {0x0000b000, 0x00010000}, | ||
884 | {0x0000b004, 0x00030002}, | ||
885 | {0x0000b008, 0x00050004}, | ||
886 | {0x0000b00c, 0x00810080}, | ||
887 | {0x0000b010, 0x00830082}, | ||
888 | {0x0000b014, 0x01810180}, | ||
889 | {0x0000b018, 0x01830182}, | ||
890 | {0x0000b01c, 0x01850184}, | ||
891 | {0x0000b020, 0x02810280}, | ||
892 | {0x0000b024, 0x02830282}, | ||
893 | {0x0000b028, 0x02850284}, | ||
894 | {0x0000b02c, 0x02890288}, | ||
895 | {0x0000b030, 0x028b028a}, | ||
896 | {0x0000b034, 0x0388028c}, | ||
897 | {0x0000b038, 0x038a0389}, | ||
898 | {0x0000b03c, 0x038c038b}, | ||
899 | {0x0000b040, 0x0390038d}, | ||
900 | {0x0000b044, 0x03920391}, | ||
901 | {0x0000b048, 0x03940393}, | ||
902 | {0x0000b04c, 0x03960395}, | ||
903 | {0x0000b050, 0x00000000}, | ||
904 | {0x0000b054, 0x00000000}, | ||
905 | {0x0000b058, 0x00000000}, | ||
906 | {0x0000b05c, 0x00000000}, | ||
907 | {0x0000b060, 0x00000000}, | ||
908 | {0x0000b064, 0x00000000}, | ||
909 | {0x0000b068, 0x00000000}, | ||
910 | {0x0000b06c, 0x00000000}, | ||
911 | {0x0000b070, 0x00000000}, | ||
912 | {0x0000b074, 0x00000000}, | ||
913 | {0x0000b078, 0x00000000}, | ||
914 | {0x0000b07c, 0x00000000}, | ||
915 | {0x0000b080, 0x2a2d2f32}, | ||
916 | {0x0000b084, 0x21232328}, | ||
917 | {0x0000b088, 0x19191c1e}, | ||
918 | {0x0000b08c, 0x12141417}, | ||
919 | {0x0000b090, 0x07070e0e}, | ||
920 | {0x0000b094, 0x03030305}, | ||
921 | {0x0000b098, 0x00000003}, | ||
922 | {0x0000b09c, 0x00000000}, | ||
923 | {0x0000b0a0, 0x00000000}, | ||
924 | {0x0000b0a4, 0x00000000}, | ||
925 | {0x0000b0a8, 0x00000000}, | ||
926 | {0x0000b0ac, 0x00000000}, | ||
927 | {0x0000b0b0, 0x00000000}, | ||
928 | {0x0000b0b4, 0x00000000}, | ||
929 | {0x0000b0b8, 0x00000000}, | ||
930 | {0x0000b0bc, 0x00000000}, | ||
931 | {0x0000b0c0, 0x003f0020}, | ||
932 | {0x0000b0c4, 0x00400041}, | ||
933 | {0x0000b0c8, 0x0140005f}, | ||
934 | {0x0000b0cc, 0x0160015f}, | ||
935 | {0x0000b0d0, 0x017e017f}, | ||
936 | {0x0000b0d4, 0x02410242}, | ||
937 | {0x0000b0d8, 0x025f0240}, | ||
938 | {0x0000b0dc, 0x027f0260}, | ||
939 | {0x0000b0e0, 0x0341027e}, | ||
940 | {0x0000b0e4, 0x035f0340}, | ||
941 | {0x0000b0e8, 0x037f0360}, | ||
942 | {0x0000b0ec, 0x04400441}, | ||
943 | {0x0000b0f0, 0x0460045f}, | ||
944 | {0x0000b0f4, 0x0541047f}, | ||
945 | {0x0000b0f8, 0x055f0540}, | ||
946 | {0x0000b0fc, 0x057f0560}, | ||
947 | {0x0000b100, 0x06400641}, | ||
948 | {0x0000b104, 0x0660065f}, | ||
949 | {0x0000b108, 0x067e067f}, | ||
950 | {0x0000b10c, 0x07410742}, | ||
951 | {0x0000b110, 0x075f0740}, | ||
952 | {0x0000b114, 0x077f0760}, | ||
953 | {0x0000b118, 0x07800781}, | ||
954 | {0x0000b11c, 0x07a0079f}, | ||
955 | {0x0000b120, 0x07c107bf}, | ||
956 | {0x0000b124, 0x000007c0}, | ||
957 | {0x0000b128, 0x00000000}, | ||
958 | {0x0000b12c, 0x00000000}, | ||
959 | {0x0000b130, 0x00000000}, | ||
960 | {0x0000b134, 0x00000000}, | ||
961 | {0x0000b138, 0x00000000}, | ||
962 | {0x0000b13c, 0x00000000}, | ||
963 | {0x0000b140, 0x003f0020}, | ||
964 | {0x0000b144, 0x00400041}, | ||
965 | {0x0000b148, 0x0140005f}, | ||
966 | {0x0000b14c, 0x0160015f}, | ||
967 | {0x0000b150, 0x017e017f}, | ||
968 | {0x0000b154, 0x02410242}, | ||
969 | {0x0000b158, 0x025f0240}, | ||
970 | {0x0000b15c, 0x027f0260}, | ||
971 | {0x0000b160, 0x0341027e}, | ||
972 | {0x0000b164, 0x035f0340}, | ||
973 | {0x0000b168, 0x037f0360}, | ||
974 | {0x0000b16c, 0x04400441}, | ||
975 | {0x0000b170, 0x0460045f}, | ||
976 | {0x0000b174, 0x0541047f}, | ||
977 | {0x0000b178, 0x055f0540}, | ||
978 | {0x0000b17c, 0x057f0560}, | ||
979 | {0x0000b180, 0x06400641}, | ||
980 | {0x0000b184, 0x0660065f}, | ||
981 | {0x0000b188, 0x067e067f}, | ||
982 | {0x0000b18c, 0x07410742}, | ||
983 | {0x0000b190, 0x075f0740}, | ||
984 | {0x0000b194, 0x077f0760}, | ||
985 | {0x0000b198, 0x07800781}, | ||
986 | {0x0000b19c, 0x07a0079f}, | ||
987 | {0x0000b1a0, 0x07c107bf}, | ||
988 | {0x0000b1a4, 0x000007c0}, | ||
989 | {0x0000b1a8, 0x00000000}, | ||
990 | {0x0000b1ac, 0x00000000}, | ||
991 | {0x0000b1b0, 0x00000000}, | ||
992 | {0x0000b1b4, 0x00000000}, | ||
993 | {0x0000b1b8, 0x00000000}, | ||
994 | {0x0000b1bc, 0x00000000}, | ||
995 | {0x0000b1c0, 0x00000000}, | ||
996 | {0x0000b1c4, 0x00000000}, | ||
997 | {0x0000b1c8, 0x00000000}, | ||
998 | {0x0000b1cc, 0x00000000}, | ||
999 | {0x0000b1d0, 0x00000000}, | ||
1000 | {0x0000b1d4, 0x00000000}, | ||
1001 | {0x0000b1d8, 0x00000000}, | ||
1002 | {0x0000b1dc, 0x00000000}, | ||
1003 | {0x0000b1e0, 0x00000000}, | ||
1004 | {0x0000b1e4, 0x00000000}, | ||
1005 | {0x0000b1e8, 0x00000000}, | ||
1006 | {0x0000b1ec, 0x00000000}, | ||
1007 | {0x0000b1f0, 0x00000396}, | ||
1008 | {0x0000b1f4, 0x00000396}, | ||
1009 | {0x0000b1f8, 0x00000396}, | ||
1010 | {0x0000b1fc, 0x00000196}, | ||
1011 | }; | ||
1012 | |||
1013 | static const u32 ar9462_2p1_baseband_core_mix_rxgain[][2] = { | ||
1014 | /* Addr allmodes */ | ||
1015 | {0x00009fd0, 0x0a2d6b93}, | ||
1016 | }; | ||
1017 | |||
1018 | static const u32 ar9462_2p1_baseband_postamble_mix_rxgain[][5] = { | ||
1019 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1020 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, | ||
1021 | {0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da}, | ||
1022 | {0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81}, | ||
1023 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8}, | ||
1024 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e}, | ||
1025 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e}, | ||
1026 | }; | ||
1027 | |||
1028 | static const u32 ar9462_2p1_baseband_postamble_5g_xlna[][5] = { | ||
1029 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1030 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, | ||
1031 | }; | ||
1032 | |||
1033 | static const u32 ar9462_2p1_common_wo_xlna_rx_gain[][2] = { | ||
1034 | /* Addr allmodes */ | ||
1035 | {0x0000a000, 0x00010000}, | ||
1036 | {0x0000a004, 0x00030002}, | ||
1037 | {0x0000a008, 0x00050004}, | ||
1038 | {0x0000a00c, 0x00810080}, | ||
1039 | {0x0000a010, 0x00830082}, | ||
1040 | {0x0000a014, 0x01810180}, | ||
1041 | {0x0000a018, 0x01830182}, | ||
1042 | {0x0000a01c, 0x01850184}, | ||
1043 | {0x0000a020, 0x01890188}, | ||
1044 | {0x0000a024, 0x018b018a}, | ||
1045 | {0x0000a028, 0x018d018c}, | ||
1046 | {0x0000a02c, 0x03820190}, | ||
1047 | {0x0000a030, 0x03840383}, | ||
1048 | {0x0000a034, 0x03880385}, | ||
1049 | {0x0000a038, 0x038a0389}, | ||
1050 | {0x0000a03c, 0x038c038b}, | ||
1051 | {0x0000a040, 0x0390038d}, | ||
1052 | {0x0000a044, 0x03920391}, | ||
1053 | {0x0000a048, 0x03940393}, | ||
1054 | {0x0000a04c, 0x03960395}, | ||
1055 | {0x0000a050, 0x00000000}, | ||
1056 | {0x0000a054, 0x00000000}, | ||
1057 | {0x0000a058, 0x00000000}, | ||
1058 | {0x0000a05c, 0x00000000}, | ||
1059 | {0x0000a060, 0x00000000}, | ||
1060 | {0x0000a064, 0x00000000}, | ||
1061 | {0x0000a068, 0x00000000}, | ||
1062 | {0x0000a06c, 0x00000000}, | ||
1063 | {0x0000a070, 0x00000000}, | ||
1064 | {0x0000a074, 0x00000000}, | ||
1065 | {0x0000a078, 0x00000000}, | ||
1066 | {0x0000a07c, 0x00000000}, | ||
1067 | {0x0000a080, 0x29292929}, | ||
1068 | {0x0000a084, 0x29292929}, | ||
1069 | {0x0000a088, 0x29292929}, | ||
1070 | {0x0000a08c, 0x29292929}, | ||
1071 | {0x0000a090, 0x22292929}, | ||
1072 | {0x0000a094, 0x1d1d2222}, | ||
1073 | {0x0000a098, 0x0c111117}, | ||
1074 | {0x0000a09c, 0x00030303}, | ||
1075 | {0x0000a0a0, 0x00000000}, | ||
1076 | {0x0000a0a4, 0x00000000}, | ||
1077 | {0x0000a0a8, 0x00000000}, | ||
1078 | {0x0000a0ac, 0x00000000}, | ||
1079 | {0x0000a0b0, 0x00000000}, | ||
1080 | {0x0000a0b4, 0x00000000}, | ||
1081 | {0x0000a0b8, 0x00000000}, | ||
1082 | {0x0000a0bc, 0x00000000}, | ||
1083 | {0x0000a0c0, 0x001f0000}, | ||
1084 | {0x0000a0c4, 0x01000101}, | ||
1085 | {0x0000a0c8, 0x011e011f}, | ||
1086 | {0x0000a0cc, 0x011c011d}, | ||
1087 | {0x0000a0d0, 0x02030204}, | ||
1088 | {0x0000a0d4, 0x02010202}, | ||
1089 | {0x0000a0d8, 0x021f0200}, | ||
1090 | {0x0000a0dc, 0x0302021e}, | ||
1091 | {0x0000a0e0, 0x03000301}, | ||
1092 | {0x0000a0e4, 0x031e031f}, | ||
1093 | {0x0000a0e8, 0x0402031d}, | ||
1094 | {0x0000a0ec, 0x04000401}, | ||
1095 | {0x0000a0f0, 0x041e041f}, | ||
1096 | {0x0000a0f4, 0x0502041d}, | ||
1097 | {0x0000a0f8, 0x05000501}, | ||
1098 | {0x0000a0fc, 0x051e051f}, | ||
1099 | {0x0000a100, 0x06010602}, | ||
1100 | {0x0000a104, 0x061f0600}, | ||
1101 | {0x0000a108, 0x061d061e}, | ||
1102 | {0x0000a10c, 0x07020703}, | ||
1103 | {0x0000a110, 0x07000701}, | ||
1104 | {0x0000a114, 0x00000000}, | ||
1105 | {0x0000a118, 0x00000000}, | ||
1106 | {0x0000a11c, 0x00000000}, | ||
1107 | {0x0000a120, 0x00000000}, | ||
1108 | {0x0000a124, 0x00000000}, | ||
1109 | {0x0000a128, 0x00000000}, | ||
1110 | {0x0000a12c, 0x00000000}, | ||
1111 | {0x0000a130, 0x00000000}, | ||
1112 | {0x0000a134, 0x00000000}, | ||
1113 | {0x0000a138, 0x00000000}, | ||
1114 | {0x0000a13c, 0x00000000}, | ||
1115 | {0x0000a140, 0x001f0000}, | ||
1116 | {0x0000a144, 0x01000101}, | ||
1117 | {0x0000a148, 0x011e011f}, | ||
1118 | {0x0000a14c, 0x011c011d}, | ||
1119 | {0x0000a150, 0x02030204}, | ||
1120 | {0x0000a154, 0x02010202}, | ||
1121 | {0x0000a158, 0x021f0200}, | ||
1122 | {0x0000a15c, 0x0302021e}, | ||
1123 | {0x0000a160, 0x03000301}, | ||
1124 | {0x0000a164, 0x031e031f}, | ||
1125 | {0x0000a168, 0x0402031d}, | ||
1126 | {0x0000a16c, 0x04000401}, | ||
1127 | {0x0000a170, 0x041e041f}, | ||
1128 | {0x0000a174, 0x0502041d}, | ||
1129 | {0x0000a178, 0x05000501}, | ||
1130 | {0x0000a17c, 0x051e051f}, | ||
1131 | {0x0000a180, 0x06010602}, | ||
1132 | {0x0000a184, 0x061f0600}, | ||
1133 | {0x0000a188, 0x061d061e}, | ||
1134 | {0x0000a18c, 0x07020703}, | ||
1135 | {0x0000a190, 0x07000701}, | ||
1136 | {0x0000a194, 0x00000000}, | ||
1137 | {0x0000a198, 0x00000000}, | ||
1138 | {0x0000a19c, 0x00000000}, | ||
1139 | {0x0000a1a0, 0x00000000}, | ||
1140 | {0x0000a1a4, 0x00000000}, | ||
1141 | {0x0000a1a8, 0x00000000}, | ||
1142 | {0x0000a1ac, 0x00000000}, | ||
1143 | {0x0000a1b0, 0x00000000}, | ||
1144 | {0x0000a1b4, 0x00000000}, | ||
1145 | {0x0000a1b8, 0x00000000}, | ||
1146 | {0x0000a1bc, 0x00000000}, | ||
1147 | {0x0000a1c0, 0x00000000}, | ||
1148 | {0x0000a1c4, 0x00000000}, | ||
1149 | {0x0000a1c8, 0x00000000}, | ||
1150 | {0x0000a1cc, 0x00000000}, | ||
1151 | {0x0000a1d0, 0x00000000}, | ||
1152 | {0x0000a1d4, 0x00000000}, | ||
1153 | {0x0000a1d8, 0x00000000}, | ||
1154 | {0x0000a1dc, 0x00000000}, | ||
1155 | {0x0000a1e0, 0x00000000}, | ||
1156 | {0x0000a1e4, 0x00000000}, | ||
1157 | {0x0000a1e8, 0x00000000}, | ||
1158 | {0x0000a1ec, 0x00000000}, | ||
1159 | {0x0000a1f0, 0x00000396}, | ||
1160 | {0x0000a1f4, 0x00000396}, | ||
1161 | {0x0000a1f8, 0x00000396}, | ||
1162 | {0x0000a1fc, 0x00000196}, | ||
1163 | {0x0000b000, 0x00010000}, | ||
1164 | {0x0000b004, 0x00030002}, | ||
1165 | {0x0000b008, 0x00050004}, | ||
1166 | {0x0000b00c, 0x00810080}, | ||
1167 | {0x0000b010, 0x00830082}, | ||
1168 | {0x0000b014, 0x01810180}, | ||
1169 | {0x0000b018, 0x01830182}, | ||
1170 | {0x0000b01c, 0x01850184}, | ||
1171 | {0x0000b020, 0x02810280}, | ||
1172 | {0x0000b024, 0x02830282}, | ||
1173 | {0x0000b028, 0x02850284}, | ||
1174 | {0x0000b02c, 0x02890288}, | ||
1175 | {0x0000b030, 0x028b028a}, | ||
1176 | {0x0000b034, 0x0388028c}, | ||
1177 | {0x0000b038, 0x038a0389}, | ||
1178 | {0x0000b03c, 0x038c038b}, | ||
1179 | {0x0000b040, 0x0390038d}, | ||
1180 | {0x0000b044, 0x03920391}, | ||
1181 | {0x0000b048, 0x03940393}, | ||
1182 | {0x0000b04c, 0x03960395}, | ||
1183 | {0x0000b050, 0x00000000}, | ||
1184 | {0x0000b054, 0x00000000}, | ||
1185 | {0x0000b058, 0x00000000}, | ||
1186 | {0x0000b05c, 0x00000000}, | ||
1187 | {0x0000b060, 0x00000000}, | ||
1188 | {0x0000b064, 0x00000000}, | ||
1189 | {0x0000b068, 0x00000000}, | ||
1190 | {0x0000b06c, 0x00000000}, | ||
1191 | {0x0000b070, 0x00000000}, | ||
1192 | {0x0000b074, 0x00000000}, | ||
1193 | {0x0000b078, 0x00000000}, | ||
1194 | {0x0000b07c, 0x00000000}, | ||
1195 | {0x0000b080, 0x32323232}, | ||
1196 | {0x0000b084, 0x2f2f3232}, | ||
1197 | {0x0000b088, 0x23282a2d}, | ||
1198 | {0x0000b08c, 0x1c1e2123}, | ||
1199 | {0x0000b090, 0x14171919}, | ||
1200 | {0x0000b094, 0x0e0e1214}, | ||
1201 | {0x0000b098, 0x03050707}, | ||
1202 | {0x0000b09c, 0x00030303}, | ||
1203 | {0x0000b0a0, 0x00000000}, | ||
1204 | {0x0000b0a4, 0x00000000}, | ||
1205 | {0x0000b0a8, 0x00000000}, | ||
1206 | {0x0000b0ac, 0x00000000}, | ||
1207 | {0x0000b0b0, 0x00000000}, | ||
1208 | {0x0000b0b4, 0x00000000}, | ||
1209 | {0x0000b0b8, 0x00000000}, | ||
1210 | {0x0000b0bc, 0x00000000}, | ||
1211 | {0x0000b0c0, 0x003f0020}, | ||
1212 | {0x0000b0c4, 0x00400041}, | ||
1213 | {0x0000b0c8, 0x0140005f}, | ||
1214 | {0x0000b0cc, 0x0160015f}, | ||
1215 | {0x0000b0d0, 0x017e017f}, | ||
1216 | {0x0000b0d4, 0x02410242}, | ||
1217 | {0x0000b0d8, 0x025f0240}, | ||
1218 | {0x0000b0dc, 0x027f0260}, | ||
1219 | {0x0000b0e0, 0x0341027e}, | ||
1220 | {0x0000b0e4, 0x035f0340}, | ||
1221 | {0x0000b0e8, 0x037f0360}, | ||
1222 | {0x0000b0ec, 0x04400441}, | ||
1223 | {0x0000b0f0, 0x0460045f}, | ||
1224 | {0x0000b0f4, 0x0541047f}, | ||
1225 | {0x0000b0f8, 0x055f0540}, | ||
1226 | {0x0000b0fc, 0x057f0560}, | ||
1227 | {0x0000b100, 0x06400641}, | ||
1228 | {0x0000b104, 0x0660065f}, | ||
1229 | {0x0000b108, 0x067e067f}, | ||
1230 | {0x0000b10c, 0x07410742}, | ||
1231 | {0x0000b110, 0x075f0740}, | ||
1232 | {0x0000b114, 0x077f0760}, | ||
1233 | {0x0000b118, 0x07800781}, | ||
1234 | {0x0000b11c, 0x07a0079f}, | ||
1235 | {0x0000b120, 0x07c107bf}, | ||
1236 | {0x0000b124, 0x000007c0}, | ||
1237 | {0x0000b128, 0x00000000}, | ||
1238 | {0x0000b12c, 0x00000000}, | ||
1239 | {0x0000b130, 0x00000000}, | ||
1240 | {0x0000b134, 0x00000000}, | ||
1241 | {0x0000b138, 0x00000000}, | ||
1242 | {0x0000b13c, 0x00000000}, | ||
1243 | {0x0000b140, 0x003f0020}, | ||
1244 | {0x0000b144, 0x00400041}, | ||
1245 | {0x0000b148, 0x0140005f}, | ||
1246 | {0x0000b14c, 0x0160015f}, | ||
1247 | {0x0000b150, 0x017e017f}, | ||
1248 | {0x0000b154, 0x02410242}, | ||
1249 | {0x0000b158, 0x025f0240}, | ||
1250 | {0x0000b15c, 0x027f0260}, | ||
1251 | {0x0000b160, 0x0341027e}, | ||
1252 | {0x0000b164, 0x035f0340}, | ||
1253 | {0x0000b168, 0x037f0360}, | ||
1254 | {0x0000b16c, 0x04400441}, | ||
1255 | {0x0000b170, 0x0460045f}, | ||
1256 | {0x0000b174, 0x0541047f}, | ||
1257 | {0x0000b178, 0x055f0540}, | ||
1258 | {0x0000b17c, 0x057f0560}, | ||
1259 | {0x0000b180, 0x06400641}, | ||
1260 | {0x0000b184, 0x0660065f}, | ||
1261 | {0x0000b188, 0x067e067f}, | ||
1262 | {0x0000b18c, 0x07410742}, | ||
1263 | {0x0000b190, 0x075f0740}, | ||
1264 | {0x0000b194, 0x077f0760}, | ||
1265 | {0x0000b198, 0x07800781}, | ||
1266 | {0x0000b19c, 0x07a0079f}, | ||
1267 | {0x0000b1a0, 0x07c107bf}, | ||
1268 | {0x0000b1a4, 0x000007c0}, | ||
1269 | {0x0000b1a8, 0x00000000}, | ||
1270 | {0x0000b1ac, 0x00000000}, | ||
1271 | {0x0000b1b0, 0x00000000}, | ||
1272 | {0x0000b1b4, 0x00000000}, | ||
1273 | {0x0000b1b8, 0x00000000}, | ||
1274 | {0x0000b1bc, 0x00000000}, | ||
1275 | {0x0000b1c0, 0x00000000}, | ||
1276 | {0x0000b1c4, 0x00000000}, | ||
1277 | {0x0000b1c8, 0x00000000}, | ||
1278 | {0x0000b1cc, 0x00000000}, | ||
1279 | {0x0000b1d0, 0x00000000}, | ||
1280 | {0x0000b1d4, 0x00000000}, | ||
1281 | {0x0000b1d8, 0x00000000}, | ||
1282 | {0x0000b1dc, 0x00000000}, | ||
1283 | {0x0000b1e0, 0x00000000}, | ||
1284 | {0x0000b1e4, 0x00000000}, | ||
1285 | {0x0000b1e8, 0x00000000}, | ||
1286 | {0x0000b1ec, 0x00000000}, | ||
1287 | {0x0000b1f0, 0x00000396}, | ||
1288 | {0x0000b1f4, 0x00000396}, | ||
1289 | {0x0000b1f8, 0x00000396}, | ||
1290 | {0x0000b1fc, 0x00000196}, | ||
1291 | }; | ||
1292 | |||
1293 | static const u32 ar9462_2p1_common_5g_xlna_only_rx_gain[][2] = { | ||
1294 | /* Addr allmodes */ | ||
1295 | {0x0000a000, 0x00010000}, | ||
1296 | {0x0000a004, 0x00030002}, | ||
1297 | {0x0000a008, 0x00050004}, | ||
1298 | {0x0000a00c, 0x00810080}, | ||
1299 | {0x0000a010, 0x00830082}, | ||
1300 | {0x0000a014, 0x01810180}, | ||
1301 | {0x0000a018, 0x01830182}, | ||
1302 | {0x0000a01c, 0x01850184}, | ||
1303 | {0x0000a020, 0x01890188}, | ||
1304 | {0x0000a024, 0x018b018a}, | ||
1305 | {0x0000a028, 0x018d018c}, | ||
1306 | {0x0000a02c, 0x03820190}, | ||
1307 | {0x0000a030, 0x03840383}, | ||
1308 | {0x0000a034, 0x03880385}, | ||
1309 | {0x0000a038, 0x038a0389}, | ||
1310 | {0x0000a03c, 0x038c038b}, | ||
1311 | {0x0000a040, 0x0390038d}, | ||
1312 | {0x0000a044, 0x03920391}, | ||
1313 | {0x0000a048, 0x03940393}, | ||
1314 | {0x0000a04c, 0x03960395}, | ||
1315 | {0x0000a050, 0x00000000}, | ||
1316 | {0x0000a054, 0x00000000}, | ||
1317 | {0x0000a058, 0x00000000}, | ||
1318 | {0x0000a05c, 0x00000000}, | ||
1319 | {0x0000a060, 0x00000000}, | ||
1320 | {0x0000a064, 0x00000000}, | ||
1321 | {0x0000a068, 0x00000000}, | ||
1322 | {0x0000a06c, 0x00000000}, | ||
1323 | {0x0000a070, 0x00000000}, | ||
1324 | {0x0000a074, 0x00000000}, | ||
1325 | {0x0000a078, 0x00000000}, | ||
1326 | {0x0000a07c, 0x00000000}, | ||
1327 | {0x0000a080, 0x29292929}, | ||
1328 | {0x0000a084, 0x29292929}, | ||
1329 | {0x0000a088, 0x29292929}, | ||
1330 | {0x0000a08c, 0x29292929}, | ||
1331 | {0x0000a090, 0x22292929}, | ||
1332 | {0x0000a094, 0x1d1d2222}, | ||
1333 | {0x0000a098, 0x0c111117}, | ||
1334 | {0x0000a09c, 0x00030303}, | ||
1335 | {0x0000a0a0, 0x00000000}, | ||
1336 | {0x0000a0a4, 0x00000000}, | ||
1337 | {0x0000a0a8, 0x00000000}, | ||
1338 | {0x0000a0ac, 0x00000000}, | ||
1339 | {0x0000a0b0, 0x00000000}, | ||
1340 | {0x0000a0b4, 0x00000000}, | ||
1341 | {0x0000a0b8, 0x00000000}, | ||
1342 | {0x0000a0bc, 0x00000000}, | ||
1343 | {0x0000a0c0, 0x001f0000}, | ||
1344 | {0x0000a0c4, 0x01000101}, | ||
1345 | {0x0000a0c8, 0x011e011f}, | ||
1346 | {0x0000a0cc, 0x011c011d}, | ||
1347 | {0x0000a0d0, 0x02030204}, | ||
1348 | {0x0000a0d4, 0x02010202}, | ||
1349 | {0x0000a0d8, 0x021f0200}, | ||
1350 | {0x0000a0dc, 0x0302021e}, | ||
1351 | {0x0000a0e0, 0x03000301}, | ||
1352 | {0x0000a0e4, 0x031e031f}, | ||
1353 | {0x0000a0e8, 0x0402031d}, | ||
1354 | {0x0000a0ec, 0x04000401}, | ||
1355 | {0x0000a0f0, 0x041e041f}, | ||
1356 | {0x0000a0f4, 0x0502041d}, | ||
1357 | {0x0000a0f8, 0x05000501}, | ||
1358 | {0x0000a0fc, 0x051e051f}, | ||
1359 | {0x0000a100, 0x06010602}, | ||
1360 | {0x0000a104, 0x061f0600}, | ||
1361 | {0x0000a108, 0x061d061e}, | ||
1362 | {0x0000a10c, 0x07020703}, | ||
1363 | {0x0000a110, 0x07000701}, | ||
1364 | {0x0000a114, 0x00000000}, | ||
1365 | {0x0000a118, 0x00000000}, | ||
1366 | {0x0000a11c, 0x00000000}, | ||
1367 | {0x0000a120, 0x00000000}, | ||
1368 | {0x0000a124, 0x00000000}, | ||
1369 | {0x0000a128, 0x00000000}, | ||
1370 | {0x0000a12c, 0x00000000}, | ||
1371 | {0x0000a130, 0x00000000}, | ||
1372 | {0x0000a134, 0x00000000}, | ||
1373 | {0x0000a138, 0x00000000}, | ||
1374 | {0x0000a13c, 0x00000000}, | ||
1375 | {0x0000a140, 0x001f0000}, | ||
1376 | {0x0000a144, 0x01000101}, | ||
1377 | {0x0000a148, 0x011e011f}, | ||
1378 | {0x0000a14c, 0x011c011d}, | ||
1379 | {0x0000a150, 0x02030204}, | ||
1380 | {0x0000a154, 0x02010202}, | ||
1381 | {0x0000a158, 0x021f0200}, | ||
1382 | {0x0000a15c, 0x0302021e}, | ||
1383 | {0x0000a160, 0x03000301}, | ||
1384 | {0x0000a164, 0x031e031f}, | ||
1385 | {0x0000a168, 0x0402031d}, | ||
1386 | {0x0000a16c, 0x04000401}, | ||
1387 | {0x0000a170, 0x041e041f}, | ||
1388 | {0x0000a174, 0x0502041d}, | ||
1389 | {0x0000a178, 0x05000501}, | ||
1390 | {0x0000a17c, 0x051e051f}, | ||
1391 | {0x0000a180, 0x06010602}, | ||
1392 | {0x0000a184, 0x061f0600}, | ||
1393 | {0x0000a188, 0x061d061e}, | ||
1394 | {0x0000a18c, 0x07020703}, | ||
1395 | {0x0000a190, 0x07000701}, | ||
1396 | {0x0000a194, 0x00000000}, | ||
1397 | {0x0000a198, 0x00000000}, | ||
1398 | {0x0000a19c, 0x00000000}, | ||
1399 | {0x0000a1a0, 0x00000000}, | ||
1400 | {0x0000a1a4, 0x00000000}, | ||
1401 | {0x0000a1a8, 0x00000000}, | ||
1402 | {0x0000a1ac, 0x00000000}, | ||
1403 | {0x0000a1b0, 0x00000000}, | ||
1404 | {0x0000a1b4, 0x00000000}, | ||
1405 | {0x0000a1b8, 0x00000000}, | ||
1406 | {0x0000a1bc, 0x00000000}, | ||
1407 | {0x0000a1c0, 0x00000000}, | ||
1408 | {0x0000a1c4, 0x00000000}, | ||
1409 | {0x0000a1c8, 0x00000000}, | ||
1410 | {0x0000a1cc, 0x00000000}, | ||
1411 | {0x0000a1d0, 0x00000000}, | ||
1412 | {0x0000a1d4, 0x00000000}, | ||
1413 | {0x0000a1d8, 0x00000000}, | ||
1414 | {0x0000a1dc, 0x00000000}, | ||
1415 | {0x0000a1e0, 0x00000000}, | ||
1416 | {0x0000a1e4, 0x00000000}, | ||
1417 | {0x0000a1e8, 0x00000000}, | ||
1418 | {0x0000a1ec, 0x00000000}, | ||
1419 | {0x0000a1f0, 0x00000396}, | ||
1420 | {0x0000a1f4, 0x00000396}, | ||
1421 | {0x0000a1f8, 0x00000396}, | ||
1422 | {0x0000a1fc, 0x00000196}, | ||
1423 | {0x0000b000, 0x00010000}, | ||
1424 | {0x0000b004, 0x00030002}, | ||
1425 | {0x0000b008, 0x00050004}, | ||
1426 | {0x0000b00c, 0x00810080}, | ||
1427 | {0x0000b010, 0x00830082}, | ||
1428 | {0x0000b014, 0x01810180}, | ||
1429 | {0x0000b018, 0x01830182}, | ||
1430 | {0x0000b01c, 0x01850184}, | ||
1431 | {0x0000b020, 0x02810280}, | ||
1432 | {0x0000b024, 0x02830282}, | ||
1433 | {0x0000b028, 0x02850284}, | ||
1434 | {0x0000b02c, 0x02890288}, | ||
1435 | {0x0000b030, 0x028b028a}, | ||
1436 | {0x0000b034, 0x0388028c}, | ||
1437 | {0x0000b038, 0x038a0389}, | ||
1438 | {0x0000b03c, 0x038c038b}, | ||
1439 | {0x0000b040, 0x0390038d}, | ||
1440 | {0x0000b044, 0x03920391}, | ||
1441 | {0x0000b048, 0x03940393}, | ||
1442 | {0x0000b04c, 0x03960395}, | ||
1443 | {0x0000b050, 0x00000000}, | ||
1444 | {0x0000b054, 0x00000000}, | ||
1445 | {0x0000b058, 0x00000000}, | ||
1446 | {0x0000b05c, 0x00000000}, | ||
1447 | {0x0000b060, 0x00000000}, | ||
1448 | {0x0000b064, 0x00000000}, | ||
1449 | {0x0000b068, 0x00000000}, | ||
1450 | {0x0000b06c, 0x00000000}, | ||
1451 | {0x0000b070, 0x00000000}, | ||
1452 | {0x0000b074, 0x00000000}, | ||
1453 | {0x0000b078, 0x00000000}, | ||
1454 | {0x0000b07c, 0x00000000}, | ||
1455 | {0x0000b080, 0x2a2d2f32}, | ||
1456 | {0x0000b084, 0x21232328}, | ||
1457 | {0x0000b088, 0x19191c1e}, | ||
1458 | {0x0000b08c, 0x12141417}, | ||
1459 | {0x0000b090, 0x07070e0e}, | ||
1460 | {0x0000b094, 0x03030305}, | ||
1461 | {0x0000b098, 0x00000003}, | ||
1462 | {0x0000b09c, 0x00000000}, | ||
1463 | {0x0000b0a0, 0x00000000}, | ||
1464 | {0x0000b0a4, 0x00000000}, | ||
1465 | {0x0000b0a8, 0x00000000}, | ||
1466 | {0x0000b0ac, 0x00000000}, | ||
1467 | {0x0000b0b0, 0x00000000}, | ||
1468 | {0x0000b0b4, 0x00000000}, | ||
1469 | {0x0000b0b8, 0x00000000}, | ||
1470 | {0x0000b0bc, 0x00000000}, | ||
1471 | {0x0000b0c0, 0x003f0020}, | ||
1472 | {0x0000b0c4, 0x00400041}, | ||
1473 | {0x0000b0c8, 0x0140005f}, | ||
1474 | {0x0000b0cc, 0x0160015f}, | ||
1475 | {0x0000b0d0, 0x017e017f}, | ||
1476 | {0x0000b0d4, 0x02410242}, | ||
1477 | {0x0000b0d8, 0x025f0240}, | ||
1478 | {0x0000b0dc, 0x027f0260}, | ||
1479 | {0x0000b0e0, 0x0341027e}, | ||
1480 | {0x0000b0e4, 0x035f0340}, | ||
1481 | {0x0000b0e8, 0x037f0360}, | ||
1482 | {0x0000b0ec, 0x04400441}, | ||
1483 | {0x0000b0f0, 0x0460045f}, | ||
1484 | {0x0000b0f4, 0x0541047f}, | ||
1485 | {0x0000b0f8, 0x055f0540}, | ||
1486 | {0x0000b0fc, 0x057f0560}, | ||
1487 | {0x0000b100, 0x06400641}, | ||
1488 | {0x0000b104, 0x0660065f}, | ||
1489 | {0x0000b108, 0x067e067f}, | ||
1490 | {0x0000b10c, 0x07410742}, | ||
1491 | {0x0000b110, 0x075f0740}, | ||
1492 | {0x0000b114, 0x077f0760}, | ||
1493 | {0x0000b118, 0x07800781}, | ||
1494 | {0x0000b11c, 0x07a0079f}, | ||
1495 | {0x0000b120, 0x07c107bf}, | ||
1496 | {0x0000b124, 0x000007c0}, | ||
1497 | {0x0000b128, 0x00000000}, | ||
1498 | {0x0000b12c, 0x00000000}, | ||
1499 | {0x0000b130, 0x00000000}, | ||
1500 | {0x0000b134, 0x00000000}, | ||
1501 | {0x0000b138, 0x00000000}, | ||
1502 | {0x0000b13c, 0x00000000}, | ||
1503 | {0x0000b140, 0x003f0020}, | ||
1504 | {0x0000b144, 0x00400041}, | ||
1505 | {0x0000b148, 0x0140005f}, | ||
1506 | {0x0000b14c, 0x0160015f}, | ||
1507 | {0x0000b150, 0x017e017f}, | ||
1508 | {0x0000b154, 0x02410242}, | ||
1509 | {0x0000b158, 0x025f0240}, | ||
1510 | {0x0000b15c, 0x027f0260}, | ||
1511 | {0x0000b160, 0x0341027e}, | ||
1512 | {0x0000b164, 0x035f0340}, | ||
1513 | {0x0000b168, 0x037f0360}, | ||
1514 | {0x0000b16c, 0x04400441}, | ||
1515 | {0x0000b170, 0x0460045f}, | ||
1516 | {0x0000b174, 0x0541047f}, | ||
1517 | {0x0000b178, 0x055f0540}, | ||
1518 | {0x0000b17c, 0x057f0560}, | ||
1519 | {0x0000b180, 0x06400641}, | ||
1520 | {0x0000b184, 0x0660065f}, | ||
1521 | {0x0000b188, 0x067e067f}, | ||
1522 | {0x0000b18c, 0x07410742}, | ||
1523 | {0x0000b190, 0x075f0740}, | ||
1524 | {0x0000b194, 0x077f0760}, | ||
1525 | {0x0000b198, 0x07800781}, | ||
1526 | {0x0000b19c, 0x07a0079f}, | ||
1527 | {0x0000b1a0, 0x07c107bf}, | ||
1528 | {0x0000b1a4, 0x000007c0}, | ||
1529 | {0x0000b1a8, 0x00000000}, | ||
1530 | {0x0000b1ac, 0x00000000}, | ||
1531 | {0x0000b1b0, 0x00000000}, | ||
1532 | {0x0000b1b4, 0x00000000}, | ||
1533 | {0x0000b1b8, 0x00000000}, | ||
1534 | {0x0000b1bc, 0x00000000}, | ||
1535 | {0x0000b1c0, 0x00000000}, | ||
1536 | {0x0000b1c4, 0x00000000}, | ||
1537 | {0x0000b1c8, 0x00000000}, | ||
1538 | {0x0000b1cc, 0x00000000}, | ||
1539 | {0x0000b1d0, 0x00000000}, | ||
1540 | {0x0000b1d4, 0x00000000}, | ||
1541 | {0x0000b1d8, 0x00000000}, | ||
1542 | {0x0000b1dc, 0x00000000}, | ||
1543 | {0x0000b1e0, 0x00000000}, | ||
1544 | {0x0000b1e4, 0x00000000}, | ||
1545 | {0x0000b1e8, 0x00000000}, | ||
1546 | {0x0000b1ec, 0x00000000}, | ||
1547 | {0x0000b1f0, 0x00000396}, | ||
1548 | {0x0000b1f4, 0x00000396}, | ||
1549 | {0x0000b1f8, 0x00000396}, | ||
1550 | {0x0000b1fc, 0x00000196}, | ||
1551 | }; | ||
1552 | |||
1553 | static const u32 ar9462_2p1_modes_low_ob_db_tx_gain[][5] = { | ||
1554 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1555 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
1556 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
1557 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
1558 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
1559 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1560 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
1561 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1562 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1563 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
1564 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
1565 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
1566 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
1567 | {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, | ||
1568 | {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, | ||
1569 | {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, | ||
1570 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, | ||
1571 | {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, | ||
1572 | {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, | ||
1573 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, | ||
1574 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, | ||
1575 | {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, | ||
1576 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | ||
1577 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | ||
1578 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | ||
1579 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | ||
1580 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | ||
1581 | {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, | ||
1582 | {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, | ||
1583 | {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, | ||
1584 | {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, | ||
1585 | {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, | ||
1586 | {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, | ||
1587 | {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1588 | {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1589 | {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1590 | {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1591 | {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1592 | {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1593 | {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, | ||
1594 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1595 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1596 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1597 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1598 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1599 | {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, | ||
1600 | {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, | ||
1601 | {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, | ||
1602 | {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, | ||
1603 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | ||
1604 | {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, | ||
1605 | {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, | ||
1606 | {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1607 | {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1608 | {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1609 | {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | ||
1610 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
1611 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
1612 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
1613 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1614 | {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, | ||
1615 | {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060}, | ||
1616 | {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, | ||
1617 | {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, | ||
1618 | {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000}, | ||
1619 | {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, | ||
1620 | }; | ||
1621 | |||
1622 | static const u32 ar9462_2p1_modes_high_ob_db_tx_gain[][5] = { | ||
1623 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1624 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
1625 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1626 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1627 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1628 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1629 | {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, | ||
1630 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1631 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | ||
1632 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | ||
1633 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | ||
1634 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | ||
1635 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | ||
1636 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | ||
1637 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | ||
1638 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | ||
1639 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | ||
1640 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | ||
1641 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | ||
1642 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | ||
1643 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | ||
1644 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | ||
1645 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | ||
1646 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | ||
1647 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | ||
1648 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | ||
1649 | {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, | ||
1650 | {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, | ||
1651 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, | ||
1652 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | ||
1653 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | ||
1654 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | ||
1655 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | ||
1656 | {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, | ||
1657 | {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, | ||
1658 | {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, | ||
1659 | {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, | ||
1660 | {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, | ||
1661 | {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, | ||
1662 | {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, | ||
1663 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1664 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1665 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1666 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1667 | {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, | ||
1668 | {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, | ||
1669 | {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, | ||
1670 | {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, | ||
1671 | {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, | ||
1672 | {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, | ||
1673 | {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, | ||
1674 | {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1675 | {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1676 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1677 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1678 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1679 | {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1680 | {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1681 | {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1682 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1683 | {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, | ||
1684 | {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060}, | ||
1685 | {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, | ||
1686 | {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, | ||
1687 | {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000}, | ||
1688 | {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, | ||
1689 | }; | ||
1690 | |||
1691 | static const u32 ar9462_2p1_modes_mix_ob_db_tx_gain[][5] = { | ||
1692 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1693 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
1694 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1695 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1696 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1697 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1698 | {0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de}, | ||
1699 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1700 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | ||
1701 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | ||
1702 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | ||
1703 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | ||
1704 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | ||
1705 | {0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400}, | ||
1706 | {0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402}, | ||
1707 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | ||
1708 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603}, | ||
1709 | {0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02}, | ||
1710 | {0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04}, | ||
1711 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20}, | ||
1712 | {0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20}, | ||
1713 | {0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22}, | ||
1714 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24}, | ||
1715 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640}, | ||
1716 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660}, | ||
1717 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861}, | ||
1718 | {0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81}, | ||
1719 | {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83}, | ||
1720 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84}, | ||
1721 | {0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3}, | ||
1722 | {0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5}, | ||
1723 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9}, | ||
1724 | {0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb}, | ||
1725 | {0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec}, | ||
1726 | {0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0}, | ||
1727 | {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4}, | ||
1728 | {0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, | ||
1729 | {0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, | ||
1730 | {0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, | ||
1731 | {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, | ||
1732 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1733 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1734 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1735 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1736 | {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, | ||
1737 | {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, | ||
1738 | {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, | ||
1739 | {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, | ||
1740 | {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, | ||
1741 | {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, | ||
1742 | {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, | ||
1743 | {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1744 | {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1745 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1746 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1747 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1748 | {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1749 | {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1750 | {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1751 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1752 | }; | ||
1753 | |||
1754 | static const u32 ar9462_2p1_modes_fast_clock[][3] = { | ||
1755 | /* Addr 5G_HT20 5G_HT40 */ | ||
1756 | {0x00001030, 0x00000268, 0x000004d0}, | ||
1757 | {0x00001070, 0x0000018c, 0x00000318}, | ||
1758 | {0x000010b0, 0x00000fd0, 0x00001fa0}, | ||
1759 | {0x00008014, 0x044c044c, 0x08980898}, | ||
1760 | {0x0000801c, 0x148ec02b, 0x148ec057}, | ||
1761 | {0x00008318, 0x000044c0, 0x00008980}, | ||
1762 | {0x00009e00, 0x0372131c, 0x0372131c}, | ||
1763 | {0x0000a230, 0x0000400b, 0x00004016}, | ||
1764 | {0x0000a254, 0x00000898, 0x00001130}, | ||
1765 | }; | ||
1766 | |||
1767 | static const u32 ar9462_2p1_baseband_core_txfir_coeff_japan_2484[][2] = { | ||
1768 | /* Addr allmodes */ | ||
1769 | {0x0000a398, 0x00000000}, | ||
1770 | {0x0000a39c, 0x6f7f0301}, | ||
1771 | {0x0000a3a0, 0xca9228ee}, | ||
1772 | }; | ||
1773 | |||
1774 | #endif /* INITVALS_9462_2P1_H */ | 291 | #endif /* INITVALS_9462_2P1_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h new file mode 100644 index 000000000000..56810539971e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * Copyright (c) 2011-2012 Qualcomm Atheros Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef INITVALS_9565_1P1_H | ||
19 | #define INITVALS_9565_1P1_H | ||
20 | |||
21 | /* AR9565 1.1 */ | ||
22 | |||
23 | #define ar9565_1p1_mac_core ar9565_1p0_mac_core | ||
24 | |||
25 | #define ar9565_1p1_mac_postamble ar9565_1p0_mac_postamble | ||
26 | |||
27 | #define ar9565_1p1_baseband_core ar9565_1p0_baseband_core | ||
28 | |||
29 | #define ar9565_1p1_baseband_postamble ar9565_1p0_baseband_postamble | ||
30 | |||
31 | #define ar9565_1p1_radio_core ar9565_1p0_radio_core | ||
32 | |||
33 | #define ar9565_1p1_soc_preamble ar9565_1p0_soc_preamble | ||
34 | |||
35 | #define ar9565_1p1_soc_postamble ar9565_1p0_soc_postamble | ||
36 | |||
37 | #define ar9565_1p1_Common_rx_gain_table ar9565_1p0_Common_rx_gain_table | ||
38 | |||
39 | #define ar9565_1p1_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_Modes_lowest_ob_db_tx_gain_table | ||
40 | |||
41 | #define ar9565_1p1_pciephy_clkreq_disable_L1 ar9565_1p0_pciephy_clkreq_disable_L1 | ||
42 | |||
43 | #define ar9565_1p1_modes_fast_clock ar9565_1p0_modes_fast_clock | ||
44 | |||
45 | #define ar9565_1p1_common_wo_xlna_rx_gain_table ar9565_1p0_common_wo_xlna_rx_gain_table | ||
46 | |||
47 | #define ar9565_1p1_modes_low_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table | ||
48 | |||
49 | #define ar9565_1p1_modes_high_ob_db_tx_gain_table ar9565_1p0_modes_high_ob_db_tx_gain_table | ||
50 | |||
51 | #define ar9565_1p1_modes_high_power_tx_gain_table ar9565_1p0_modes_high_power_tx_gain_table | ||
52 | |||
53 | #define ar9565_1p1_baseband_core_txfir_coeff_japan_2484 ar9565_1p0_baseband_core_txfir_coeff_japan_2484 | ||
54 | |||
55 | static const u32 ar9565_1p1_radio_postamble[][5] = { | ||
56 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
57 | {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524}, | ||
58 | {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, | ||
59 | {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70}, | ||
60 | {0x0001610c, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, | ||
61 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
62 | }; | ||
63 | |||
64 | #endif /* INITVALS_9565_1P1_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index bdee2ed67219..75bef1179d0d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | |||
@@ -20,18 +20,34 @@ | |||
20 | 20 | ||
21 | /* AR9580 1.0 */ | 21 | /* AR9580 1.0 */ |
22 | 22 | ||
23 | #define ar9580_1p0_soc_preamble ar9300_2p2_soc_preamble | ||
24 | |||
25 | #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
26 | |||
27 | #define ar9580_1p0_radio_core ar9300_2p2_radio_core | ||
28 | |||
29 | #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble | ||
30 | |||
31 | #define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
32 | |||
33 | #define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2 | ||
34 | |||
35 | #define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 | ||
36 | |||
23 | #define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 | 37 | #define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 |
24 | 38 | ||
39 | #define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484 | ||
40 | |||
25 | static const u32 ar9580_1p0_radio_postamble[][5] = { | 41 | static const u32 ar9580_1p0_radio_postamble[][5] = { |
26 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 42 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
27 | {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, | 43 | {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, |
28 | {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, | 44 | {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, |
29 | {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, | 45 | {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, |
30 | {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | 46 | {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
31 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | 47 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, |
32 | {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | 48 | {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
33 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | 49 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, |
34 | {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | 50 | {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
35 | {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | 51 | {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, |
36 | }; | 52 | }; |
37 | 53 | ||
@@ -44,9 +60,9 @@ static const u32 ar9580_1p0_baseband_core[][2] = { | |||
44 | {0x00009814, 0x3280c00a}, | 60 | {0x00009814, 0x3280c00a}, |
45 | {0x00009818, 0x00000000}, | 61 | {0x00009818, 0x00000000}, |
46 | {0x0000981c, 0x00020028}, | 62 | {0x0000981c, 0x00020028}, |
47 | {0x00009834, 0x6400a290}, | 63 | {0x00009834, 0x6400a190}, |
48 | {0x00009838, 0x0108ecff}, | 64 | {0x00009838, 0x0108ecff}, |
49 | {0x0000983c, 0x0d000600}, | 65 | {0x0000983c, 0x14000600}, |
50 | {0x00009880, 0x201fff00}, | 66 | {0x00009880, 0x201fff00}, |
51 | {0x00009884, 0x00001042}, | 67 | {0x00009884, 0x00001042}, |
52 | {0x000098a4, 0x00200400}, | 68 | {0x000098a4, 0x00200400}, |
@@ -67,7 +83,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = { | |||
67 | {0x00009d04, 0x40206c10}, | 83 | {0x00009d04, 0x40206c10}, |
68 | {0x00009d08, 0x009c4060}, | 84 | {0x00009d08, 0x009c4060}, |
69 | {0x00009d0c, 0x9883800a}, | 85 | {0x00009d0c, 0x9883800a}, |
70 | {0x00009d10, 0x01834061}, | 86 | {0x00009d10, 0x01884061}, |
71 | {0x00009d14, 0x00c0040b}, | 87 | {0x00009d14, 0x00c0040b}, |
72 | {0x00009d18, 0x00000000}, | 88 | {0x00009d18, 0x00000000}, |
73 | {0x00009e08, 0x0038230c}, | 89 | {0x00009e08, 0x0038230c}, |
@@ -198,8 +214,6 @@ static const u32 ar9580_1p0_baseband_core[][2] = { | |||
198 | {0x0000c420, 0x00000000}, | 214 | {0x0000c420, 0x00000000}, |
199 | }; | 215 | }; |
200 | 216 | ||
201 | #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble | ||
202 | |||
203 | static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { | 217 | static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { |
204 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 218 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
205 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | 219 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
@@ -306,7 +320,112 @@ static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { | |||
306 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 320 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
307 | }; | 321 | }; |
308 | 322 | ||
309 | #define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table | 323 | static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = { |
324 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
325 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
326 | {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
327 | {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
328 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
329 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
330 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
331 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
332 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
333 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
334 | {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, | ||
335 | {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, | ||
336 | {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, | ||
337 | {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, | ||
338 | {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, | ||
339 | {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, | ||
340 | {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, | ||
341 | {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, | ||
342 | {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, | ||
343 | {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, | ||
344 | {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, | ||
345 | {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, | ||
346 | {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, | ||
347 | {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, | ||
348 | {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, | ||
349 | {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83}, | ||
350 | {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84}, | ||
351 | {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, | ||
352 | {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, | ||
353 | {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, | ||
354 | {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, | ||
355 | {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
356 | {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
357 | {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
358 | {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
359 | {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
360 | {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
361 | {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
362 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
363 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
364 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
365 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
366 | {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, | ||
367 | {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, | ||
368 | {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, | ||
369 | {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, | ||
370 | {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, | ||
371 | {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, | ||
372 | {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, | ||
373 | {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, | ||
374 | {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, | ||
375 | {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, | ||
376 | {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, | ||
377 | {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, | ||
378 | {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, | ||
379 | {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, | ||
380 | {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, | ||
381 | {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, | ||
382 | {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, | ||
383 | {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, | ||
384 | {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, | ||
385 | {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, | ||
386 | {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, | ||
387 | {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
388 | {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
389 | {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
390 | {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
391 | {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
392 | {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
393 | {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | ||
394 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
395 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
396 | {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
397 | {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
398 | {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
399 | {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, | ||
400 | {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, | ||
401 | {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, | ||
402 | {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, | ||
403 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | ||
404 | {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, | ||
405 | {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
406 | {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
407 | {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
408 | {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
409 | {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
410 | {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
411 | {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
412 | {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
413 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
414 | {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
415 | {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
416 | {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
417 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
418 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
419 | {0x00016048, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
420 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
421 | {0x00016288, 0x05a2040a, 0x05a2040a, 0x05a20408, 0x05a20408}, | ||
422 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
423 | {0x00016448, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
424 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
425 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
426 | {0x00016848, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
427 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
428 | }; | ||
310 | 429 | ||
311 | static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { | 430 | static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { |
312 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 431 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
@@ -414,8 +533,6 @@ static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { | |||
414 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 533 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
415 | }; | 534 | }; |
416 | 535 | ||
417 | #define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 | ||
418 | |||
419 | static const u32 ar9580_1p0_mac_core[][2] = { | 536 | static const u32 ar9580_1p0_mac_core[][2] = { |
420 | /* Addr allmodes */ | 537 | /* Addr allmodes */ |
421 | {0x00000008, 0x00000000}, | 538 | {0x00000008, 0x00000000}, |
@@ -679,14 +796,6 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { | |||
679 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 796 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
680 | }; | 797 | }; |
681 | 798 | ||
682 | #define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
683 | |||
684 | #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
685 | |||
686 | #define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 | ||
687 | |||
688 | #define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2 | ||
689 | |||
690 | static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { | 799 | static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { |
691 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 800 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
692 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | 801 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, |
@@ -761,160 +870,264 @@ static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { | |||
761 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 870 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
762 | }; | 871 | }; |
763 | 872 | ||
764 | static const u32 ar9580_1p0_soc_preamble[][2] = { | 873 | static const u32 ar9580_1p0_rx_gain_table[][2] = { |
765 | /* Addr allmodes */ | ||
766 | {0x000040a4, 0x00a0c1c9}, | ||
767 | {0x00007008, 0x00000000}, | ||
768 | {0x00007020, 0x00000000}, | ||
769 | {0x00007034, 0x00000002}, | ||
770 | {0x00007038, 0x000004c2}, | ||
771 | {0x00007048, 0x00000008}, | ||
772 | }; | ||
773 | |||
774 | #define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0 | ||
775 | |||
776 | static const u32 ar9580_1p0_radio_core[][2] = { | ||
777 | /* Addr allmodes */ | 874 | /* Addr allmodes */ |
778 | {0x00016000, 0x36db6db6}, | 875 | {0x0000a000, 0x00010000}, |
779 | {0x00016004, 0x6db6db40}, | 876 | {0x0000a004, 0x00030002}, |
780 | {0x00016008, 0x73f00000}, | 877 | {0x0000a008, 0x00050004}, |
781 | {0x0001600c, 0x00000000}, | 878 | {0x0000a00c, 0x00810080}, |
782 | {0x00016040, 0x7f80fff8}, | 879 | {0x0000a010, 0x00830082}, |
783 | {0x0001604c, 0x76d005b5}, | 880 | {0x0000a014, 0x01810180}, |
784 | {0x00016050, 0x556cf031}, | 881 | {0x0000a018, 0x01830182}, |
785 | {0x00016054, 0x13449440}, | 882 | {0x0000a01c, 0x01850184}, |
786 | {0x00016058, 0x0c51c92c}, | 883 | {0x0000a020, 0x01890188}, |
787 | {0x0001605c, 0x3db7fffc}, | 884 | {0x0000a024, 0x018b018a}, |
788 | {0x00016060, 0xfffffffc}, | 885 | {0x0000a028, 0x018d018c}, |
789 | {0x00016064, 0x000f0278}, | 886 | {0x0000a02c, 0x01910190}, |
790 | {0x0001606c, 0x6db60000}, | 887 | {0x0000a030, 0x01930192}, |
791 | {0x00016080, 0x00000000}, | 888 | {0x0000a034, 0x01950194}, |
792 | {0x00016084, 0x0e48048c}, | 889 | {0x0000a038, 0x038a0196}, |
793 | {0x00016088, 0x54214514}, | 890 | {0x0000a03c, 0x038c038b}, |
794 | {0x0001608c, 0x119f481e}, | 891 | {0x0000a040, 0x0390038d}, |
795 | {0x00016090, 0x24926490}, | 892 | {0x0000a044, 0x03920391}, |
796 | {0x00016098, 0xd2888888}, | 893 | {0x0000a048, 0x03940393}, |
797 | {0x000160a0, 0x0a108ffe}, | 894 | {0x0000a04c, 0x03960395}, |
798 | {0x000160a4, 0x812fc370}, | 895 | {0x0000a050, 0x00000000}, |
799 | {0x000160a8, 0x423c8000}, | 896 | {0x0000a054, 0x00000000}, |
800 | {0x000160b4, 0x92480080}, | 897 | {0x0000a058, 0x00000000}, |
801 | {0x000160c0, 0x00adb6d0}, | 898 | {0x0000a05c, 0x00000000}, |
802 | {0x000160c4, 0x6db6db60}, | 899 | {0x0000a060, 0x00000000}, |
803 | {0x000160c8, 0x6db6db6c}, | 900 | {0x0000a064, 0x00000000}, |
804 | {0x000160cc, 0x01e6c000}, | 901 | {0x0000a068, 0x00000000}, |
805 | {0x00016100, 0x3fffbe01}, | 902 | {0x0000a06c, 0x00000000}, |
806 | {0x00016104, 0xfff80000}, | 903 | {0x0000a070, 0x00000000}, |
807 | {0x00016108, 0x00080010}, | 904 | {0x0000a074, 0x00000000}, |
808 | {0x00016144, 0x02084080}, | 905 | {0x0000a078, 0x00000000}, |
809 | {0x00016148, 0x00000000}, | 906 | {0x0000a07c, 0x00000000}, |
810 | {0x00016280, 0x058a0001}, | 907 | {0x0000a080, 0x22222229}, |
811 | {0x00016284, 0x3d840208}, | 908 | {0x0000a084, 0x1d1d1d1d}, |
812 | {0x00016288, 0x05a20408}, | 909 | {0x0000a088, 0x1d1d1d1d}, |
813 | {0x0001628c, 0x00038c07}, | 910 | {0x0000a08c, 0x1d1d1d1d}, |
814 | {0x00016290, 0x00000004}, | 911 | {0x0000a090, 0x171d1d1d}, |
815 | {0x00016294, 0x458aa14f}, | 912 | {0x0000a094, 0x11111717}, |
816 | {0x00016380, 0x00000000}, | 913 | {0x0000a098, 0x00030311}, |
817 | {0x00016384, 0x00000000}, | 914 | {0x0000a09c, 0x00000000}, |
818 | {0x00016388, 0x00800700}, | 915 | {0x0000a0a0, 0x00000000}, |
819 | {0x0001638c, 0x00800700}, | 916 | {0x0000a0a4, 0x00000000}, |
820 | {0x00016390, 0x00800700}, | 917 | {0x0000a0a8, 0x00000000}, |
821 | {0x00016394, 0x00000000}, | 918 | {0x0000a0ac, 0x00000000}, |
822 | {0x00016398, 0x00000000}, | 919 | {0x0000a0b0, 0x00000000}, |
823 | {0x0001639c, 0x00000000}, | 920 | {0x0000a0b4, 0x00000000}, |
824 | {0x000163a0, 0x00000001}, | 921 | {0x0000a0b8, 0x00000000}, |
825 | {0x000163a4, 0x00000001}, | 922 | {0x0000a0bc, 0x00000000}, |
826 | {0x000163a8, 0x00000000}, | 923 | {0x0000a0c0, 0x001f0000}, |
827 | {0x000163ac, 0x00000000}, | 924 | {0x0000a0c4, 0x01000101}, |
828 | {0x000163b0, 0x00000000}, | 925 | {0x0000a0c8, 0x011e011f}, |
829 | {0x000163b4, 0x00000000}, | 926 | {0x0000a0cc, 0x011c011d}, |
830 | {0x000163b8, 0x00000000}, | 927 | {0x0000a0d0, 0x02030204}, |
831 | {0x000163bc, 0x00000000}, | 928 | {0x0000a0d4, 0x02010202}, |
832 | {0x000163c0, 0x000000a0}, | 929 | {0x0000a0d8, 0x021f0200}, |
833 | {0x000163c4, 0x000c0000}, | 930 | {0x0000a0dc, 0x0302021e}, |
834 | {0x000163c8, 0x14021402}, | 931 | {0x0000a0e0, 0x03000301}, |
835 | {0x000163cc, 0x00001402}, | 932 | {0x0000a0e4, 0x031e031f}, |
836 | {0x000163d0, 0x00000000}, | 933 | {0x0000a0e8, 0x0402031d}, |
837 | {0x000163d4, 0x00000000}, | 934 | {0x0000a0ec, 0x04000401}, |
838 | {0x00016400, 0x36db6db6}, | 935 | {0x0000a0f0, 0x041e041f}, |
839 | {0x00016404, 0x6db6db40}, | 936 | {0x0000a0f4, 0x0502041d}, |
840 | {0x00016408, 0x73f00000}, | 937 | {0x0000a0f8, 0x05000501}, |
841 | {0x0001640c, 0x00000000}, | 938 | {0x0000a0fc, 0x051e051f}, |
842 | {0x00016440, 0x7f80fff8}, | 939 | {0x0000a100, 0x06010602}, |
843 | {0x0001644c, 0x76d005b5}, | 940 | {0x0000a104, 0x061f0600}, |
844 | {0x00016450, 0x556cf031}, | 941 | {0x0000a108, 0x061d061e}, |
845 | {0x00016454, 0x13449440}, | 942 | {0x0000a10c, 0x07020703}, |
846 | {0x00016458, 0x0c51c92c}, | 943 | {0x0000a110, 0x07000701}, |
847 | {0x0001645c, 0x3db7fffc}, | 944 | {0x0000a114, 0x00000000}, |
848 | {0x00016460, 0xfffffffc}, | 945 | {0x0000a118, 0x00000000}, |
849 | {0x00016464, 0x000f0278}, | 946 | {0x0000a11c, 0x00000000}, |
850 | {0x0001646c, 0x6db60000}, | 947 | {0x0000a120, 0x00000000}, |
851 | {0x00016500, 0x3fffbe01}, | 948 | {0x0000a124, 0x00000000}, |
852 | {0x00016504, 0xfff80000}, | 949 | {0x0000a128, 0x00000000}, |
853 | {0x00016508, 0x00080010}, | 950 | {0x0000a12c, 0x00000000}, |
854 | {0x00016544, 0x02084080}, | 951 | {0x0000a130, 0x00000000}, |
855 | {0x00016548, 0x00000000}, | 952 | {0x0000a134, 0x00000000}, |
856 | {0x00016780, 0x00000000}, | 953 | {0x0000a138, 0x00000000}, |
857 | {0x00016784, 0x00000000}, | 954 | {0x0000a13c, 0x00000000}, |
858 | {0x00016788, 0x00800700}, | 955 | {0x0000a140, 0x001f0000}, |
859 | {0x0001678c, 0x00800700}, | 956 | {0x0000a144, 0x01000101}, |
860 | {0x00016790, 0x00800700}, | 957 | {0x0000a148, 0x011e011f}, |
861 | {0x00016794, 0x00000000}, | 958 | {0x0000a14c, 0x011c011d}, |
862 | {0x00016798, 0x00000000}, | 959 | {0x0000a150, 0x02030204}, |
863 | {0x0001679c, 0x00000000}, | 960 | {0x0000a154, 0x02010202}, |
864 | {0x000167a0, 0x00000001}, | 961 | {0x0000a158, 0x021f0200}, |
865 | {0x000167a4, 0x00000001}, | 962 | {0x0000a15c, 0x0302021e}, |
866 | {0x000167a8, 0x00000000}, | 963 | {0x0000a160, 0x03000301}, |
867 | {0x000167ac, 0x00000000}, | 964 | {0x0000a164, 0x031e031f}, |
868 | {0x000167b0, 0x00000000}, | 965 | {0x0000a168, 0x0402031d}, |
869 | {0x000167b4, 0x00000000}, | 966 | {0x0000a16c, 0x04000401}, |
870 | {0x000167b8, 0x00000000}, | 967 | {0x0000a170, 0x041e041f}, |
871 | {0x000167bc, 0x00000000}, | 968 | {0x0000a174, 0x0502041d}, |
872 | {0x000167c0, 0x000000a0}, | 969 | {0x0000a178, 0x05000501}, |
873 | {0x000167c4, 0x000c0000}, | 970 | {0x0000a17c, 0x051e051f}, |
874 | {0x000167c8, 0x14021402}, | 971 | {0x0000a180, 0x06010602}, |
875 | {0x000167cc, 0x00001402}, | 972 | {0x0000a184, 0x061f0600}, |
876 | {0x000167d0, 0x00000000}, | 973 | {0x0000a188, 0x061d061e}, |
877 | {0x000167d4, 0x00000000}, | 974 | {0x0000a18c, 0x07020703}, |
878 | {0x00016800, 0x36db6db6}, | 975 | {0x0000a190, 0x07000701}, |
879 | {0x00016804, 0x6db6db40}, | 976 | {0x0000a194, 0x00000000}, |
880 | {0x00016808, 0x73f00000}, | 977 | {0x0000a198, 0x00000000}, |
881 | {0x0001680c, 0x00000000}, | 978 | {0x0000a19c, 0x00000000}, |
882 | {0x00016840, 0x7f80fff8}, | 979 | {0x0000a1a0, 0x00000000}, |
883 | {0x0001684c, 0x76d005b5}, | 980 | {0x0000a1a4, 0x00000000}, |
884 | {0x00016850, 0x556cf031}, | 981 | {0x0000a1a8, 0x00000000}, |
885 | {0x00016854, 0x13449440}, | 982 | {0x0000a1ac, 0x00000000}, |
886 | {0x00016858, 0x0c51c92c}, | 983 | {0x0000a1b0, 0x00000000}, |
887 | {0x0001685c, 0x3db7fffc}, | 984 | {0x0000a1b4, 0x00000000}, |
888 | {0x00016860, 0xfffffffc}, | 985 | {0x0000a1b8, 0x00000000}, |
889 | {0x00016864, 0x000f0278}, | 986 | {0x0000a1bc, 0x00000000}, |
890 | {0x0001686c, 0x6db60000}, | 987 | {0x0000a1c0, 0x00000000}, |
891 | {0x00016900, 0x3fffbe01}, | 988 | {0x0000a1c4, 0x00000000}, |
892 | {0x00016904, 0xfff80000}, | 989 | {0x0000a1c8, 0x00000000}, |
893 | {0x00016908, 0x00080010}, | 990 | {0x0000a1cc, 0x00000000}, |
894 | {0x00016944, 0x02084080}, | 991 | {0x0000a1d0, 0x00000000}, |
895 | {0x00016948, 0x00000000}, | 992 | {0x0000a1d4, 0x00000000}, |
896 | {0x00016b80, 0x00000000}, | 993 | {0x0000a1d8, 0x00000000}, |
897 | {0x00016b84, 0x00000000}, | 994 | {0x0000a1dc, 0x00000000}, |
898 | {0x00016b88, 0x00800700}, | 995 | {0x0000a1e0, 0x00000000}, |
899 | {0x00016b8c, 0x00800700}, | 996 | {0x0000a1e4, 0x00000000}, |
900 | {0x00016b90, 0x00800700}, | 997 | {0x0000a1e8, 0x00000000}, |
901 | {0x00016b94, 0x00000000}, | 998 | {0x0000a1ec, 0x00000000}, |
902 | {0x00016b98, 0x00000000}, | 999 | {0x0000a1f0, 0x00000396}, |
903 | {0x00016b9c, 0x00000000}, | 1000 | {0x0000a1f4, 0x00000396}, |
904 | {0x00016ba0, 0x00000001}, | 1001 | {0x0000a1f8, 0x00000396}, |
905 | {0x00016ba4, 0x00000001}, | 1002 | {0x0000a1fc, 0x00000196}, |
906 | {0x00016ba8, 0x00000000}, | 1003 | {0x0000b000, 0x00010000}, |
907 | {0x00016bac, 0x00000000}, | 1004 | {0x0000b004, 0x00030002}, |
908 | {0x00016bb0, 0x00000000}, | 1005 | {0x0000b008, 0x00050004}, |
909 | {0x00016bb4, 0x00000000}, | 1006 | {0x0000b00c, 0x00810080}, |
910 | {0x00016bb8, 0x00000000}, | 1007 | {0x0000b010, 0x00830082}, |
911 | {0x00016bbc, 0x00000000}, | 1008 | {0x0000b014, 0x01810180}, |
912 | {0x00016bc0, 0x000000a0}, | 1009 | {0x0000b018, 0x01830182}, |
913 | {0x00016bc4, 0x000c0000}, | 1010 | {0x0000b01c, 0x01850184}, |
914 | {0x00016bc8, 0x14021402}, | 1011 | {0x0000b020, 0x02810280}, |
915 | {0x00016bcc, 0x00001402}, | 1012 | {0x0000b024, 0x02830282}, |
916 | {0x00016bd0, 0x00000000}, | 1013 | {0x0000b028, 0x02850284}, |
917 | {0x00016bd4, 0x00000000}, | 1014 | {0x0000b02c, 0x02890288}, |
1015 | {0x0000b030, 0x028b028a}, | ||
1016 | {0x0000b034, 0x0388028c}, | ||
1017 | {0x0000b038, 0x038a0389}, | ||
1018 | {0x0000b03c, 0x038c038b}, | ||
1019 | {0x0000b040, 0x0390038d}, | ||
1020 | {0x0000b044, 0x03920391}, | ||
1021 | {0x0000b048, 0x03940393}, | ||
1022 | {0x0000b04c, 0x03960395}, | ||
1023 | {0x0000b050, 0x00000000}, | ||
1024 | {0x0000b054, 0x00000000}, | ||
1025 | {0x0000b058, 0x00000000}, | ||
1026 | {0x0000b05c, 0x00000000}, | ||
1027 | {0x0000b060, 0x00000000}, | ||
1028 | {0x0000b064, 0x00000000}, | ||
1029 | {0x0000b068, 0x00000000}, | ||
1030 | {0x0000b06c, 0x00000000}, | ||
1031 | {0x0000b070, 0x00000000}, | ||
1032 | {0x0000b074, 0x00000000}, | ||
1033 | {0x0000b078, 0x00000000}, | ||
1034 | {0x0000b07c, 0x00000000}, | ||
1035 | {0x0000b080, 0x23232323}, | ||
1036 | {0x0000b084, 0x21232323}, | ||
1037 | {0x0000b088, 0x19191c1e}, | ||
1038 | {0x0000b08c, 0x12141417}, | ||
1039 | {0x0000b090, 0x07070e0e}, | ||
1040 | {0x0000b094, 0x03030305}, | ||
1041 | {0x0000b098, 0x00000003}, | ||
1042 | {0x0000b09c, 0x00000000}, | ||
1043 | {0x0000b0a0, 0x00000000}, | ||
1044 | {0x0000b0a4, 0x00000000}, | ||
1045 | {0x0000b0a8, 0x00000000}, | ||
1046 | {0x0000b0ac, 0x00000000}, | ||
1047 | {0x0000b0b0, 0x00000000}, | ||
1048 | {0x0000b0b4, 0x00000000}, | ||
1049 | {0x0000b0b8, 0x00000000}, | ||
1050 | {0x0000b0bc, 0x00000000}, | ||
1051 | {0x0000b0c0, 0x003f0020}, | ||
1052 | {0x0000b0c4, 0x00400041}, | ||
1053 | {0x0000b0c8, 0x0140005f}, | ||
1054 | {0x0000b0cc, 0x0160015f}, | ||
1055 | {0x0000b0d0, 0x017e017f}, | ||
1056 | {0x0000b0d4, 0x02410242}, | ||
1057 | {0x0000b0d8, 0x025f0240}, | ||
1058 | {0x0000b0dc, 0x027f0260}, | ||
1059 | {0x0000b0e0, 0x0341027e}, | ||
1060 | {0x0000b0e4, 0x035f0340}, | ||
1061 | {0x0000b0e8, 0x037f0360}, | ||
1062 | {0x0000b0ec, 0x04400441}, | ||
1063 | {0x0000b0f0, 0x0460045f}, | ||
1064 | {0x0000b0f4, 0x0541047f}, | ||
1065 | {0x0000b0f8, 0x055f0540}, | ||
1066 | {0x0000b0fc, 0x057f0560}, | ||
1067 | {0x0000b100, 0x06400641}, | ||
1068 | {0x0000b104, 0x0660065f}, | ||
1069 | {0x0000b108, 0x067e067f}, | ||
1070 | {0x0000b10c, 0x07410742}, | ||
1071 | {0x0000b110, 0x075f0740}, | ||
1072 | {0x0000b114, 0x077f0760}, | ||
1073 | {0x0000b118, 0x07800781}, | ||
1074 | {0x0000b11c, 0x07a0079f}, | ||
1075 | {0x0000b120, 0x07c107bf}, | ||
1076 | {0x0000b124, 0x000007c0}, | ||
1077 | {0x0000b128, 0x00000000}, | ||
1078 | {0x0000b12c, 0x00000000}, | ||
1079 | {0x0000b130, 0x00000000}, | ||
1080 | {0x0000b134, 0x00000000}, | ||
1081 | {0x0000b138, 0x00000000}, | ||
1082 | {0x0000b13c, 0x00000000}, | ||
1083 | {0x0000b140, 0x003f0020}, | ||
1084 | {0x0000b144, 0x00400041}, | ||
1085 | {0x0000b148, 0x0140005f}, | ||
1086 | {0x0000b14c, 0x0160015f}, | ||
1087 | {0x0000b150, 0x017e017f}, | ||
1088 | {0x0000b154, 0x02410242}, | ||
1089 | {0x0000b158, 0x025f0240}, | ||
1090 | {0x0000b15c, 0x027f0260}, | ||
1091 | {0x0000b160, 0x0341027e}, | ||
1092 | {0x0000b164, 0x035f0340}, | ||
1093 | {0x0000b168, 0x037f0360}, | ||
1094 | {0x0000b16c, 0x04400441}, | ||
1095 | {0x0000b170, 0x0460045f}, | ||
1096 | {0x0000b174, 0x0541047f}, | ||
1097 | {0x0000b178, 0x055f0540}, | ||
1098 | {0x0000b17c, 0x057f0560}, | ||
1099 | {0x0000b180, 0x06400641}, | ||
1100 | {0x0000b184, 0x0660065f}, | ||
1101 | {0x0000b188, 0x067e067f}, | ||
1102 | {0x0000b18c, 0x07410742}, | ||
1103 | {0x0000b190, 0x075f0740}, | ||
1104 | {0x0000b194, 0x077f0760}, | ||
1105 | {0x0000b198, 0x07800781}, | ||
1106 | {0x0000b19c, 0x07a0079f}, | ||
1107 | {0x0000b1a0, 0x07c107bf}, | ||
1108 | {0x0000b1a4, 0x000007c0}, | ||
1109 | {0x0000b1a8, 0x00000000}, | ||
1110 | {0x0000b1ac, 0x00000000}, | ||
1111 | {0x0000b1b0, 0x00000000}, | ||
1112 | {0x0000b1b4, 0x00000000}, | ||
1113 | {0x0000b1b8, 0x00000000}, | ||
1114 | {0x0000b1bc, 0x00000000}, | ||
1115 | {0x0000b1c0, 0x00000000}, | ||
1116 | {0x0000b1c4, 0x00000000}, | ||
1117 | {0x0000b1c8, 0x00000000}, | ||
1118 | {0x0000b1cc, 0x00000000}, | ||
1119 | {0x0000b1d0, 0x00000000}, | ||
1120 | {0x0000b1d4, 0x00000000}, | ||
1121 | {0x0000b1d8, 0x00000000}, | ||
1122 | {0x0000b1dc, 0x00000000}, | ||
1123 | {0x0000b1e0, 0x00000000}, | ||
1124 | {0x0000b1e4, 0x00000000}, | ||
1125 | {0x0000b1e8, 0x00000000}, | ||
1126 | {0x0000b1ec, 0x00000000}, | ||
1127 | {0x0000b1f0, 0x00000396}, | ||
1128 | {0x0000b1f4, 0x00000396}, | ||
1129 | {0x0000b1f8, 0x00000396}, | ||
1130 | {0x0000b1fc, 0x00000196}, | ||
918 | }; | 1131 | }; |
919 | 1132 | ||
920 | static const u32 ar9580_1p0_baseband_postamble[][5] = { | 1133 | static const u32 ar9580_1p0_baseband_postamble[][5] = { |
@@ -956,7 +1169,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { | |||
956 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 1169 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
957 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 1170 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
958 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 1171 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, |
959 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, | 1172 | {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, |
960 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 1173 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
961 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1174 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
962 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 1175 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 60a5da53668f..5e5d5cb2458c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -459,6 +459,7 @@ void ath_check_ani(struct ath_softc *sc); | |||
459 | int ath_update_survey_stats(struct ath_softc *sc); | 459 | int ath_update_survey_stats(struct ath_softc *sc); |
460 | void ath_update_survey_nf(struct ath_softc *sc, int channel); | 460 | void ath_update_survey_nf(struct ath_softc *sc, int channel); |
461 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); | 461 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); |
462 | void ath_ps_full_sleep(unsigned long data); | ||
462 | 463 | ||
463 | /**********/ | 464 | /**********/ |
464 | /* BTCOEX */ | 465 | /* BTCOEX */ |
@@ -570,6 +571,34 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
570 | } | 571 | } |
571 | #endif | 572 | #endif |
572 | 573 | ||
574 | /************************/ | ||
575 | /* Wake on Wireless LAN */ | ||
576 | /************************/ | ||
577 | |||
578 | #ifdef CONFIG_ATH9K_WOW | ||
579 | void ath9k_init_wow(struct ieee80211_hw *hw); | ||
580 | int ath9k_suspend(struct ieee80211_hw *hw, | ||
581 | struct cfg80211_wowlan *wowlan); | ||
582 | int ath9k_resume(struct ieee80211_hw *hw); | ||
583 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); | ||
584 | #else | ||
585 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) | ||
586 | { | ||
587 | } | ||
588 | static inline int ath9k_suspend(struct ieee80211_hw *hw, | ||
589 | struct cfg80211_wowlan *wowlan) | ||
590 | { | ||
591 | return 0; | ||
592 | } | ||
593 | static inline int ath9k_resume(struct ieee80211_hw *hw) | ||
594 | { | ||
595 | return 0; | ||
596 | } | ||
597 | static inline void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | ||
598 | { | ||
599 | } | ||
600 | #endif /* CONFIG_ATH9K_WOW */ | ||
601 | |||
573 | /*******************************/ | 602 | /*******************************/ |
574 | /* Antenna diversity/combining */ | 603 | /* Antenna diversity/combining */ |
575 | /*******************************/ | 604 | /*******************************/ |
@@ -642,6 +671,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
642 | #define ATH9K_PCI_AR9565_1ANT 0x0080 | 671 | #define ATH9K_PCI_AR9565_1ANT 0x0080 |
643 | #define ATH9K_PCI_AR9565_2ANT 0x0100 | 672 | #define ATH9K_PCI_AR9565_2ANT 0x0100 |
644 | #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 | 673 | #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 |
674 | #define ATH9K_PCI_KILLER 0x0400 | ||
645 | 675 | ||
646 | /* | 676 | /* |
647 | * Default cache line size, in bytes. | 677 | * Default cache line size, in bytes. |
@@ -724,6 +754,7 @@ struct ath_softc { | |||
724 | struct work_struct hw_check_work; | 754 | struct work_struct hw_check_work; |
725 | struct work_struct hw_reset_work; | 755 | struct work_struct hw_reset_work; |
726 | struct completion paprd_complete; | 756 | struct completion paprd_complete; |
757 | wait_queue_head_t tx_wait; | ||
727 | 758 | ||
728 | unsigned int hw_busy_count; | 759 | unsigned int hw_busy_count; |
729 | unsigned long sc_flags; | 760 | unsigned long sc_flags; |
@@ -760,6 +791,7 @@ struct ath_softc { | |||
760 | struct delayed_work tx_complete_work; | 791 | struct delayed_work tx_complete_work; |
761 | struct delayed_work hw_pll_work; | 792 | struct delayed_work hw_pll_work; |
762 | struct timer_list rx_poll_timer; | 793 | struct timer_list rx_poll_timer; |
794 | struct timer_list sleep_timer; | ||
763 | 795 | ||
764 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 796 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
765 | struct ath_btcoex btcoex; | 797 | struct ath_btcoex btcoex; |
@@ -784,7 +816,7 @@ struct ath_softc { | |||
784 | bool tx99_state; | 816 | bool tx99_state; |
785 | s16 tx99_power; | 817 | s16 tx99_power; |
786 | 818 | ||
787 | #ifdef CONFIG_PM_SLEEP | 819 | #ifdef CONFIG_ATH9K_WOW |
788 | atomic_t wow_got_bmiss_intr; | 820 | atomic_t wow_got_bmiss_intr; |
789 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ | 821 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ |
790 | u32 wow_intr_before_sleep; | 822 | u32 wow_intr_before_sleep; |
@@ -947,10 +979,25 @@ struct fft_sample_ht20_40 { | |||
947 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | 979 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; |
948 | } __packed; | 980 | } __packed; |
949 | 981 | ||
950 | int ath9k_tx99_init(struct ath_softc *sc); | 982 | /********/ |
951 | void ath9k_tx99_deinit(struct ath_softc *sc); | 983 | /* TX99 */ |
984 | /********/ | ||
985 | |||
986 | #ifdef CONFIG_ATH9K_TX99 | ||
987 | void ath9k_tx99_init_debug(struct ath_softc *sc); | ||
952 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | 988 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, |
953 | struct ath_tx_control *txctl); | 989 | struct ath_tx_control *txctl); |
990 | #else | ||
991 | static inline void ath9k_tx99_init_debug(struct ath_softc *sc) | ||
992 | { | ||
993 | } | ||
994 | static inline int ath9k_tx99_send(struct ath_softc *sc, | ||
995 | struct sk_buff *skb, | ||
996 | struct ath_tx_control *txctl) | ||
997 | { | ||
998 | return 0; | ||
999 | } | ||
1000 | #endif /* CONFIG_ATH9K_TX99 */ | ||
954 | 1001 | ||
955 | void ath9k_tasklet(unsigned long data); | 1002 | void ath9k_tasklet(unsigned long data); |
956 | int ath_cabq_update(struct ath_softc *); | 1003 | int ath_cabq_update(struct ath_softc *); |
@@ -967,6 +1014,9 @@ extern bool is_ath9k_unloaded; | |||
967 | 1014 | ||
968 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); | 1015 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); |
969 | irqreturn_t ath_isr(int irq, void *dev); | 1016 | irqreturn_t ath_isr(int irq, void *dev); |
1017 | int ath_reset(struct ath_softc *sc); | ||
1018 | void ath_cancel_work(struct ath_softc *sc); | ||
1019 | void ath_restart_work(struct ath_softc *sc); | ||
970 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 1020 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
971 | const struct ath_bus_ops *bus_ops); | 1021 | const struct ath_bus_ops *bus_ops); |
972 | void ath9k_deinit_device(struct ath_softc *sc); | 1022 | void ath9k_deinit_device(struct ath_softc *sc); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 83a2c59f680b..2f7dccfdb727 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1778,111 +1778,6 @@ void ath9k_deinit_debug(struct ath_softc *sc) | |||
1778 | } | 1778 | } |
1779 | } | 1779 | } |
1780 | 1780 | ||
1781 | static ssize_t read_file_tx99(struct file *file, char __user *user_buf, | ||
1782 | size_t count, loff_t *ppos) | ||
1783 | { | ||
1784 | struct ath_softc *sc = file->private_data; | ||
1785 | char buf[3]; | ||
1786 | unsigned int len; | ||
1787 | |||
1788 | len = sprintf(buf, "%d\n", sc->tx99_state); | ||
1789 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1790 | } | ||
1791 | |||
1792 | static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, | ||
1793 | size_t count, loff_t *ppos) | ||
1794 | { | ||
1795 | struct ath_softc *sc = file->private_data; | ||
1796 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1797 | char buf[32]; | ||
1798 | bool start; | ||
1799 | ssize_t len; | ||
1800 | int r; | ||
1801 | |||
1802 | if (sc->nvifs > 1) | ||
1803 | return -EOPNOTSUPP; | ||
1804 | |||
1805 | len = min(count, sizeof(buf) - 1); | ||
1806 | if (copy_from_user(buf, user_buf, len)) | ||
1807 | return -EFAULT; | ||
1808 | |||
1809 | if (strtobool(buf, &start)) | ||
1810 | return -EINVAL; | ||
1811 | |||
1812 | if (start == sc->tx99_state) { | ||
1813 | if (!start) | ||
1814 | return count; | ||
1815 | ath_dbg(common, XMIT, "Resetting TX99\n"); | ||
1816 | ath9k_tx99_deinit(sc); | ||
1817 | } | ||
1818 | |||
1819 | if (!start) { | ||
1820 | ath9k_tx99_deinit(sc); | ||
1821 | return count; | ||
1822 | } | ||
1823 | |||
1824 | r = ath9k_tx99_init(sc); | ||
1825 | if (r) | ||
1826 | return r; | ||
1827 | |||
1828 | return count; | ||
1829 | } | ||
1830 | |||
1831 | static const struct file_operations fops_tx99 = { | ||
1832 | .read = read_file_tx99, | ||
1833 | .write = write_file_tx99, | ||
1834 | .open = simple_open, | ||
1835 | .owner = THIS_MODULE, | ||
1836 | .llseek = default_llseek, | ||
1837 | }; | ||
1838 | |||
1839 | static ssize_t read_file_tx99_power(struct file *file, | ||
1840 | char __user *user_buf, | ||
1841 | size_t count, loff_t *ppos) | ||
1842 | { | ||
1843 | struct ath_softc *sc = file->private_data; | ||
1844 | char buf[32]; | ||
1845 | unsigned int len; | ||
1846 | |||
1847 | len = sprintf(buf, "%d (%d dBm)\n", | ||
1848 | sc->tx99_power, | ||
1849 | sc->tx99_power / 2); | ||
1850 | |||
1851 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1852 | } | ||
1853 | |||
1854 | static ssize_t write_file_tx99_power(struct file *file, | ||
1855 | const char __user *user_buf, | ||
1856 | size_t count, loff_t *ppos) | ||
1857 | { | ||
1858 | struct ath_softc *sc = file->private_data; | ||
1859 | int r; | ||
1860 | u8 tx_power; | ||
1861 | |||
1862 | r = kstrtou8_from_user(user_buf, count, 0, &tx_power); | ||
1863 | if (r) | ||
1864 | return r; | ||
1865 | |||
1866 | if (tx_power > MAX_RATE_POWER) | ||
1867 | return -EINVAL; | ||
1868 | |||
1869 | sc->tx99_power = tx_power; | ||
1870 | |||
1871 | ath9k_ps_wakeup(sc); | ||
1872 | ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); | ||
1873 | ath9k_ps_restore(sc); | ||
1874 | |||
1875 | return count; | ||
1876 | } | ||
1877 | |||
1878 | static const struct file_operations fops_tx99_power = { | ||
1879 | .read = read_file_tx99_power, | ||
1880 | .write = write_file_tx99_power, | ||
1881 | .open = simple_open, | ||
1882 | .owner = THIS_MODULE, | ||
1883 | .llseek = default_llseek, | ||
1884 | }; | ||
1885 | |||
1886 | int ath9k_init_debug(struct ath_hw *ah) | 1781 | int ath9k_init_debug(struct ath_hw *ah) |
1887 | { | 1782 | { |
1888 | struct ath_common *common = ath9k_hw_common(ah); | 1783 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1899,6 +1794,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1899 | #endif | 1794 | #endif |
1900 | 1795 | ||
1901 | ath9k_dfs_init_debug(sc); | 1796 | ath9k_dfs_init_debug(sc); |
1797 | ath9k_tx99_init_debug(sc); | ||
1902 | 1798 | ||
1903 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1799 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1904 | &fops_dma); | 1800 | &fops_dma); |
@@ -1974,15 +1870,6 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1974 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | 1870 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, |
1975 | &fops_btcoex); | 1871 | &fops_btcoex); |
1976 | #endif | 1872 | #endif |
1977 | if (config_enabled(CONFIG_ATH9K_TX99) && | ||
1978 | AR_SREV_9300_20_OR_LATER(ah)) { | ||
1979 | debugfs_create_file("tx99", S_IRUSR | S_IWUSR, | ||
1980 | sc->debug.debugfs_phy, sc, | ||
1981 | &fops_tx99); | ||
1982 | debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, | ||
1983 | sc->debug.debugfs_phy, sc, | ||
1984 | &fops_tx99_power); | ||
1985 | } | ||
1986 | 1873 | ||
1987 | return 0; | 1874 | return 0; |
1988 | } | 1875 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8918035da3a3..779d38a98a0e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/time.h> | ||
20 | #include <asm/unaligned.h> | 21 | #include <asm/unaligned.h> |
21 | 22 | ||
22 | #include "hw.h" | 23 | #include "hw.h" |
@@ -453,7 +454,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
453 | } | 454 | } |
454 | 455 | ||
455 | ah->config.rx_intr_mitigation = true; | 456 | ah->config.rx_intr_mitigation = true; |
456 | ah->config.pcieSerDesWrite = true; | ||
457 | 457 | ||
458 | /* | 458 | /* |
459 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 459 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
@@ -1501,8 +1501,9 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1501 | int r; | 1501 | int r; |
1502 | 1502 | ||
1503 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { | 1503 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { |
1504 | band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); | 1504 | u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags; |
1505 | mode_diff = (chan->channelFlags != ah->curchan->channelFlags); | 1505 | band_switch = !!(flags_diff & CHANNEL_5GHZ); |
1506 | mode_diff = !!(flags_diff & ~CHANNEL_HT); | ||
1506 | } | 1507 | } |
1507 | 1508 | ||
1508 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1509 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
@@ -1814,7 +1815,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1814 | * If cross-band fcc is not supoprted, bail out if channelFlags differ. | 1815 | * If cross-band fcc is not supoprted, bail out if channelFlags differ. |
1815 | */ | 1816 | */ |
1816 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && | 1817 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && |
1817 | chan->channelFlags != ah->curchan->channelFlags) | 1818 | ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT)) |
1818 | goto fail; | 1819 | goto fail; |
1819 | 1820 | ||
1820 | if (!ath9k_hw_check_alive(ah)) | 1821 | if (!ath9k_hw_check_alive(ah)) |
@@ -1855,10 +1856,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1855 | struct ath9k_hw_cal_data *caldata, bool fastcc) | 1856 | struct ath9k_hw_cal_data *caldata, bool fastcc) |
1856 | { | 1857 | { |
1857 | struct ath_common *common = ath9k_hw_common(ah); | 1858 | struct ath_common *common = ath9k_hw_common(ah); |
1859 | struct timespec ts; | ||
1858 | u32 saveLedState; | 1860 | u32 saveLedState; |
1859 | u32 saveDefAntenna; | 1861 | u32 saveDefAntenna; |
1860 | u32 macStaId1; | 1862 | u32 macStaId1; |
1861 | u64 tsf = 0; | 1863 | u64 tsf = 0; |
1864 | s64 usec = 0; | ||
1862 | int r; | 1865 | int r; |
1863 | bool start_mci_reset = false; | 1866 | bool start_mci_reset = false; |
1864 | bool save_fullsleep = ah->chip_fullsleep; | 1867 | bool save_fullsleep = ah->chip_fullsleep; |
@@ -1901,10 +1904,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1901 | 1904 | ||
1902 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; | 1905 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; |
1903 | 1906 | ||
1904 | /* For chips on which RTC reset is done, save TSF before it gets cleared */ | 1907 | /* Save TSF before chip reset, a cold reset clears it */ |
1905 | if (AR_SREV_9100(ah) || | 1908 | tsf = ath9k_hw_gettsf64(ah); |
1906 | (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) | 1909 | getrawmonotonic(&ts); |
1907 | tsf = ath9k_hw_gettsf64(ah); | 1910 | usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000; |
1908 | 1911 | ||
1909 | saveLedState = REG_READ(ah, AR_CFG_LED) & | 1912 | saveLedState = REG_READ(ah, AR_CFG_LED) & |
1910 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | 1913 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | |
@@ -1937,8 +1940,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1937 | } | 1940 | } |
1938 | 1941 | ||
1939 | /* Restore TSF */ | 1942 | /* Restore TSF */ |
1940 | if (tsf) | 1943 | getrawmonotonic(&ts); |
1941 | ath9k_hw_settsf64(ah, tsf); | 1944 | usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec; |
1945 | ath9k_hw_settsf64(ah, tsf + usec); | ||
1942 | 1946 | ||
1943 | if (AR_SREV_9280_20_OR_LATER(ah)) | 1947 | if (AR_SREV_9280_20_OR_LATER(ah)) |
1944 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 1948 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a2c9a5dbac6b..e50843600989 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -283,7 +283,6 @@ struct ath9k_ops_config { | |||
283 | int additional_swba_backoff; | 283 | int additional_swba_backoff; |
284 | int ack_6mb; | 284 | int ack_6mb; |
285 | u32 cwm_ignore_extcca; | 285 | u32 cwm_ignore_extcca; |
286 | bool pcieSerDesWrite; | ||
287 | u8 pcie_clock_req; | 286 | u8 pcie_clock_req; |
288 | u32 pcie_waen; | 287 | u32 pcie_waen; |
289 | u8 analog_shiftreg; | 288 | u8 analog_shiftreg; |
@@ -921,7 +920,7 @@ struct ath_hw { | |||
921 | /* Enterprise mode cap */ | 920 | /* Enterprise mode cap */ |
922 | u32 ent_mode; | 921 | u32 ent_mode; |
923 | 922 | ||
924 | #ifdef CONFIG_PM_SLEEP | 923 | #ifdef CONFIG_ATH9K_WOW |
925 | u32 wow_event_mask; | 924 | u32 wow_event_mask; |
926 | #endif | 925 | #endif |
927 | bool is_clk_25mhz; | 926 | bool is_clk_25mhz; |
@@ -1127,7 +1126,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) | |||
1127 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 1126 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
1128 | 1127 | ||
1129 | 1128 | ||
1130 | #ifdef CONFIG_PM_SLEEP | 1129 | #ifdef CONFIG_ATH9K_WOW |
1131 | const char *ath9k_hw_wow_event_to_string(u32 wow_event); | 1130 | const char *ath9k_hw_wow_event_to_string(u32 wow_event); |
1132 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 1131 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
1133 | u8 *user_mask, int pattern_count, | 1132 | u8 *user_mask, int pattern_count, |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 710192ed27ed..8f4c1674b76e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -589,6 +589,9 @@ static void ath9k_init_platform(struct ath_softc *sc) | |||
589 | if (sc->driver_data & ATH9K_PCI_AR9565_2ANT) | 589 | if (sc->driver_data & ATH9K_PCI_AR9565_2ANT) |
590 | ath_info(common, "WB335 2-ANT card detected\n"); | 590 | ath_info(common, "WB335 2-ANT card detected\n"); |
591 | 591 | ||
592 | if (sc->driver_data & ATH9K_PCI_KILLER) | ||
593 | ath_info(common, "Killer Wireless card detected\n"); | ||
594 | |||
592 | /* | 595 | /* |
593 | * Some WB335 cards do not support antenna diversity. Since | 596 | * Some WB335 cards do not support antenna diversity. Since |
594 | * we use a hardcoded value for AR9565 instead of using the | 597 | * we use a hardcoded value for AR9565 instead of using the |
@@ -688,6 +691,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
688 | common = ath9k_hw_common(ah); | 691 | common = ath9k_hw_common(ah); |
689 | sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); | 692 | sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); |
690 | sc->tx99_power = MAX_RATE_POWER + 1; | 693 | sc->tx99_power = MAX_RATE_POWER + 1; |
694 | init_waitqueue_head(&sc->tx_wait); | ||
691 | 695 | ||
692 | if (!pdata) { | 696 | if (!pdata) { |
693 | ah->ah_flags |= AH_USE_EEPROM; | 697 | ah->ah_flags |= AH_USE_EEPROM; |
@@ -735,6 +739,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
735 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | 739 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, |
736 | (unsigned long)sc); | 740 | (unsigned long)sc); |
737 | 741 | ||
742 | setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc); | ||
738 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); | 743 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); |
739 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | 744 | INIT_WORK(&sc->hw_check_work, ath_hw_check); |
740 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 745 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
@@ -873,15 +878,6 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
873 | } | 878 | } |
874 | }; | 879 | }; |
875 | 880 | ||
876 | #ifdef CONFIG_PM | ||
877 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { | ||
878 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, | ||
879 | .n_patterns = MAX_NUM_USER_PATTERN, | ||
880 | .pattern_min_len = 1, | ||
881 | .pattern_max_len = MAX_PATTERN_SIZE, | ||
882 | }; | ||
883 | #endif | ||
884 | |||
885 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 881 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
886 | { | 882 | { |
887 | struct ath_hw *ah = sc->sc_ah; | 883 | struct ath_hw *ah = sc->sc_ah; |
@@ -931,16 +927,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
931 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; | 927 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; |
932 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | 928 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; |
933 | 929 | ||
934 | #ifdef CONFIG_PM_SLEEP | ||
935 | if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && | ||
936 | (sc->driver_data & ATH9K_PCI_WOW) && | ||
937 | device_can_wakeup(sc->dev)) | ||
938 | hw->wiphy->wowlan = &ath9k_wowlan_support; | ||
939 | |||
940 | atomic_set(&sc->wow_sleep_proc_intr, -1); | ||
941 | atomic_set(&sc->wow_got_bmiss_intr, -1); | ||
942 | #endif | ||
943 | |||
944 | hw->queues = 4; | 930 | hw->queues = 4; |
945 | hw->max_rates = 4; | 931 | hw->max_rates = 4; |
946 | hw->channel_change_time = 5000; | 932 | hw->channel_change_time = 5000; |
@@ -966,6 +952,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
966 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 952 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
967 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 953 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
968 | 954 | ||
955 | ath9k_init_wow(hw); | ||
969 | ath9k_reload_chainmask_settings(sc); | 956 | ath9k_reload_chainmask_settings(sc); |
970 | 957 | ||
971 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 958 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
@@ -1064,6 +1051,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
1064 | if (ATH_TXQ_SETUP(sc, i)) | 1051 | if (ATH_TXQ_SETUP(sc, i)) |
1065 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1052 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
1066 | 1053 | ||
1054 | del_timer_sync(&sc->sleep_timer); | ||
1067 | ath9k_hw_deinit(sc->sc_ah); | 1055 | ath9k_hw_deinit(sc->sc_ah); |
1068 | if (sc->dfs_detector != NULL) | 1056 | if (sc->dfs_detector != NULL) |
1069 | sc->dfs_detector->exit(sc->dfs_detector); | 1057 | sc->dfs_detector->exit(sc->dfs_detector); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 74f452c7b166..b1dcf89138d3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -82,6 +82,22 @@ static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | |||
82 | return ret; | 82 | return ret; |
83 | } | 83 | } |
84 | 84 | ||
85 | void ath_ps_full_sleep(unsigned long data) | ||
86 | { | ||
87 | struct ath_softc *sc = (struct ath_softc *) data; | ||
88 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
89 | bool reset; | ||
90 | |||
91 | spin_lock(&common->cc_lock); | ||
92 | ath_hw_cycle_counters_update(common); | ||
93 | spin_unlock(&common->cc_lock); | ||
94 | |||
95 | ath9k_hw_setrxabort(sc->sc_ah, 1); | ||
96 | ath9k_hw_stopdmarecv(sc->sc_ah, &reset); | ||
97 | |||
98 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | ||
99 | } | ||
100 | |||
85 | void ath9k_ps_wakeup(struct ath_softc *sc) | 101 | void ath9k_ps_wakeup(struct ath_softc *sc) |
86 | { | 102 | { |
87 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 103 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -92,6 +108,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc) | |||
92 | if (++sc->ps_usecount != 1) | 108 | if (++sc->ps_usecount != 1) |
93 | goto unlock; | 109 | goto unlock; |
94 | 110 | ||
111 | del_timer_sync(&sc->sleep_timer); | ||
95 | power_mode = sc->sc_ah->power_mode; | 112 | power_mode = sc->sc_ah->power_mode; |
96 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | 113 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); |
97 | 114 | ||
@@ -117,17 +134,17 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
117 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 134 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
118 | enum ath9k_power_mode mode; | 135 | enum ath9k_power_mode mode; |
119 | unsigned long flags; | 136 | unsigned long flags; |
120 | bool reset; | ||
121 | 137 | ||
122 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 138 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
123 | if (--sc->ps_usecount != 0) | 139 | if (--sc->ps_usecount != 0) |
124 | goto unlock; | 140 | goto unlock; |
125 | 141 | ||
126 | if (sc->ps_idle) { | 142 | if (sc->ps_idle) { |
127 | ath9k_hw_setrxabort(sc->sc_ah, 1); | 143 | mod_timer(&sc->sleep_timer, jiffies + HZ / 10); |
128 | ath9k_hw_stopdmarecv(sc->sc_ah, &reset); | 144 | goto unlock; |
129 | mode = ATH9K_PM_FULL_SLEEP; | 145 | } |
130 | } else if (sc->ps_enabled && | 146 | |
147 | if (sc->ps_enabled && | ||
131 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | | 148 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
132 | PS_WAIT_FOR_CAB | | 149 | PS_WAIT_FOR_CAB | |
133 | PS_WAIT_FOR_PSPOLL_DATA | | 150 | PS_WAIT_FOR_PSPOLL_DATA | |
@@ -163,13 +180,13 @@ static void __ath_cancel_work(struct ath_softc *sc) | |||
163 | #endif | 180 | #endif |
164 | } | 181 | } |
165 | 182 | ||
166 | static void ath_cancel_work(struct ath_softc *sc) | 183 | void ath_cancel_work(struct ath_softc *sc) |
167 | { | 184 | { |
168 | __ath_cancel_work(sc); | 185 | __ath_cancel_work(sc); |
169 | cancel_work_sync(&sc->hw_reset_work); | 186 | cancel_work_sync(&sc->hw_reset_work); |
170 | } | 187 | } |
171 | 188 | ||
172 | static void ath_restart_work(struct ath_softc *sc) | 189 | void ath_restart_work(struct ath_softc *sc) |
173 | { | 190 | { |
174 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 191 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
175 | 192 | ||
@@ -487,6 +504,8 @@ void ath9k_tasklet(unsigned long data) | |||
487 | ath_tx_edma_tasklet(sc); | 504 | ath_tx_edma_tasklet(sc); |
488 | else | 505 | else |
489 | ath_tx_tasklet(sc); | 506 | ath_tx_tasklet(sc); |
507 | |||
508 | wake_up(&sc->tx_wait); | ||
490 | } | 509 | } |
491 | 510 | ||
492 | ath9k_btcoex_handle_interrupt(sc, status); | 511 | ath9k_btcoex_handle_interrupt(sc, status); |
@@ -579,7 +598,8 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
579 | 598 | ||
580 | goto chip_reset; | 599 | goto chip_reset; |
581 | } | 600 | } |
582 | #ifdef CONFIG_PM_SLEEP | 601 | |
602 | #ifdef CONFIG_ATH9K_WOW | ||
583 | if (status & ATH9K_INT_BMISS) { | 603 | if (status & ATH9K_INT_BMISS) { |
584 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { | 604 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { |
585 | ath_dbg(common, ANY, "during WoW we got a BMISS\n"); | 605 | ath_dbg(common, ANY, "during WoW we got a BMISS\n"); |
@@ -588,6 +608,8 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
588 | } | 608 | } |
589 | } | 609 | } |
590 | #endif | 610 | #endif |
611 | |||
612 | |||
591 | if (status & ATH9K_INT_SWBA) | 613 | if (status & ATH9K_INT_SWBA) |
592 | tasklet_schedule(&sc->bcon_tasklet); | 614 | tasklet_schedule(&sc->bcon_tasklet); |
593 | 615 | ||
@@ -627,7 +649,7 @@ chip_reset: | |||
627 | #undef SCHED_INTR | 649 | #undef SCHED_INTR |
628 | } | 650 | } |
629 | 651 | ||
630 | static int ath_reset(struct ath_softc *sc) | 652 | int ath_reset(struct ath_softc *sc) |
631 | { | 653 | { |
632 | int r; | 654 | int r; |
633 | 655 | ||
@@ -1817,13 +1839,31 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | |||
1817 | mutex_unlock(&sc->mutex); | 1839 | mutex_unlock(&sc->mutex); |
1818 | } | 1840 | } |
1819 | 1841 | ||
1842 | static bool ath9k_has_tx_pending(struct ath_softc *sc) | ||
1843 | { | ||
1844 | int i, npend; | ||
1845 | |||
1846 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
1847 | if (!ATH_TXQ_SETUP(sc, i)) | ||
1848 | continue; | ||
1849 | |||
1850 | if (!sc->tx.txq[i].axq_depth) | ||
1851 | continue; | ||
1852 | |||
1853 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | ||
1854 | if (npend) | ||
1855 | break; | ||
1856 | } | ||
1857 | |||
1858 | return !!npend; | ||
1859 | } | ||
1860 | |||
1820 | static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 1861 | static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1821 | { | 1862 | { |
1822 | struct ath_softc *sc = hw->priv; | 1863 | struct ath_softc *sc = hw->priv; |
1823 | struct ath_hw *ah = sc->sc_ah; | 1864 | struct ath_hw *ah = sc->sc_ah; |
1824 | struct ath_common *common = ath9k_hw_common(ah); | 1865 | struct ath_common *common = ath9k_hw_common(ah); |
1825 | int timeout = 200; /* ms */ | 1866 | int timeout = HZ / 5; /* 200 ms */ |
1826 | int i, j; | ||
1827 | bool drain_txq; | 1867 | bool drain_txq; |
1828 | 1868 | ||
1829 | mutex_lock(&sc->mutex); | 1869 | mutex_lock(&sc->mutex); |
@@ -1841,25 +1881,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
1841 | return; | 1881 | return; |
1842 | } | 1882 | } |
1843 | 1883 | ||
1844 | for (j = 0; j < timeout; j++) { | 1884 | if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), |
1845 | bool npend = false; | 1885 | timeout) > 0) |
1846 | 1886 | drop = false; | |
1847 | if (j) | ||
1848 | usleep_range(1000, 2000); | ||
1849 | |||
1850 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
1851 | if (!ATH_TXQ_SETUP(sc, i)) | ||
1852 | continue; | ||
1853 | |||
1854 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | ||
1855 | |||
1856 | if (npend) | ||
1857 | break; | ||
1858 | } | ||
1859 | |||
1860 | if (!npend) | ||
1861 | break; | ||
1862 | } | ||
1863 | 1887 | ||
1864 | if (drop) { | 1888 | if (drop) { |
1865 | ath9k_ps_wakeup(sc); | 1889 | ath9k_ps_wakeup(sc); |
@@ -2021,333 +2045,6 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
2021 | return 0; | 2045 | return 0; |
2022 | } | 2046 | } |
2023 | 2047 | ||
2024 | #ifdef CONFIG_PM_SLEEP | ||
2025 | |||
2026 | static void ath9k_wow_map_triggers(struct ath_softc *sc, | ||
2027 | struct cfg80211_wowlan *wowlan, | ||
2028 | u32 *wow_triggers) | ||
2029 | { | ||
2030 | if (wowlan->disconnect) | ||
2031 | *wow_triggers |= AH_WOW_LINK_CHANGE | | ||
2032 | AH_WOW_BEACON_MISS; | ||
2033 | if (wowlan->magic_pkt) | ||
2034 | *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; | ||
2035 | |||
2036 | if (wowlan->n_patterns) | ||
2037 | *wow_triggers |= AH_WOW_USER_PATTERN_EN; | ||
2038 | |||
2039 | sc->wow_enabled = *wow_triggers; | ||
2040 | |||
2041 | } | ||
2042 | |||
2043 | static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | ||
2044 | { | ||
2045 | struct ath_hw *ah = sc->sc_ah; | ||
2046 | struct ath_common *common = ath9k_hw_common(ah); | ||
2047 | int pattern_count = 0; | ||
2048 | int i, byte_cnt; | ||
2049 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; | ||
2050 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; | ||
2051 | |||
2052 | memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); | ||
2053 | memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); | ||
2054 | |||
2055 | /* | ||
2056 | * Create Dissassociate / Deauthenticate packet filter | ||
2057 | * | ||
2058 | * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes | ||
2059 | * +--------------+----------+---------+--------+--------+---- | ||
2060 | * + Frame Control+ Duration + DA + SA + BSSID + | ||
2061 | * +--------------+----------+---------+--------+--------+---- | ||
2062 | * | ||
2063 | * The above is the management frame format for disassociate/ | ||
2064 | * deauthenticate pattern, from this we need to match the first byte | ||
2065 | * of 'Frame Control' and DA, SA, and BSSID fields | ||
2066 | * (skipping 2nd byte of FC and Duration feild. | ||
2067 | * | ||
2068 | * Disassociate pattern | ||
2069 | * -------------------- | ||
2070 | * Frame control = 00 00 1010 | ||
2071 | * DA, SA, BSSID = x:x:x:x:x:x | ||
2072 | * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x | ||
2073 | * | x:x:x:x:x:x -- 22 bytes | ||
2074 | * | ||
2075 | * Deauthenticate pattern | ||
2076 | * ---------------------- | ||
2077 | * Frame control = 00 00 1100 | ||
2078 | * DA, SA, BSSID = x:x:x:x:x:x | ||
2079 | * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x | ||
2080 | * | x:x:x:x:x:x -- 22 bytes | ||
2081 | */ | ||
2082 | |||
2083 | /* Create Disassociate Pattern first */ | ||
2084 | |||
2085 | byte_cnt = 0; | ||
2086 | |||
2087 | /* Fill out the mask with all FF's */ | ||
2088 | |||
2089 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) | ||
2090 | dis_deauth_mask[i] = 0xff; | ||
2091 | |||
2092 | /* copy the first byte of frame control field */ | ||
2093 | dis_deauth_pattern[byte_cnt] = 0xa0; | ||
2094 | byte_cnt++; | ||
2095 | |||
2096 | /* skip 2nd byte of frame control and Duration field */ | ||
2097 | byte_cnt += 3; | ||
2098 | |||
2099 | /* | ||
2100 | * need not match the destination mac address, it can be a broadcast | ||
2101 | * mac address or an unicast to this station | ||
2102 | */ | ||
2103 | byte_cnt += 6; | ||
2104 | |||
2105 | /* copy the source mac address */ | ||
2106 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); | ||
2107 | |||
2108 | byte_cnt += 6; | ||
2109 | |||
2110 | /* copy the bssid, its same as the source mac address */ | ||
2111 | |||
2112 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); | ||
2113 | |||
2114 | /* Create Disassociate pattern mask */ | ||
2115 | |||
2116 | dis_deauth_mask[0] = 0xfe; | ||
2117 | dis_deauth_mask[1] = 0x03; | ||
2118 | dis_deauth_mask[2] = 0xc0; | ||
2119 | |||
2120 | ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); | ||
2121 | |||
2122 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | ||
2123 | pattern_count, byte_cnt); | ||
2124 | |||
2125 | pattern_count++; | ||
2126 | /* | ||
2127 | * for de-authenticate pattern, only the first byte of the frame | ||
2128 | * control field gets changed from 0xA0 to 0xC0 | ||
2129 | */ | ||
2130 | dis_deauth_pattern[0] = 0xC0; | ||
2131 | |||
2132 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | ||
2133 | pattern_count, byte_cnt); | ||
2134 | |||
2135 | } | ||
2136 | |||
2137 | static void ath9k_wow_add_pattern(struct ath_softc *sc, | ||
2138 | struct cfg80211_wowlan *wowlan) | ||
2139 | { | ||
2140 | struct ath_hw *ah = sc->sc_ah; | ||
2141 | struct ath9k_wow_pattern *wow_pattern = NULL; | ||
2142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; | ||
2143 | int mask_len; | ||
2144 | s8 i = 0; | ||
2145 | |||
2146 | if (!wowlan->n_patterns) | ||
2147 | return; | ||
2148 | |||
2149 | /* | ||
2150 | * Add the new user configured patterns | ||
2151 | */ | ||
2152 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
2153 | |||
2154 | wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); | ||
2155 | |||
2156 | if (!wow_pattern) | ||
2157 | return; | ||
2158 | |||
2159 | /* | ||
2160 | * TODO: convert the generic user space pattern to | ||
2161 | * appropriate chip specific/802.11 pattern. | ||
2162 | */ | ||
2163 | |||
2164 | mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | ||
2165 | memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); | ||
2166 | memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); | ||
2167 | memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, | ||
2168 | patterns[i].pattern_len); | ||
2169 | memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); | ||
2170 | wow_pattern->pattern_len = patterns[i].pattern_len; | ||
2171 | |||
2172 | /* | ||
2173 | * just need to take care of deauth and disssoc pattern, | ||
2174 | * make sure we don't overwrite them. | ||
2175 | */ | ||
2176 | |||
2177 | ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, | ||
2178 | wow_pattern->mask_bytes, | ||
2179 | i + 2, | ||
2180 | wow_pattern->pattern_len); | ||
2181 | kfree(wow_pattern); | ||
2182 | |||
2183 | } | ||
2184 | |||
2185 | } | ||
2186 | |||
2187 | static int ath9k_suspend(struct ieee80211_hw *hw, | ||
2188 | struct cfg80211_wowlan *wowlan) | ||
2189 | { | ||
2190 | struct ath_softc *sc = hw->priv; | ||
2191 | struct ath_hw *ah = sc->sc_ah; | ||
2192 | struct ath_common *common = ath9k_hw_common(ah); | ||
2193 | u32 wow_triggers_enabled = 0; | ||
2194 | int ret = 0; | ||
2195 | |||
2196 | mutex_lock(&sc->mutex); | ||
2197 | |||
2198 | ath_cancel_work(sc); | ||
2199 | ath_stop_ani(sc); | ||
2200 | del_timer_sync(&sc->rx_poll_timer); | ||
2201 | |||
2202 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | ||
2203 | ath_dbg(common, ANY, "Device not present\n"); | ||
2204 | ret = -EINVAL; | ||
2205 | goto fail_wow; | ||
2206 | } | ||
2207 | |||
2208 | if (WARN_ON(!wowlan)) { | ||
2209 | ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); | ||
2210 | ret = -EINVAL; | ||
2211 | goto fail_wow; | ||
2212 | } | ||
2213 | |||
2214 | if (!device_can_wakeup(sc->dev)) { | ||
2215 | ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); | ||
2216 | ret = 1; | ||
2217 | goto fail_wow; | ||
2218 | } | ||
2219 | |||
2220 | /* | ||
2221 | * none of the sta vifs are associated | ||
2222 | * and we are not currently handling multivif | ||
2223 | * cases, for instance we have to seperately | ||
2224 | * configure 'keep alive frame' for each | ||
2225 | * STA. | ||
2226 | */ | ||
2227 | |||
2228 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | ||
2229 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); | ||
2230 | ret = 1; | ||
2231 | goto fail_wow; | ||
2232 | } | ||
2233 | |||
2234 | if (sc->nvifs > 1) { | ||
2235 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); | ||
2236 | ret = 1; | ||
2237 | goto fail_wow; | ||
2238 | } | ||
2239 | |||
2240 | ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); | ||
2241 | |||
2242 | ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", | ||
2243 | wow_triggers_enabled); | ||
2244 | |||
2245 | ath9k_ps_wakeup(sc); | ||
2246 | |||
2247 | ath9k_stop_btcoex(sc); | ||
2248 | |||
2249 | /* | ||
2250 | * Enable wake up on recieving disassoc/deauth | ||
2251 | * frame by default. | ||
2252 | */ | ||
2253 | ath9k_wow_add_disassoc_deauth_pattern(sc); | ||
2254 | |||
2255 | if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) | ||
2256 | ath9k_wow_add_pattern(sc, wowlan); | ||
2257 | |||
2258 | spin_lock_bh(&sc->sc_pcu_lock); | ||
2259 | /* | ||
2260 | * To avoid false wake, we enable beacon miss interrupt only | ||
2261 | * when we go to sleep. We save the current interrupt mask | ||
2262 | * so we can restore it after the system wakes up | ||
2263 | */ | ||
2264 | sc->wow_intr_before_sleep = ah->imask; | ||
2265 | ah->imask &= ~ATH9K_INT_GLOBAL; | ||
2266 | ath9k_hw_disable_interrupts(ah); | ||
2267 | ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; | ||
2268 | ath9k_hw_set_interrupts(ah); | ||
2269 | ath9k_hw_enable_interrupts(ah); | ||
2270 | |||
2271 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2272 | |||
2273 | /* | ||
2274 | * we can now sync irq and kill any running tasklets, since we already | ||
2275 | * disabled interrupts and not holding a spin lock | ||
2276 | */ | ||
2277 | synchronize_irq(sc->irq); | ||
2278 | tasklet_kill(&sc->intr_tq); | ||
2279 | |||
2280 | ath9k_hw_wow_enable(ah, wow_triggers_enabled); | ||
2281 | |||
2282 | ath9k_ps_restore(sc); | ||
2283 | ath_dbg(common, ANY, "WoW enabled in ath9k\n"); | ||
2284 | atomic_inc(&sc->wow_sleep_proc_intr); | ||
2285 | |||
2286 | fail_wow: | ||
2287 | mutex_unlock(&sc->mutex); | ||
2288 | return ret; | ||
2289 | } | ||
2290 | |||
2291 | static int ath9k_resume(struct ieee80211_hw *hw) | ||
2292 | { | ||
2293 | struct ath_softc *sc = hw->priv; | ||
2294 | struct ath_hw *ah = sc->sc_ah; | ||
2295 | struct ath_common *common = ath9k_hw_common(ah); | ||
2296 | u32 wow_status; | ||
2297 | |||
2298 | mutex_lock(&sc->mutex); | ||
2299 | |||
2300 | ath9k_ps_wakeup(sc); | ||
2301 | |||
2302 | spin_lock_bh(&sc->sc_pcu_lock); | ||
2303 | |||
2304 | ath9k_hw_disable_interrupts(ah); | ||
2305 | ah->imask = sc->wow_intr_before_sleep; | ||
2306 | ath9k_hw_set_interrupts(ah); | ||
2307 | ath9k_hw_enable_interrupts(ah); | ||
2308 | |||
2309 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2310 | |||
2311 | wow_status = ath9k_hw_wow_wakeup(ah); | ||
2312 | |||
2313 | if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { | ||
2314 | /* | ||
2315 | * some devices may not pick beacon miss | ||
2316 | * as the reason they woke up so we add | ||
2317 | * that here for that shortcoming. | ||
2318 | */ | ||
2319 | wow_status |= AH_WOW_BEACON_MISS; | ||
2320 | atomic_dec(&sc->wow_got_bmiss_intr); | ||
2321 | ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); | ||
2322 | } | ||
2323 | |||
2324 | atomic_dec(&sc->wow_sleep_proc_intr); | ||
2325 | |||
2326 | if (wow_status) { | ||
2327 | ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", | ||
2328 | ath9k_hw_wow_event_to_string(wow_status), wow_status); | ||
2329 | } | ||
2330 | |||
2331 | ath_restart_work(sc); | ||
2332 | ath9k_start_btcoex(sc); | ||
2333 | |||
2334 | ath9k_ps_restore(sc); | ||
2335 | mutex_unlock(&sc->mutex); | ||
2336 | |||
2337 | return 0; | ||
2338 | } | ||
2339 | |||
2340 | static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | ||
2341 | { | ||
2342 | struct ath_softc *sc = hw->priv; | ||
2343 | |||
2344 | mutex_lock(&sc->mutex); | ||
2345 | device_init_wakeup(sc->dev, 1); | ||
2346 | device_set_wakeup_enable(sc->dev, enabled); | ||
2347 | mutex_unlock(&sc->mutex); | ||
2348 | } | ||
2349 | |||
2350 | #endif | ||
2351 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | 2048 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) |
2352 | { | 2049 | { |
2353 | struct ath_softc *sc = hw->priv; | 2050 | struct ath_softc *sc = hw->priv; |
@@ -2373,134 +2070,6 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, | |||
2373 | sc->csa_vif = vif; | 2070 | sc->csa_vif = vif; |
2374 | } | 2071 | } |
2375 | 2072 | ||
2376 | static void ath9k_tx99_stop(struct ath_softc *sc) | ||
2377 | { | ||
2378 | struct ath_hw *ah = sc->sc_ah; | ||
2379 | struct ath_common *common = ath9k_hw_common(ah); | ||
2380 | |||
2381 | ath_drain_all_txq(sc); | ||
2382 | ath_startrecv(sc); | ||
2383 | |||
2384 | ath9k_hw_set_interrupts(ah); | ||
2385 | ath9k_hw_enable_interrupts(ah); | ||
2386 | |||
2387 | ieee80211_wake_queues(sc->hw); | ||
2388 | |||
2389 | kfree_skb(sc->tx99_skb); | ||
2390 | sc->tx99_skb = NULL; | ||
2391 | sc->tx99_state = false; | ||
2392 | |||
2393 | ath9k_hw_tx99_stop(sc->sc_ah); | ||
2394 | ath_dbg(common, XMIT, "TX99 stopped\n"); | ||
2395 | } | ||
2396 | |||
2397 | static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | ||
2398 | { | ||
2399 | static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, | ||
2400 | 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, | ||
2401 | 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, | ||
2402 | 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, | ||
2403 | 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, | ||
2404 | 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, | ||
2405 | 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, | ||
2406 | 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; | ||
2407 | u32 len = 1200; | ||
2408 | struct ieee80211_hw *hw = sc->hw; | ||
2409 | struct ieee80211_hdr *hdr; | ||
2410 | struct ieee80211_tx_info *tx_info; | ||
2411 | struct sk_buff *skb; | ||
2412 | |||
2413 | skb = alloc_skb(len, GFP_KERNEL); | ||
2414 | if (!skb) | ||
2415 | return NULL; | ||
2416 | |||
2417 | skb_put(skb, len); | ||
2418 | |||
2419 | memset(skb->data, 0, len); | ||
2420 | |||
2421 | hdr = (struct ieee80211_hdr *)skb->data; | ||
2422 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); | ||
2423 | hdr->duration_id = 0; | ||
2424 | |||
2425 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
2426 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
2427 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
2428 | |||
2429 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
2430 | |||
2431 | tx_info = IEEE80211_SKB_CB(skb); | ||
2432 | memset(tx_info, 0, sizeof(*tx_info)); | ||
2433 | tx_info->band = hw->conf.chandef.chan->band; | ||
2434 | tx_info->flags = IEEE80211_TX_CTL_NO_ACK; | ||
2435 | tx_info->control.vif = sc->tx99_vif; | ||
2436 | |||
2437 | memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); | ||
2438 | |||
2439 | return skb; | ||
2440 | } | ||
2441 | |||
2442 | void ath9k_tx99_deinit(struct ath_softc *sc) | ||
2443 | { | ||
2444 | ath_reset(sc); | ||
2445 | |||
2446 | ath9k_ps_wakeup(sc); | ||
2447 | ath9k_tx99_stop(sc); | ||
2448 | ath9k_ps_restore(sc); | ||
2449 | } | ||
2450 | |||
2451 | int ath9k_tx99_init(struct ath_softc *sc) | ||
2452 | { | ||
2453 | struct ieee80211_hw *hw = sc->hw; | ||
2454 | struct ath_hw *ah = sc->sc_ah; | ||
2455 | struct ath_common *common = ath9k_hw_common(ah); | ||
2456 | struct ath_tx_control txctl; | ||
2457 | int r; | ||
2458 | |||
2459 | if (sc->sc_flags & SC_OP_INVALID) { | ||
2460 | ath_err(common, | ||
2461 | "driver is in invalid state unable to use TX99"); | ||
2462 | return -EINVAL; | ||
2463 | } | ||
2464 | |||
2465 | sc->tx99_skb = ath9k_build_tx99_skb(sc); | ||
2466 | if (!sc->tx99_skb) | ||
2467 | return -ENOMEM; | ||
2468 | |||
2469 | memset(&txctl, 0, sizeof(txctl)); | ||
2470 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | ||
2471 | |||
2472 | ath_reset(sc); | ||
2473 | |||
2474 | ath9k_ps_wakeup(sc); | ||
2475 | |||
2476 | ath9k_hw_disable_interrupts(ah); | ||
2477 | atomic_set(&ah->intr_ref_cnt, -1); | ||
2478 | ath_drain_all_txq(sc); | ||
2479 | ath_stoprecv(sc); | ||
2480 | |||
2481 | sc->tx99_state = true; | ||
2482 | |||
2483 | ieee80211_stop_queues(hw); | ||
2484 | |||
2485 | if (sc->tx99_power == MAX_RATE_POWER + 1) | ||
2486 | sc->tx99_power = MAX_RATE_POWER; | ||
2487 | |||
2488 | ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); | ||
2489 | r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); | ||
2490 | if (r) { | ||
2491 | ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); | ||
2492 | return r; | ||
2493 | } | ||
2494 | |||
2495 | ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", | ||
2496 | sc->tx99_power, | ||
2497 | sc->tx99_power / 2); | ||
2498 | |||
2499 | /* We leave the harware awake as it will be chugging on */ | ||
2500 | |||
2501 | return 0; | ||
2502 | } | ||
2503 | |||
2504 | struct ieee80211_ops ath9k_ops = { | 2073 | struct ieee80211_ops ath9k_ops = { |
2505 | .tx = ath9k_tx, | 2074 | .tx = ath9k_tx, |
2506 | .start = ath9k_start, | 2075 | .start = ath9k_start, |
@@ -2531,7 +2100,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2531 | .set_antenna = ath9k_set_antenna, | 2100 | .set_antenna = ath9k_set_antenna, |
2532 | .get_antenna = ath9k_get_antenna, | 2101 | .get_antenna = ath9k_get_antenna, |
2533 | 2102 | ||
2534 | #ifdef CONFIG_PM_SLEEP | 2103 | #ifdef CONFIG_ATH9K_WOW |
2535 | .suspend = ath9k_suspend, | 2104 | .suspend = ath9k_suspend, |
2536 | .resume = ath9k_resume, | 2105 | .resume = ath9k_resume, |
2537 | .set_wakeup = ath9k_set_wakeup, | 2106 | .set_wakeup = ath9k_set_wakeup, |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b5656fce4ff5..e9a585758941 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -87,6 +87,19 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
87 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 87 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
88 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 88 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
89 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 89 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
90 | |||
91 | /* Killer Wireless (3x3) */ | ||
92 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
93 | 0x0030, | ||
94 | 0x1A56, | ||
95 | 0x2000), | ||
96 | .driver_data = ATH9K_PCI_KILLER }, | ||
97 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
98 | 0x0030, | ||
99 | 0x1A56, | ||
100 | 0x2001), | ||
101 | .driver_data = ATH9K_PCI_KILLER }, | ||
102 | |||
90 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | 103 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ |
91 | 104 | ||
92 | /* PCI-E CUS198 */ | 105 | /* PCI-E CUS198 */ |
@@ -354,6 +367,13 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
354 | 0x1783), | 367 | 0x1783), |
355 | .driver_data = ATH9K_PCI_WOW }, | 368 | .driver_data = ATH9K_PCI_WOW }, |
356 | 369 | ||
370 | /* Killer Wireless (2x2) */ | ||
371 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
372 | 0x0030, | ||
373 | 0x1A56, | ||
374 | 0x2003), | ||
375 | .driver_data = ATH9K_PCI_KILLER }, | ||
376 | |||
357 | { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ | 377 | { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ |
358 | { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ | 378 | { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ |
359 | 379 | ||
@@ -448,6 +468,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
448 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 468 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
449 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 469 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
450 | 0x0036, | 470 | 0x0036, |
471 | 0x11AD, /* LITEON */ | ||
472 | 0x0682), | ||
473 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
474 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
475 | 0x0036, | ||
451 | PCI_VENDOR_ID_AZWAVE, | 476 | PCI_VENDOR_ID_AZWAVE, |
452 | 0x213A), | 477 | 0x213A), |
453 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 478 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
@@ -458,6 +483,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
458 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 483 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
459 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 484 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
460 | 0x0036, | 485 | 0x0036, |
486 | PCI_VENDOR_ID_LENOVO, | ||
487 | 0x4026), | ||
488 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
489 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
490 | 0x0036, | ||
461 | PCI_VENDOR_ID_HP, | 491 | PCI_VENDOR_ID_HP, |
462 | 0x18E3), | 492 | 0x18E3), |
463 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 493 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
@@ -468,6 +498,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
468 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 498 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
469 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 499 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
470 | 0x0036, | 500 | 0x0036, |
501 | PCI_VENDOR_ID_HP, | ||
502 | 0x2005), | ||
503 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
504 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
505 | 0x0036, | ||
471 | PCI_VENDOR_ID_DELL, | 506 | PCI_VENDOR_ID_DELL, |
472 | 0x020E), | 507 | 0x020E), |
473 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 508 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
@@ -545,6 +580,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
545 | 0x185F, /* WNC */ | 580 | 0x185F, /* WNC */ |
546 | 0x3027), | 581 | 0x3027), |
547 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 582 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
583 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
584 | 0x0036, | ||
585 | 0x185F, /* WNC */ | ||
586 | 0xA120), | ||
587 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
588 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
589 | 0x0036, | ||
590 | PCI_VENDOR_ID_FOXCONN, | ||
591 | 0xE07F), | ||
592 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
548 | 593 | ||
549 | /* PCI-E AR9565 (WB335) */ | 594 | /* PCI-E AR9565 (WB335) */ |
550 | { PCI_VDEVICE(ATHEROS, 0x0036), | 595 | { PCI_VDEVICE(ATHEROS, 0x0036), |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index a13b2d143d9e..259a4b307707 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -809,6 +809,8 @@ | |||
809 | #define AR_SREV_REVISION_9462_21 3 | 809 | #define AR_SREV_REVISION_9462_21 3 |
810 | #define AR_SREV_VERSION_9565 0x2C0 | 810 | #define AR_SREV_VERSION_9565 0x2C0 |
811 | #define AR_SREV_REVISION_9565_10 0 | 811 | #define AR_SREV_REVISION_9565_10 0 |
812 | #define AR_SREV_REVISION_9565_101 1 | ||
813 | #define AR_SREV_REVISION_9565_11 2 | ||
812 | #define AR_SREV_VERSION_9550 0x400 | 814 | #define AR_SREV_VERSION_9550 0x400 |
813 | 815 | ||
814 | #define AR_SREV_5416(_ah) \ | 816 | #define AR_SREV_5416(_ah) \ |
@@ -927,10 +929,18 @@ | |||
927 | 929 | ||
928 | #define AR_SREV_9565(_ah) \ | 930 | #define AR_SREV_9565(_ah) \ |
929 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | 931 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) |
930 | |||
931 | #define AR_SREV_9565_10(_ah) \ | 932 | #define AR_SREV_9565_10(_ah) \ |
932 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | 933 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ |
933 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) | 934 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) |
935 | #define AR_SREV_9565_101(_ah) \ | ||
936 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | ||
937 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101)) | ||
938 | #define AR_SREV_9565_11(_ah) \ | ||
939 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | ||
940 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11)) | ||
941 | #define AR_SREV_9565_11_OR_LATER(_ah) \ | ||
942 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | ||
943 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11)) | ||
934 | 944 | ||
935 | #define AR_SREV_9550(_ah) \ | 945 | #define AR_SREV_9550(_ah) \ |
936 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550)) | 946 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550)) |
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c new file mode 100644 index 000000000000..57d775783ec8 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/tx99.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static void ath9k_tx99_stop(struct ath_softc *sc) | ||
20 | { | ||
21 | struct ath_hw *ah = sc->sc_ah; | ||
22 | struct ath_common *common = ath9k_hw_common(ah); | ||
23 | |||
24 | ath_drain_all_txq(sc); | ||
25 | ath_startrecv(sc); | ||
26 | |||
27 | ath9k_hw_set_interrupts(ah); | ||
28 | ath9k_hw_enable_interrupts(ah); | ||
29 | |||
30 | ieee80211_wake_queues(sc->hw); | ||
31 | |||
32 | kfree_skb(sc->tx99_skb); | ||
33 | sc->tx99_skb = NULL; | ||
34 | sc->tx99_state = false; | ||
35 | |||
36 | ath9k_hw_tx99_stop(sc->sc_ah); | ||
37 | ath_dbg(common, XMIT, "TX99 stopped\n"); | ||
38 | } | ||
39 | |||
40 | static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | ||
41 | { | ||
42 | static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, | ||
43 | 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, | ||
44 | 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, | ||
45 | 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, | ||
46 | 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, | ||
47 | 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, | ||
48 | 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, | ||
49 | 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; | ||
50 | u32 len = 1200; | ||
51 | struct ieee80211_hw *hw = sc->hw; | ||
52 | struct ieee80211_hdr *hdr; | ||
53 | struct ieee80211_tx_info *tx_info; | ||
54 | struct sk_buff *skb; | ||
55 | |||
56 | skb = alloc_skb(len, GFP_KERNEL); | ||
57 | if (!skb) | ||
58 | return NULL; | ||
59 | |||
60 | skb_put(skb, len); | ||
61 | |||
62 | memset(skb->data, 0, len); | ||
63 | |||
64 | hdr = (struct ieee80211_hdr *)skb->data; | ||
65 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); | ||
66 | hdr->duration_id = 0; | ||
67 | |||
68 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
69 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
70 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
71 | |||
72 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
73 | |||
74 | tx_info = IEEE80211_SKB_CB(skb); | ||
75 | memset(tx_info, 0, sizeof(*tx_info)); | ||
76 | tx_info->band = hw->conf.chandef.chan->band; | ||
77 | tx_info->flags = IEEE80211_TX_CTL_NO_ACK; | ||
78 | tx_info->control.vif = sc->tx99_vif; | ||
79 | tx_info->control.rates[0].count = 1; | ||
80 | |||
81 | memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); | ||
82 | |||
83 | return skb; | ||
84 | } | ||
85 | |||
86 | static void ath9k_tx99_deinit(struct ath_softc *sc) | ||
87 | { | ||
88 | ath_reset(sc); | ||
89 | |||
90 | ath9k_ps_wakeup(sc); | ||
91 | ath9k_tx99_stop(sc); | ||
92 | ath9k_ps_restore(sc); | ||
93 | } | ||
94 | |||
95 | static int ath9k_tx99_init(struct ath_softc *sc) | ||
96 | { | ||
97 | struct ieee80211_hw *hw = sc->hw; | ||
98 | struct ath_hw *ah = sc->sc_ah; | ||
99 | struct ath_common *common = ath9k_hw_common(ah); | ||
100 | struct ath_tx_control txctl; | ||
101 | int r; | ||
102 | |||
103 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { | ||
104 | ath_err(common, | ||
105 | "driver is in invalid state unable to use TX99"); | ||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | sc->tx99_skb = ath9k_build_tx99_skb(sc); | ||
110 | if (!sc->tx99_skb) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | memset(&txctl, 0, sizeof(txctl)); | ||
114 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | ||
115 | |||
116 | ath_reset(sc); | ||
117 | |||
118 | ath9k_ps_wakeup(sc); | ||
119 | |||
120 | ath9k_hw_disable_interrupts(ah); | ||
121 | atomic_set(&ah->intr_ref_cnt, -1); | ||
122 | ath_drain_all_txq(sc); | ||
123 | ath_stoprecv(sc); | ||
124 | |||
125 | sc->tx99_state = true; | ||
126 | |||
127 | ieee80211_stop_queues(hw); | ||
128 | |||
129 | if (sc->tx99_power == MAX_RATE_POWER + 1) | ||
130 | sc->tx99_power = MAX_RATE_POWER; | ||
131 | |||
132 | ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); | ||
133 | r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); | ||
134 | if (r) { | ||
135 | ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); | ||
136 | return r; | ||
137 | } | ||
138 | |||
139 | ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", | ||
140 | sc->tx99_power, | ||
141 | sc->tx99_power / 2); | ||
142 | |||
143 | /* We leave the harware awake as it will be chugging on */ | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static ssize_t read_file_tx99(struct file *file, char __user *user_buf, | ||
149 | size_t count, loff_t *ppos) | ||
150 | { | ||
151 | struct ath_softc *sc = file->private_data; | ||
152 | char buf[3]; | ||
153 | unsigned int len; | ||
154 | |||
155 | len = sprintf(buf, "%d\n", sc->tx99_state); | ||
156 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
157 | } | ||
158 | |||
159 | static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, | ||
160 | size_t count, loff_t *ppos) | ||
161 | { | ||
162 | struct ath_softc *sc = file->private_data; | ||
163 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
164 | char buf[32]; | ||
165 | bool start; | ||
166 | ssize_t len; | ||
167 | int r; | ||
168 | |||
169 | if (sc->nvifs > 1) | ||
170 | return -EOPNOTSUPP; | ||
171 | |||
172 | len = min(count, sizeof(buf) - 1); | ||
173 | if (copy_from_user(buf, user_buf, len)) | ||
174 | return -EFAULT; | ||
175 | |||
176 | if (strtobool(buf, &start)) | ||
177 | return -EINVAL; | ||
178 | |||
179 | if (start == sc->tx99_state) { | ||
180 | if (!start) | ||
181 | return count; | ||
182 | ath_dbg(common, XMIT, "Resetting TX99\n"); | ||
183 | ath9k_tx99_deinit(sc); | ||
184 | } | ||
185 | |||
186 | if (!start) { | ||
187 | ath9k_tx99_deinit(sc); | ||
188 | return count; | ||
189 | } | ||
190 | |||
191 | r = ath9k_tx99_init(sc); | ||
192 | if (r) | ||
193 | return r; | ||
194 | |||
195 | return count; | ||
196 | } | ||
197 | |||
198 | static const struct file_operations fops_tx99 = { | ||
199 | .read = read_file_tx99, | ||
200 | .write = write_file_tx99, | ||
201 | .open = simple_open, | ||
202 | .owner = THIS_MODULE, | ||
203 | .llseek = default_llseek, | ||
204 | }; | ||
205 | |||
206 | static ssize_t read_file_tx99_power(struct file *file, | ||
207 | char __user *user_buf, | ||
208 | size_t count, loff_t *ppos) | ||
209 | { | ||
210 | struct ath_softc *sc = file->private_data; | ||
211 | char buf[32]; | ||
212 | unsigned int len; | ||
213 | |||
214 | len = sprintf(buf, "%d (%d dBm)\n", | ||
215 | sc->tx99_power, | ||
216 | sc->tx99_power / 2); | ||
217 | |||
218 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
219 | } | ||
220 | |||
221 | static ssize_t write_file_tx99_power(struct file *file, | ||
222 | const char __user *user_buf, | ||
223 | size_t count, loff_t *ppos) | ||
224 | { | ||
225 | struct ath_softc *sc = file->private_data; | ||
226 | int r; | ||
227 | u8 tx_power; | ||
228 | |||
229 | r = kstrtou8_from_user(user_buf, count, 0, &tx_power); | ||
230 | if (r) | ||
231 | return r; | ||
232 | |||
233 | if (tx_power > MAX_RATE_POWER) | ||
234 | return -EINVAL; | ||
235 | |||
236 | sc->tx99_power = tx_power; | ||
237 | |||
238 | ath9k_ps_wakeup(sc); | ||
239 | ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); | ||
240 | ath9k_ps_restore(sc); | ||
241 | |||
242 | return count; | ||
243 | } | ||
244 | |||
245 | static const struct file_operations fops_tx99_power = { | ||
246 | .read = read_file_tx99_power, | ||
247 | .write = write_file_tx99_power, | ||
248 | .open = simple_open, | ||
249 | .owner = THIS_MODULE, | ||
250 | .llseek = default_llseek, | ||
251 | }; | ||
252 | |||
253 | void ath9k_tx99_init_debug(struct ath_softc *sc) | ||
254 | { | ||
255 | if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah)) | ||
256 | return; | ||
257 | |||
258 | debugfs_create_file("tx99", S_IRUSR | S_IWUSR, | ||
259 | sc->debug.debugfs_phy, sc, | ||
260 | &fops_tx99); | ||
261 | debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, | ||
262 | sc->debug.debugfs_phy, sc, | ||
263 | &fops_tx99_power); | ||
264 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 81c88dd606dc..f1cde81bb7a2 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2013 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -14,409 +14,348 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/export.h> | ||
18 | #include "ath9k.h" | 17 | #include "ath9k.h" |
19 | #include "reg.h" | ||
20 | #include "hw-ops.h" | ||
21 | 18 | ||
22 | const char *ath9k_hw_wow_event_to_string(u32 wow_event) | 19 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { |
23 | { | 20 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
24 | if (wow_event & AH_WOW_MAGIC_PATTERN_EN) | 21 | .n_patterns = MAX_NUM_USER_PATTERN, |
25 | return "Magic pattern"; | 22 | .pattern_min_len = 1, |
26 | if (wow_event & AH_WOW_USER_PATTERN_EN) | 23 | .pattern_max_len = MAX_PATTERN_SIZE, |
27 | return "User pattern"; | 24 | }; |
28 | if (wow_event & AH_WOW_LINK_CHANGE) | ||
29 | return "Link change"; | ||
30 | if (wow_event & AH_WOW_BEACON_MISS) | ||
31 | return "Beacon miss"; | ||
32 | |||
33 | return "unknown reason"; | ||
34 | } | ||
35 | EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); | ||
36 | 25 | ||
37 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | 26 | static void ath9k_wow_map_triggers(struct ath_softc *sc, |
27 | struct cfg80211_wowlan *wowlan, | ||
28 | u32 *wow_triggers) | ||
38 | { | 29 | { |
39 | struct ath_common *common = ath9k_hw_common(ah); | 30 | if (wowlan->disconnect) |
31 | *wow_triggers |= AH_WOW_LINK_CHANGE | | ||
32 | AH_WOW_BEACON_MISS; | ||
33 | if (wowlan->magic_pkt) | ||
34 | *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; | ||
40 | 35 | ||
41 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | 36 | if (wowlan->n_patterns) |
37 | *wow_triggers |= AH_WOW_USER_PATTERN_EN; | ||
42 | 38 | ||
43 | /* set rx disable bit */ | 39 | sc->wow_enabled = *wow_triggers; |
44 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
45 | |||
46 | if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { | ||
47 | ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | ||
48 | REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); | ||
49 | return; | ||
50 | } | ||
51 | 40 | ||
52 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); | ||
53 | } | 41 | } |
54 | 42 | ||
55 | static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | 43 | static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) |
56 | { | 44 | { |
45 | struct ath_hw *ah = sc->sc_ah; | ||
57 | struct ath_common *common = ath9k_hw_common(ah); | 46 | struct ath_common *common = ath9k_hw_common(ah); |
58 | u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; | 47 | int pattern_count = 0; |
59 | u32 ctl[13] = {0}; | 48 | int i, byte_cnt; |
60 | u32 data_word[KAL_NUM_DATA_WORDS]; | 49 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; |
61 | u8 i; | 50 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; |
62 | u32 wow_ka_data_word0; | ||
63 | |||
64 | memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); | ||
65 | memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); | ||
66 | |||
67 | /* set the transmit buffer */ | ||
68 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); | ||
69 | ctl[1] = 0; | ||
70 | ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ | ||
71 | ctl[4] = 0; | ||
72 | ctl[7] = (ah->txchainmask) << 2; | ||
73 | ctl[2] = 0xf << 16; /* tx_tries 0 */ | ||
74 | |||
75 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) | ||
76 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | ||
77 | |||
78 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | ||
79 | |||
80 | data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | | ||
81 | (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); | ||
82 | data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | | ||
83 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); | ||
84 | data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | | ||
85 | (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); | ||
86 | data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | | ||
87 | (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); | ||
88 | data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | | ||
89 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); | ||
90 | data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); | ||
91 | |||
92 | if (AR_SREV_9462_20(ah)) { | ||
93 | /* AR9462 2.0 has an extra descriptor word (time based | ||
94 | * discard) compared to other chips */ | ||
95 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); | ||
96 | wow_ka_data_word0 = AR_WOW_TXBUF(13); | ||
97 | } else { | ||
98 | wow_ka_data_word0 = AR_WOW_TXBUF(12); | ||
99 | } | ||
100 | |||
101 | for (i = 0; i < KAL_NUM_DATA_WORDS; i++) | ||
102 | REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); | ||
103 | |||
104 | } | ||
105 | |||
106 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | ||
107 | u8 *user_mask, int pattern_count, | ||
108 | int pattern_len) | ||
109 | { | ||
110 | int i; | ||
111 | u32 pattern_val, mask_val; | ||
112 | u32 set, clr; | ||
113 | 51 | ||
114 | /* FIXME: should check count by querying the hardware capability */ | 52 | memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); |
115 | if (pattern_count >= MAX_NUM_PATTERN) | 53 | memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); |
116 | return; | ||
117 | |||
118 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | ||
119 | |||
120 | /* set the registers for pattern */ | ||
121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { | ||
122 | memcpy(&pattern_val, user_pattern, 4); | ||
123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), | ||
124 | pattern_val); | ||
125 | user_pattern += 4; | ||
126 | } | ||
127 | |||
128 | /* set the registers for mask */ | ||
129 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { | ||
130 | memcpy(&mask_val, user_mask, 4); | ||
131 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); | ||
132 | user_mask += 4; | ||
133 | } | ||
134 | 54 | ||
135 | /* set the pattern length to be matched | 55 | /* |
56 | * Create Dissassociate / Deauthenticate packet filter | ||
57 | * | ||
58 | * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes | ||
59 | * +--------------+----------+---------+--------+--------+---- | ||
60 | * + Frame Control+ Duration + DA + SA + BSSID + | ||
61 | * +--------------+----------+---------+--------+--------+---- | ||
136 | * | 62 | * |
137 | * AR_WOW_LENGTH1_REG1 | 63 | * The above is the management frame format for disassociate/ |
138 | * bit 31:24 pattern 0 length | 64 | * deauthenticate pattern, from this we need to match the first byte |
139 | * bit 23:16 pattern 1 length | 65 | * of 'Frame Control' and DA, SA, and BSSID fields |
140 | * bit 15:8 pattern 2 length | 66 | * (skipping 2nd byte of FC and Duration feild. |
141 | * bit 7:0 pattern 3 length | ||
142 | * | 67 | * |
143 | * AR_WOW_LENGTH1_REG2 | 68 | * Disassociate pattern |
144 | * bit 31:24 pattern 4 length | 69 | * -------------------- |
145 | * bit 23:16 pattern 5 length | 70 | * Frame control = 00 00 1010 |
146 | * bit 15:8 pattern 6 length | 71 | * DA, SA, BSSID = x:x:x:x:x:x |
147 | * bit 7:0 pattern 7 length | 72 | * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x |
73 | * | x:x:x:x:x:x -- 22 bytes | ||
148 | * | 74 | * |
149 | * the below logic writes out the new | 75 | * Deauthenticate pattern |
150 | * pattern length for the corresponding | 76 | * ---------------------- |
151 | * pattern_count, while masking out the | 77 | * Frame control = 00 00 1100 |
152 | * other fields | 78 | * DA, SA, BSSID = x:x:x:x:x:x |
79 | * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x | ||
80 | * | x:x:x:x:x:x -- 22 bytes | ||
153 | */ | 81 | */ |
154 | 82 | ||
155 | ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); | 83 | /* Create Disassociate Pattern first */ |
156 | |||
157 | if (pattern_count < 4) { | ||
158 | /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ | ||
159 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
160 | AR_WOW_LEN1_SHIFT(pattern_count); | ||
161 | clr = AR_WOW_LENGTH1_MASK(pattern_count); | ||
162 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); | ||
163 | } else { | ||
164 | /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ | ||
165 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
166 | AR_WOW_LEN2_SHIFT(pattern_count); | ||
167 | clr = AR_WOW_LENGTH2_MASK(pattern_count); | ||
168 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); | ||
169 | } | ||
170 | 84 | ||
171 | } | 85 | byte_cnt = 0; |
172 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); | ||
173 | 86 | ||
174 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | 87 | /* Fill out the mask with all FF's */ |
175 | { | ||
176 | u32 wow_status = 0; | ||
177 | u32 val = 0, rval; | ||
178 | 88 | ||
179 | /* | 89 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) |
180 | * read the WoW status register to know | 90 | dis_deauth_mask[i] = 0xff; |
181 | * the wakeup reason | ||
182 | */ | ||
183 | rval = REG_READ(ah, AR_WOW_PATTERN); | ||
184 | val = AR_WOW_STATUS(rval); | ||
185 | 91 | ||
186 | /* | 92 | /* copy the first byte of frame control field */ |
187 | * mask only the WoW events that we have enabled. Sometimes | 93 | dis_deauth_pattern[byte_cnt] = 0xa0; |
188 | * we have spurious WoW events from the AR_WOW_PATTERN | 94 | byte_cnt++; |
189 | * register. This mask will clean it up. | ||
190 | */ | ||
191 | 95 | ||
192 | val &= ah->wow_event_mask; | 96 | /* skip 2nd byte of frame control and Duration field */ |
193 | 97 | byte_cnt += 3; | |
194 | if (val) { | ||
195 | if (val & AR_WOW_MAGIC_PAT_FOUND) | ||
196 | wow_status |= AH_WOW_MAGIC_PATTERN_EN; | ||
197 | if (AR_WOW_PATTERN_FOUND(val)) | ||
198 | wow_status |= AH_WOW_USER_PATTERN_EN; | ||
199 | if (val & AR_WOW_KEEP_ALIVE_FAIL) | ||
200 | wow_status |= AH_WOW_LINK_CHANGE; | ||
201 | if (val & AR_WOW_BEACON_FAIL) | ||
202 | wow_status |= AH_WOW_BEACON_MISS; | ||
203 | } | ||
204 | 98 | ||
205 | /* | 99 | /* |
206 | * set and clear WOW_PME_CLEAR registers for the chip to | 100 | * need not match the destination mac address, it can be a broadcast |
207 | * generate next wow signal. | 101 | * mac address or an unicast to this station |
208 | * disable D3 before accessing other registers ? | ||
209 | */ | 102 | */ |
103 | byte_cnt += 6; | ||
210 | 104 | ||
211 | /* do we need to check the bit value 0x01000000 (7-10) ?? */ | 105 | /* copy the source mac address */ |
212 | REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, | 106 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); |
213 | AR_PMCTRL_PWR_STATE_D1D3); | ||
214 | 107 | ||
215 | /* | 108 | byte_cnt += 6; |
216 | * clear all events | ||
217 | */ | ||
218 | REG_WRITE(ah, AR_WOW_PATTERN, | ||
219 | AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); | ||
220 | 109 | ||
221 | /* | 110 | /* copy the bssid, its same as the source mac address */ |
222 | * restore the beacon threshold to init value | 111 | |
223 | */ | 112 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); |
224 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | 113 | |
114 | /* Create Disassociate pattern mask */ | ||
115 | |||
116 | dis_deauth_mask[0] = 0xfe; | ||
117 | dis_deauth_mask[1] = 0x03; | ||
118 | dis_deauth_mask[2] = 0xc0; | ||
119 | |||
120 | ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); | ||
225 | 121 | ||
122 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | ||
123 | pattern_count, byte_cnt); | ||
124 | |||
125 | pattern_count++; | ||
226 | /* | 126 | /* |
227 | * Restore the way the PCI-E reset, Power-On-Reset, external | 127 | * for de-authenticate pattern, only the first byte of the frame |
228 | * PCIE_POR_SHORT pins are tied to its original value. | 128 | * control field gets changed from 0xA0 to 0xC0 |
229 | * Previously just before WoW sleep, we untie the PCI-E | ||
230 | * reset to our Chip's Power On Reset so that any PCI-E | ||
231 | * reset from the bus will not reset our chip | ||
232 | */ | 129 | */ |
233 | if (ah->is_pciexpress) | 130 | dis_deauth_pattern[0] = 0xC0; |
234 | ath9k_hw_configpcipowersave(ah, false); | ||
235 | 131 | ||
236 | ah->wow_event_mask = 0; | 132 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, |
133 | pattern_count, byte_cnt); | ||
237 | 134 | ||
238 | return wow_status; | ||
239 | } | 135 | } |
240 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); | ||
241 | 136 | ||
242 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) | 137 | static void ath9k_wow_add_pattern(struct ath_softc *sc, |
138 | struct cfg80211_wowlan *wowlan) | ||
243 | { | 139 | { |
244 | u32 wow_event_mask; | 140 | struct ath_hw *ah = sc->sc_ah; |
245 | u32 set, clr; | 141 | struct ath9k_wow_pattern *wow_pattern = NULL; |
142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; | ||
143 | int mask_len; | ||
144 | s8 i = 0; | ||
246 | 145 | ||
247 | /* | 146 | if (!wowlan->n_patterns) |
248 | * wow_event_mask is a mask to the AR_WOW_PATTERN register to | 147 | return; |
249 | * indicate which WoW events we have enabled. The WoW events | ||
250 | * are from the 'pattern_enable' in this function and | ||
251 | * 'pattern_count' of ath9k_hw_wow_apply_pattern() | ||
252 | */ | ||
253 | wow_event_mask = ah->wow_event_mask; | ||
254 | 148 | ||
255 | /* | 149 | /* |
256 | * Untie Power-on-Reset from the PCI-E-Reset. When we are in | 150 | * Add the new user configured patterns |
257 | * WOW sleep, we do want the Reset from the PCI-E to disturb | ||
258 | * our hw state | ||
259 | */ | 151 | */ |
260 | if (ah->is_pciexpress) { | 152 | for (i = 0; i < wowlan->n_patterns; i++) { |
153 | |||
154 | wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); | ||
155 | |||
156 | if (!wow_pattern) | ||
157 | return; | ||
158 | |||
159 | /* | ||
160 | * TODO: convert the generic user space pattern to | ||
161 | * appropriate chip specific/802.11 pattern. | ||
162 | */ | ||
163 | |||
164 | mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | ||
165 | memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); | ||
166 | memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); | ||
167 | memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, | ||
168 | patterns[i].pattern_len); | ||
169 | memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); | ||
170 | wow_pattern->pattern_len = patterns[i].pattern_len; | ||
171 | |||
261 | /* | 172 | /* |
262 | * we need to untie the internal POR (power-on-reset) | 173 | * just need to take care of deauth and disssoc pattern, |
263 | * to the external PCI-E reset. We also need to tie | 174 | * make sure we don't overwrite them. |
264 | * the PCI-E Phy reset to the PCI-E reset. | ||
265 | */ | 175 | */ |
266 | set = AR_WA_RESET_EN | AR_WA_POR_SHORT; | 176 | |
267 | clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; | 177 | ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, |
268 | REG_RMW(ah, AR_WA, set, clr); | 178 | wow_pattern->mask_bytes, |
179 | i + 2, | ||
180 | wow_pattern->pattern_len); | ||
181 | kfree(wow_pattern); | ||
182 | |||
269 | } | 183 | } |
270 | 184 | ||
271 | /* | 185 | } |
272 | * set the power states appropriately and enable PME | ||
273 | */ | ||
274 | set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | | ||
275 | AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; | ||
276 | 186 | ||
277 | /* | 187 | int ath9k_suspend(struct ieee80211_hw *hw, |
278 | * set and clear WOW_PME_CLEAR registers for the chip | 188 | struct cfg80211_wowlan *wowlan) |
279 | * to generate next wow signal. | 189 | { |
280 | */ | 190 | struct ath_softc *sc = hw->priv; |
281 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 191 | struct ath_hw *ah = sc->sc_ah; |
282 | clr = AR_PMCTRL_WOW_PME_CLR; | 192 | struct ath_common *common = ath9k_hw_common(ah); |
283 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | 193 | u32 wow_triggers_enabled = 0; |
194 | int ret = 0; | ||
284 | 195 | ||
285 | /* | 196 | mutex_lock(&sc->mutex); |
286 | * Setup for: | ||
287 | * - beacon misses | ||
288 | * - magic pattern | ||
289 | * - keep alive timeout | ||
290 | * - pattern matching | ||
291 | */ | ||
292 | 197 | ||
293 | /* | 198 | ath_cancel_work(sc); |
294 | * Program default values for pattern backoff, aifs/slot/KAL count, | 199 | ath_stop_ani(sc); |
295 | * beacon miss timeout, KAL timeout, etc. | 200 | del_timer_sync(&sc->rx_poll_timer); |
296 | */ | ||
297 | set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); | ||
298 | REG_SET_BIT(ah, AR_WOW_PATTERN, set); | ||
299 | 201 | ||
300 | set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | 202 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { |
301 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | 203 | ath_dbg(common, ANY, "Device not present\n"); |
302 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); | 204 | ret = -EINVAL; |
303 | REG_SET_BIT(ah, AR_WOW_COUNT, set); | 205 | goto fail_wow; |
206 | } | ||
304 | 207 | ||
305 | if (pattern_enable & AH_WOW_BEACON_MISS) | 208 | if (WARN_ON(!wowlan)) { |
306 | set = AR_WOW_BEACON_TIMO; | 209 | ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); |
307 | /* We are not using beacon miss, program a large value */ | 210 | ret = -EINVAL; |
308 | else | 211 | goto fail_wow; |
309 | set = AR_WOW_BEACON_TIMO_MAX; | 212 | } |
310 | 213 | ||
311 | REG_WRITE(ah, AR_WOW_BCN_TIMO, set); | 214 | if (!device_can_wakeup(sc->dev)) { |
215 | ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); | ||
216 | ret = 1; | ||
217 | goto fail_wow; | ||
218 | } | ||
312 | 219 | ||
313 | /* | 220 | /* |
314 | * Keep alive timo in ms except AR9280 | 221 | * none of the sta vifs are associated |
222 | * and we are not currently handling multivif | ||
223 | * cases, for instance we have to seperately | ||
224 | * configure 'keep alive frame' for each | ||
225 | * STA. | ||
315 | */ | 226 | */ |
316 | if (!pattern_enable) | ||
317 | set = AR_WOW_KEEP_ALIVE_NEVER; | ||
318 | else | ||
319 | set = KAL_TIMEOUT * 32; | ||
320 | 227 | ||
321 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); | 228 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { |
229 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); | ||
230 | ret = 1; | ||
231 | goto fail_wow; | ||
232 | } | ||
233 | |||
234 | if (sc->nvifs > 1) { | ||
235 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); | ||
236 | ret = 1; | ||
237 | goto fail_wow; | ||
238 | } | ||
239 | |||
240 | ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); | ||
241 | |||
242 | ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", | ||
243 | wow_triggers_enabled); | ||
244 | |||
245 | ath9k_ps_wakeup(sc); | ||
246 | |||
247 | ath9k_stop_btcoex(sc); | ||
322 | 248 | ||
323 | /* | 249 | /* |
324 | * Keep alive delay in us. based on 'power on clock', | 250 | * Enable wake up on recieving disassoc/deauth |
325 | * therefore in usec | 251 | * frame by default. |
326 | */ | 252 | */ |
327 | set = KAL_DELAY * 1000; | 253 | ath9k_wow_add_disassoc_deauth_pattern(sc); |
328 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); | 254 | |
255 | if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) | ||
256 | ath9k_wow_add_pattern(sc, wowlan); | ||
329 | 257 | ||
258 | spin_lock_bh(&sc->sc_pcu_lock); | ||
330 | /* | 259 | /* |
331 | * Create keep alive pattern to respond to beacons | 260 | * To avoid false wake, we enable beacon miss interrupt only |
261 | * when we go to sleep. We save the current interrupt mask | ||
262 | * so we can restore it after the system wakes up | ||
332 | */ | 263 | */ |
333 | ath9k_wow_create_keep_alive_pattern(ah); | 264 | sc->wow_intr_before_sleep = ah->imask; |
265 | ah->imask &= ~ATH9K_INT_GLOBAL; | ||
266 | ath9k_hw_disable_interrupts(ah); | ||
267 | ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; | ||
268 | ath9k_hw_set_interrupts(ah); | ||
269 | ath9k_hw_enable_interrupts(ah); | ||
270 | |||
271 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
334 | 272 | ||
335 | /* | 273 | /* |
336 | * Configure MAC WoW Registers | 274 | * we can now sync irq and kill any running tasklets, since we already |
275 | * disabled interrupts and not holding a spin lock | ||
337 | */ | 276 | */ |
338 | set = 0; | 277 | synchronize_irq(sc->irq); |
339 | /* Send keep alive timeouts anyway */ | 278 | tasklet_kill(&sc->intr_tq); |
340 | clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; | ||
341 | 279 | ||
342 | if (pattern_enable & AH_WOW_LINK_CHANGE) | 280 | ath9k_hw_wow_enable(ah, wow_triggers_enabled); |
343 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; | ||
344 | else | ||
345 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | ||
346 | 281 | ||
347 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | 282 | ath9k_ps_restore(sc); |
348 | REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); | 283 | ath_dbg(common, ANY, "WoW enabled in ath9k\n"); |
284 | atomic_inc(&sc->wow_sleep_proc_intr); | ||
349 | 285 | ||
350 | /* | 286 | fail_wow: |
351 | * we are relying on a bmiss failure. ensure we have | 287 | mutex_unlock(&sc->mutex); |
352 | * enough threshold to prevent false positives | 288 | return ret; |
353 | */ | 289 | } |
354 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, | 290 | |
355 | AR_WOW_BMISSTHRESHOLD); | 291 | int ath9k_resume(struct ieee80211_hw *hw) |
292 | { | ||
293 | struct ath_softc *sc = hw->priv; | ||
294 | struct ath_hw *ah = sc->sc_ah; | ||
295 | struct ath_common *common = ath9k_hw_common(ah); | ||
296 | u32 wow_status; | ||
356 | 297 | ||
357 | set = 0; | 298 | mutex_lock(&sc->mutex); |
358 | clr = 0; | ||
359 | 299 | ||
360 | if (pattern_enable & AH_WOW_BEACON_MISS) { | 300 | ath9k_ps_wakeup(sc); |
361 | set = AR_WOW_BEACON_FAIL_EN; | 301 | |
362 | wow_event_mask |= AR_WOW_BEACON_FAIL; | 302 | spin_lock_bh(&sc->sc_pcu_lock); |
363 | } else { | 303 | |
364 | clr = AR_WOW_BEACON_FAIL_EN; | 304 | ath9k_hw_disable_interrupts(ah); |
305 | ah->imask = sc->wow_intr_before_sleep; | ||
306 | ath9k_hw_set_interrupts(ah); | ||
307 | ath9k_hw_enable_interrupts(ah); | ||
308 | |||
309 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
310 | |||
311 | wow_status = ath9k_hw_wow_wakeup(ah); | ||
312 | |||
313 | if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { | ||
314 | /* | ||
315 | * some devices may not pick beacon miss | ||
316 | * as the reason they woke up so we add | ||
317 | * that here for that shortcoming. | ||
318 | */ | ||
319 | wow_status |= AH_WOW_BEACON_MISS; | ||
320 | atomic_dec(&sc->wow_got_bmiss_intr); | ||
321 | ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); | ||
365 | } | 322 | } |
366 | 323 | ||
367 | REG_RMW(ah, AR_WOW_BCN_EN, set, clr); | 324 | atomic_dec(&sc->wow_sleep_proc_intr); |
368 | 325 | ||
369 | set = 0; | 326 | if (wow_status) { |
370 | clr = 0; | 327 | ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", |
371 | /* | 328 | ath9k_hw_wow_event_to_string(wow_status), wow_status); |
372 | * Enable the magic packet registers | ||
373 | */ | ||
374 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { | ||
375 | set = AR_WOW_MAGIC_EN; | ||
376 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; | ||
377 | } else { | ||
378 | clr = AR_WOW_MAGIC_EN; | ||
379 | } | 329 | } |
380 | set |= AR_WOW_MAC_INTR_EN; | ||
381 | REG_RMW(ah, AR_WOW_PATTERN, set, clr); | ||
382 | 330 | ||
383 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, | 331 | ath_restart_work(sc); |
384 | AR_WOW_PATTERN_SUPPORTED); | 332 | ath9k_start_btcoex(sc); |
385 | 333 | ||
386 | /* | 334 | ath9k_ps_restore(sc); |
387 | * Set the power states appropriately and enable PME | 335 | mutex_unlock(&sc->mutex); |
388 | */ | ||
389 | clr = 0; | ||
390 | set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | | ||
391 | AR_PMCTRL_PWR_PM_CTRL_ENA; | ||
392 | 336 | ||
393 | clr = AR_PCIE_PM_CTRL_ENA; | 337 | return 0; |
394 | REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); | 338 | } |
395 | 339 | ||
396 | /* | 340 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) |
397 | * this is needed to prevent the chip waking up | 341 | { |
398 | * the host within 3-4 seconds with certain | 342 | struct ath_softc *sc = hw->priv; |
399 | * platform/BIOS. The fix is to enable | ||
400 | * D1 & D3 to match original definition and | ||
401 | * also match the OTP value. Anyway this | ||
402 | * is more related to SW WOW. | ||
403 | */ | ||
404 | clr = AR_PMCTRL_PWR_STATE_D1D3; | ||
405 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | ||
406 | 343 | ||
407 | set = AR_PMCTRL_PWR_STATE_D1D3_REAL; | 344 | mutex_lock(&sc->mutex); |
408 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 345 | device_init_wakeup(sc->dev, 1); |
346 | device_set_wakeup_enable(sc->dev, enabled); | ||
347 | mutex_unlock(&sc->mutex); | ||
348 | } | ||
409 | 349 | ||
410 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); | 350 | void ath9k_init_wow(struct ieee80211_hw *hw) |
351 | { | ||
352 | struct ath_softc *sc = hw->priv; | ||
411 | 353 | ||
412 | /* to bring down WOW power low margin */ | 354 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && |
413 | set = BIT(13); | 355 | (sc->driver_data & ATH9K_PCI_WOW) && |
414 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); | 356 | device_can_wakeup(sc->dev)) |
415 | /* HW WoW */ | 357 | hw->wiphy->wowlan = &ath9k_wowlan_support; |
416 | clr = BIT(5); | ||
417 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); | ||
418 | 358 | ||
419 | ath9k_hw_set_powermode_wow_sleep(ah); | 359 | atomic_set(&sc->wow_sleep_proc_intr, -1); |
420 | ah->wow_event_mask = wow_event_mask; | 360 | atomic_set(&sc->wow_got_bmiss_intr, -1); |
421 | } | 361 | } |
422 | EXPORT_SYMBOL(ath9k_hw_wow_enable); | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 09cdbcd09739..24846d91554b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1786,6 +1786,9 @@ bool ath_drain_all_txq(struct ath_softc *sc) | |||
1786 | if (!ATH_TXQ_SETUP(sc, i)) | 1786 | if (!ATH_TXQ_SETUP(sc, i)) |
1787 | continue; | 1787 | continue; |
1788 | 1788 | ||
1789 | if (!sc->tx.txq[i].axq_depth) | ||
1790 | continue; | ||
1791 | |||
1789 | if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum)) | 1792 | if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum)) |
1790 | npend |= BIT(i); | 1793 | npend |= BIT(i); |
1791 | } | 1794 | } |
@@ -2749,6 +2752,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2749 | } | 2752 | } |
2750 | } | 2753 | } |
2751 | 2754 | ||
2755 | #ifdef CONFIG_ATH9K_TX99 | ||
2756 | |||
2752 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | 2757 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, |
2753 | struct ath_tx_control *txctl) | 2758 | struct ath_tx_control *txctl) |
2754 | { | 2759 | { |
@@ -2791,3 +2796,5 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | |||
2791 | 2796 | ||
2792 | return 0; | 2797 | return 0; |
2793 | } | 2798 | } |
2799 | |||
2800 | #endif /* CONFIG_ATH9K_TX99 */ | ||
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 1217c52ab28e..9e154732afaa 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -37,17 +37,18 @@ static int __ath_regd_init(struct ath_regulatory *reg); | |||
37 | 37 | ||
38 | /* We enable active scan on these a case by case basis by regulatory domain */ | 38 | /* We enable active scan on these a case by case basis by regulatory domain */ |
39 | #define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ | 39 | #define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ |
40 | NL80211_RRF_PASSIVE_SCAN) | 40 | NL80211_RRF_NO_IR) |
41 | #define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ | 41 | #define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ |
42 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) | 42 | NL80211_RRF_NO_IR | \ |
43 | NL80211_RRF_NO_OFDM) | ||
43 | 44 | ||
44 | /* We allow IBSS on these on a case by case basis by regulatory domain */ | 45 | /* We allow IBSS on these on a case by case basis by regulatory domain */ |
45 | #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ | 46 | #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ |
46 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) | 47 | NL80211_RRF_NO_IR) |
47 | #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ | 48 | #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ |
48 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) | 49 | NL80211_RRF_NO_IR) |
49 | #define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ | 50 | #define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ |
50 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) | 51 | NL80211_RRF_NO_IR) |
51 | 52 | ||
52 | #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ | 53 | #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ |
53 | ATH9K_2GHZ_CH12_13, \ | 54 | ATH9K_2GHZ_CH12_13, \ |
@@ -113,6 +114,87 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { | |||
113 | } | 114 | } |
114 | }; | 115 | }; |
115 | 116 | ||
117 | static bool dynamic_country_user_possible(struct ath_regulatory *reg) | ||
118 | { | ||
119 | if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) | ||
120 | return true; | ||
121 | |||
122 | switch (reg->country_code) { | ||
123 | case CTRY_UNITED_STATES: | ||
124 | case CTRY_JAPAN1: | ||
125 | case CTRY_JAPAN2: | ||
126 | case CTRY_JAPAN3: | ||
127 | case CTRY_JAPAN4: | ||
128 | case CTRY_JAPAN5: | ||
129 | case CTRY_JAPAN6: | ||
130 | case CTRY_JAPAN7: | ||
131 | case CTRY_JAPAN8: | ||
132 | case CTRY_JAPAN9: | ||
133 | case CTRY_JAPAN10: | ||
134 | case CTRY_JAPAN11: | ||
135 | case CTRY_JAPAN12: | ||
136 | case CTRY_JAPAN13: | ||
137 | case CTRY_JAPAN14: | ||
138 | case CTRY_JAPAN15: | ||
139 | case CTRY_JAPAN16: | ||
140 | case CTRY_JAPAN17: | ||
141 | case CTRY_JAPAN18: | ||
142 | case CTRY_JAPAN19: | ||
143 | case CTRY_JAPAN20: | ||
144 | case CTRY_JAPAN21: | ||
145 | case CTRY_JAPAN22: | ||
146 | case CTRY_JAPAN23: | ||
147 | case CTRY_JAPAN24: | ||
148 | case CTRY_JAPAN25: | ||
149 | case CTRY_JAPAN26: | ||
150 | case CTRY_JAPAN27: | ||
151 | case CTRY_JAPAN28: | ||
152 | case CTRY_JAPAN29: | ||
153 | case CTRY_JAPAN30: | ||
154 | case CTRY_JAPAN31: | ||
155 | case CTRY_JAPAN32: | ||
156 | case CTRY_JAPAN33: | ||
157 | case CTRY_JAPAN34: | ||
158 | case CTRY_JAPAN35: | ||
159 | case CTRY_JAPAN36: | ||
160 | case CTRY_JAPAN37: | ||
161 | case CTRY_JAPAN38: | ||
162 | case CTRY_JAPAN39: | ||
163 | case CTRY_JAPAN40: | ||
164 | case CTRY_JAPAN41: | ||
165 | case CTRY_JAPAN42: | ||
166 | case CTRY_JAPAN43: | ||
167 | case CTRY_JAPAN44: | ||
168 | case CTRY_JAPAN45: | ||
169 | case CTRY_JAPAN46: | ||
170 | case CTRY_JAPAN47: | ||
171 | case CTRY_JAPAN48: | ||
172 | case CTRY_JAPAN49: | ||
173 | case CTRY_JAPAN50: | ||
174 | case CTRY_JAPAN51: | ||
175 | case CTRY_JAPAN52: | ||
176 | case CTRY_JAPAN53: | ||
177 | case CTRY_JAPAN54: | ||
178 | case CTRY_JAPAN55: | ||
179 | case CTRY_JAPAN56: | ||
180 | case CTRY_JAPAN57: | ||
181 | case CTRY_JAPAN58: | ||
182 | case CTRY_JAPAN59: | ||
183 | return false; | ||
184 | } | ||
185 | |||
186 | return true; | ||
187 | } | ||
188 | |||
189 | static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg) | ||
190 | { | ||
191 | if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) | ||
192 | return false; | ||
193 | if (!dynamic_country_user_possible(reg)) | ||
194 | return false; | ||
195 | return true; | ||
196 | } | ||
197 | |||
116 | static inline bool is_wwr_sku(u16 regd) | 198 | static inline bool is_wwr_sku(u16 regd) |
117 | { | 199 | { |
118 | return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && | 200 | return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && |
@@ -177,118 +259,139 @@ static bool ath_is_radar_freq(u16 center_freq) | |||
177 | return (center_freq >= 5260 && center_freq <= 5700); | 259 | return (center_freq >= 5260 && center_freq <= 5700); |
178 | } | 260 | } |
179 | 261 | ||
262 | static void ath_force_clear_no_ir_chan(struct wiphy *wiphy, | ||
263 | struct ieee80211_channel *ch) | ||
264 | { | ||
265 | const struct ieee80211_reg_rule *reg_rule; | ||
266 | |||
267 | reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); | ||
268 | if (IS_ERR(reg_rule)) | ||
269 | return; | ||
270 | |||
271 | if (!(reg_rule->flags & NL80211_RRF_NO_IR)) | ||
272 | if (ch->flags & IEEE80211_CHAN_NO_IR) | ||
273 | ch->flags &= ~IEEE80211_CHAN_NO_IR; | ||
274 | } | ||
275 | |||
276 | static void ath_force_clear_no_ir_freq(struct wiphy *wiphy, u16 center_freq) | ||
277 | { | ||
278 | struct ieee80211_channel *ch; | ||
279 | |||
280 | ch = ieee80211_get_channel(wiphy, center_freq); | ||
281 | if (!ch) | ||
282 | return; | ||
283 | |||
284 | ath_force_clear_no_ir_chan(wiphy, ch); | ||
285 | } | ||
286 | |||
287 | static void ath_force_no_ir_chan(struct ieee80211_channel *ch) | ||
288 | { | ||
289 | ch->flags |= IEEE80211_CHAN_NO_IR; | ||
290 | } | ||
291 | |||
292 | static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq) | ||
293 | { | ||
294 | struct ieee80211_channel *ch; | ||
295 | |||
296 | ch = ieee80211_get_channel(wiphy, center_freq); | ||
297 | if (!ch) | ||
298 | return; | ||
299 | |||
300 | ath_force_no_ir_chan(ch); | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | __ath_reg_apply_beaconing_flags(struct wiphy *wiphy, | ||
305 | struct ath_regulatory *reg, | ||
306 | enum nl80211_reg_initiator initiator, | ||
307 | struct ieee80211_channel *ch) | ||
308 | { | ||
309 | if (ath_is_radar_freq(ch->center_freq) || | ||
310 | (ch->flags & IEEE80211_CHAN_RADAR)) | ||
311 | return; | ||
312 | |||
313 | switch (initiator) { | ||
314 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | ||
315 | ath_force_clear_no_ir_chan(wiphy, ch); | ||
316 | break; | ||
317 | case NL80211_REGDOM_SET_BY_USER: | ||
318 | if (ath_reg_dyn_country_user_allow(reg)) | ||
319 | ath_force_clear_no_ir_chan(wiphy, ch); | ||
320 | break; | ||
321 | default: | ||
322 | if (ch->beacon_found) | ||
323 | ch->flags &= ~IEEE80211_CHAN_NO_IR; | ||
324 | } | ||
325 | } | ||
326 | |||
180 | /* | 327 | /* |
181 | * N.B: These exception rules do not apply radar freqs. | 328 | * These exception rules do not apply radar frequencies. |
182 | * | 329 | * |
183 | * - We enable adhoc (or beaconing) if allowed by 11d | 330 | * - We enable initiating radiation if the country IE says its fine: |
184 | * - We enable active scan if the channel is allowed by 11d | ||
185 | * - If no country IE has been processed and a we determine we have | 331 | * - If no country IE has been processed and a we determine we have |
186 | * received a beacon on a channel we can enable active scan and | 332 | * received a beacon on a channel we can enable initiating radiation. |
187 | * adhoc (or beaconing). | ||
188 | */ | 333 | */ |
189 | static void | 334 | static void |
190 | ath_reg_apply_beaconing_flags(struct wiphy *wiphy, | 335 | ath_reg_apply_beaconing_flags(struct wiphy *wiphy, |
336 | struct ath_regulatory *reg, | ||
191 | enum nl80211_reg_initiator initiator) | 337 | enum nl80211_reg_initiator initiator) |
192 | { | 338 | { |
193 | enum ieee80211_band band; | 339 | enum ieee80211_band band; |
194 | struct ieee80211_supported_band *sband; | 340 | struct ieee80211_supported_band *sband; |
195 | const struct ieee80211_reg_rule *reg_rule; | ||
196 | struct ieee80211_channel *ch; | 341 | struct ieee80211_channel *ch; |
197 | unsigned int i; | 342 | unsigned int i; |
198 | 343 | ||
199 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 344 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
200 | |||
201 | if (!wiphy->bands[band]) | 345 | if (!wiphy->bands[band]) |
202 | continue; | 346 | continue; |
203 | |||
204 | sband = wiphy->bands[band]; | 347 | sband = wiphy->bands[band]; |
205 | |||
206 | for (i = 0; i < sband->n_channels; i++) { | 348 | for (i = 0; i < sband->n_channels; i++) { |
207 | |||
208 | ch = &sband->channels[i]; | 349 | ch = &sband->channels[i]; |
209 | 350 | __ath_reg_apply_beaconing_flags(wiphy, reg, | |
210 | if (ath_is_radar_freq(ch->center_freq) || | 351 | initiator, ch); |
211 | (ch->flags & IEEE80211_CHAN_RADAR)) | ||
212 | continue; | ||
213 | |||
214 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
215 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | ||
216 | if (IS_ERR(reg_rule)) | ||
217 | continue; | ||
218 | /* | ||
219 | * If 11d had a rule for this channel ensure | ||
220 | * we enable adhoc/beaconing if it allows us to | ||
221 | * use it. Note that we would have disabled it | ||
222 | * by applying our static world regdomain by | ||
223 | * default during init, prior to calling our | ||
224 | * regulatory_hint(). | ||
225 | */ | ||
226 | if (!(reg_rule->flags & | ||
227 | NL80211_RRF_NO_IBSS)) | ||
228 | ch->flags &= | ||
229 | ~IEEE80211_CHAN_NO_IBSS; | ||
230 | if (!(reg_rule->flags & | ||
231 | NL80211_RRF_PASSIVE_SCAN)) | ||
232 | ch->flags &= | ||
233 | ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
234 | } else { | ||
235 | if (ch->beacon_found) | ||
236 | ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | | ||
237 | IEEE80211_CHAN_PASSIVE_SCAN); | ||
238 | } | ||
239 | } | 352 | } |
240 | } | 353 | } |
241 | |||
242 | } | 354 | } |
243 | 355 | ||
244 | /* Allows active scan scan on Ch 12 and 13 */ | 356 | /** |
357 | * ath_reg_apply_ir_flags() | ||
358 | * @wiphy: the wiphy to use | ||
359 | * @initiator: the regulatory hint initiator | ||
360 | * | ||
361 | * If no country IE has been received always enable passive scan | ||
362 | * and no-ibss on these channels. This is only done for specific | ||
363 | * regulatory SKUs. | ||
364 | * | ||
365 | * If a country IE has been received check its rule for this | ||
366 | * channel first before enabling active scan. The passive scan | ||
367 | * would have been enforced by the initial processing of our | ||
368 | * custom regulatory domain. | ||
369 | */ | ||
245 | static void | 370 | static void |
246 | ath_reg_apply_active_scan_flags(struct wiphy *wiphy, | 371 | ath_reg_apply_ir_flags(struct wiphy *wiphy, |
247 | enum nl80211_reg_initiator initiator) | 372 | struct ath_regulatory *reg, |
373 | enum nl80211_reg_initiator initiator) | ||
248 | { | 374 | { |
249 | struct ieee80211_supported_band *sband; | 375 | struct ieee80211_supported_band *sband; |
250 | struct ieee80211_channel *ch; | ||
251 | const struct ieee80211_reg_rule *reg_rule; | ||
252 | 376 | ||
253 | sband = wiphy->bands[IEEE80211_BAND_2GHZ]; | 377 | sband = wiphy->bands[IEEE80211_BAND_2GHZ]; |
254 | if (!sband) | 378 | if (!sband) |
255 | return; | 379 | return; |
256 | 380 | ||
257 | /* | 381 | switch(initiator) { |
258 | * If no country IE has been received always enable active scan | 382 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
259 | * on these channels. This is only done for specific regulatory SKUs | 383 | ath_force_clear_no_ir_freq(wiphy, 2467); |
260 | */ | 384 | ath_force_clear_no_ir_freq(wiphy, 2472); |
261 | if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 385 | break; |
262 | ch = &sband->channels[11]; /* CH 12 */ | 386 | case NL80211_REGDOM_SET_BY_USER: |
263 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 387 | if (!ath_reg_dyn_country_user_allow(reg)) |
264 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 388 | break; |
265 | ch = &sband->channels[12]; /* CH 13 */ | 389 | ath_force_clear_no_ir_freq(wiphy, 2467); |
266 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 390 | ath_force_clear_no_ir_freq(wiphy, 2472); |
267 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 391 | break; |
268 | return; | 392 | default: |
269 | } | 393 | ath_force_no_ir_freq(wiphy, 2467); |
270 | 394 | ath_force_no_ir_freq(wiphy, 2472); | |
271 | /* | ||
272 | * If a country IE has been received check its rule for this | ||
273 | * channel first before enabling active scan. The passive scan | ||
274 | * would have been enforced by the initial processing of our | ||
275 | * custom regulatory domain. | ||
276 | */ | ||
277 | |||
278 | ch = &sband->channels[11]; /* CH 12 */ | ||
279 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | ||
280 | if (!IS_ERR(reg_rule)) { | ||
281 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | ||
282 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
283 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
284 | } | ||
285 | |||
286 | ch = &sband->channels[12]; /* CH 13 */ | ||
287 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | ||
288 | if (!IS_ERR(reg_rule)) { | ||
289 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | ||
290 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
291 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
292 | } | 395 | } |
293 | } | 396 | } |
294 | 397 | ||
@@ -320,8 +423,7 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy) | |||
320 | */ | 423 | */ |
321 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) | 424 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) |
322 | ch->flags |= IEEE80211_CHAN_RADAR | | 425 | ch->flags |= IEEE80211_CHAN_RADAR | |
323 | IEEE80211_CHAN_NO_IBSS | | 426 | IEEE80211_CHAN_NO_IR; |
324 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
325 | } | 427 | } |
326 | } | 428 | } |
327 | 429 | ||
@@ -335,12 +437,15 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, | |||
335 | case 0x66: | 437 | case 0x66: |
336 | case 0x67: | 438 | case 0x67: |
337 | case 0x6C: | 439 | case 0x6C: |
338 | ath_reg_apply_beaconing_flags(wiphy, initiator); | 440 | ath_reg_apply_beaconing_flags(wiphy, reg, initiator); |
339 | break; | 441 | break; |
340 | case 0x68: | 442 | case 0x68: |
341 | ath_reg_apply_beaconing_flags(wiphy, initiator); | 443 | ath_reg_apply_beaconing_flags(wiphy, reg, initiator); |
342 | ath_reg_apply_active_scan_flags(wiphy, initiator); | 444 | ath_reg_apply_ir_flags(wiphy, reg, initiator); |
343 | break; | 445 | break; |
446 | default: | ||
447 | if (ath_reg_dyn_country_user_allow(reg)) | ||
448 | ath_reg_apply_beaconing_flags(wiphy, reg, initiator); | ||
344 | } | 449 | } |
345 | } | 450 | } |
346 | 451 | ||
@@ -393,89 +498,6 @@ static void ath_reg_dyn_country(struct wiphy *wiphy, | |||
393 | reg_initiator_name(request->initiator)); | 498 | reg_initiator_name(request->initiator)); |
394 | } | 499 | } |
395 | 500 | ||
396 | static bool dynamic_country_user_possible(struct ath_regulatory *reg) | ||
397 | { | ||
398 | if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) | ||
399 | return true; | ||
400 | |||
401 | switch (reg->country_code) { | ||
402 | case CTRY_UNITED_STATES: | ||
403 | case CTRY_JAPAN1: | ||
404 | case CTRY_JAPAN2: | ||
405 | case CTRY_JAPAN3: | ||
406 | case CTRY_JAPAN4: | ||
407 | case CTRY_JAPAN5: | ||
408 | case CTRY_JAPAN6: | ||
409 | case CTRY_JAPAN7: | ||
410 | case CTRY_JAPAN8: | ||
411 | case CTRY_JAPAN9: | ||
412 | case CTRY_JAPAN10: | ||
413 | case CTRY_JAPAN11: | ||
414 | case CTRY_JAPAN12: | ||
415 | case CTRY_JAPAN13: | ||
416 | case CTRY_JAPAN14: | ||
417 | case CTRY_JAPAN15: | ||
418 | case CTRY_JAPAN16: | ||
419 | case CTRY_JAPAN17: | ||
420 | case CTRY_JAPAN18: | ||
421 | case CTRY_JAPAN19: | ||
422 | case CTRY_JAPAN20: | ||
423 | case CTRY_JAPAN21: | ||
424 | case CTRY_JAPAN22: | ||
425 | case CTRY_JAPAN23: | ||
426 | case CTRY_JAPAN24: | ||
427 | case CTRY_JAPAN25: | ||
428 | case CTRY_JAPAN26: | ||
429 | case CTRY_JAPAN27: | ||
430 | case CTRY_JAPAN28: | ||
431 | case CTRY_JAPAN29: | ||
432 | case CTRY_JAPAN30: | ||
433 | case CTRY_JAPAN31: | ||
434 | case CTRY_JAPAN32: | ||
435 | case CTRY_JAPAN33: | ||
436 | case CTRY_JAPAN34: | ||
437 | case CTRY_JAPAN35: | ||
438 | case CTRY_JAPAN36: | ||
439 | case CTRY_JAPAN37: | ||
440 | case CTRY_JAPAN38: | ||
441 | case CTRY_JAPAN39: | ||
442 | case CTRY_JAPAN40: | ||
443 | case CTRY_JAPAN41: | ||
444 | case CTRY_JAPAN42: | ||
445 | case CTRY_JAPAN43: | ||
446 | case CTRY_JAPAN44: | ||
447 | case CTRY_JAPAN45: | ||
448 | case CTRY_JAPAN46: | ||
449 | case CTRY_JAPAN47: | ||
450 | case CTRY_JAPAN48: | ||
451 | case CTRY_JAPAN49: | ||
452 | case CTRY_JAPAN50: | ||
453 | case CTRY_JAPAN51: | ||
454 | case CTRY_JAPAN52: | ||
455 | case CTRY_JAPAN53: | ||
456 | case CTRY_JAPAN54: | ||
457 | case CTRY_JAPAN55: | ||
458 | case CTRY_JAPAN56: | ||
459 | case CTRY_JAPAN57: | ||
460 | case CTRY_JAPAN58: | ||
461 | case CTRY_JAPAN59: | ||
462 | return false; | ||
463 | } | ||
464 | |||
465 | return true; | ||
466 | } | ||
467 | |||
468 | static void ath_reg_dyn_country_user(struct wiphy *wiphy, | ||
469 | struct ath_regulatory *reg, | ||
470 | struct regulatory_request *request) | ||
471 | { | ||
472 | if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) | ||
473 | return; | ||
474 | if (!dynamic_country_user_possible(reg)) | ||
475 | return; | ||
476 | ath_reg_dyn_country(wiphy, reg, request); | ||
477 | } | ||
478 | |||
479 | void ath_reg_notifier_apply(struct wiphy *wiphy, | 501 | void ath_reg_notifier_apply(struct wiphy *wiphy, |
480 | struct regulatory_request *request, | 502 | struct regulatory_request *request, |
481 | struct ath_regulatory *reg) | 503 | struct ath_regulatory *reg) |
@@ -508,7 +530,8 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, | |||
508 | case NL80211_REGDOM_SET_BY_DRIVER: | 530 | case NL80211_REGDOM_SET_BY_DRIVER: |
509 | break; | 531 | break; |
510 | case NL80211_REGDOM_SET_BY_USER: | 532 | case NL80211_REGDOM_SET_BY_USER: |
511 | ath_reg_dyn_country_user(wiphy, reg, request); | 533 | if (ath_reg_dyn_country_user_allow(reg)) |
534 | ath_reg_dyn_country(wiphy, reg, request); | ||
512 | break; | 535 | break; |
513 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 536 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
514 | ath_reg_dyn_country(wiphy, reg, request); | 537 | ath_reg_dyn_country(wiphy, reg, request); |
@@ -609,7 +632,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
609 | const struct ieee80211_regdomain *regd; | 632 | const struct ieee80211_regdomain *regd; |
610 | 633 | ||
611 | wiphy->reg_notifier = reg_notifier; | 634 | wiphy->reg_notifier = reg_notifier; |
612 | wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; | 635 | wiphy->regulatory_flags |= REGULATORY_STRICT_REG; |
613 | 636 | ||
614 | if (ath_is_world_regd(reg)) { | 637 | if (ath_is_world_regd(reg)) { |
615 | /* | 638 | /* |
@@ -617,7 +640,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
617 | * saved on the wiphy orig_* parameters | 640 | * saved on the wiphy orig_* parameters |
618 | */ | 641 | */ |
619 | regd = ath_world_regdomain(reg); | 642 | regd = ath_world_regdomain(reg); |
620 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 643 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
644 | REGULATORY_COUNTRY_IE_FOLLOW_POWER; | ||
621 | } else { | 645 | } else { |
622 | /* | 646 | /* |
623 | * This gets applied in the case of the absence of CRDA, | 647 | * This gets applied in the case of the absence of CRDA, |
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index c02dbc618724..3c2ef0c32f72 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h | |||
@@ -2644,7 +2644,7 @@ struct wcn36xx_hal_trigger_ba_rsp_candidate { | |||
2644 | struct add_ba_info ba_info[STACFG_MAX_TC]; | 2644 | struct add_ba_info ba_info[STACFG_MAX_TC]; |
2645 | } __packed; | 2645 | } __packed; |
2646 | 2646 | ||
2647 | struct wcn36xx_hal_trigget_ba_req_candidate { | 2647 | struct wcn36xx_hal_trigger_ba_req_candidate { |
2648 | u8 sta_index; | 2648 | u8 sta_index; |
2649 | u8 tid_bitmap; | 2649 | u8 tid_bitmap; |
2650 | } __packed; | 2650 | } __packed; |
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7839b31e4826..e64a6784079e 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
@@ -641,7 +641,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, | |||
641 | dev_kfree_skb(skb); | 641 | dev_kfree_skb(skb); |
642 | } | 642 | } |
643 | 643 | ||
644 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 644 | if (changed & BSS_CHANGED_BEACON_ENABLED || |
645 | changed & BSS_CHANGED_BEACON) { | ||
645 | wcn36xx_dbg(WCN36XX_DBG_MAC, | 646 | wcn36xx_dbg(WCN36XX_DBG_MAC, |
646 | "mac bss changed beacon enabled %d\n", | 647 | "mac bss changed beacon enabled %d\n", |
647 | bss_conf->enable_beacon); | 648 | bss_conf->enable_beacon); |
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 366339421d4f..823631cdb872 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
@@ -115,6 +115,22 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, | |||
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | static void wcn36xx_smd_set_sta_default_ht_params( | ||
119 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
120 | { | ||
121 | sta_params->ht_capable = 1; | ||
122 | sta_params->tx_channel_width_set = 1; | ||
123 | sta_params->lsig_txop_protection = 1; | ||
124 | sta_params->max_ampdu_size = 3; | ||
125 | sta_params->max_ampdu_density = 5; | ||
126 | sta_params->max_amsdu_size = 0; | ||
127 | sta_params->sgi_20Mhz = 1; | ||
128 | sta_params->sgi_40mhz = 1; | ||
129 | sta_params->green_field_capable = 1; | ||
130 | sta_params->delayed_ba_support = 0; | ||
131 | sta_params->dsss_cck_mode_40mhz = 1; | ||
132 | } | ||
133 | |||
118 | static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, | 134 | static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, |
119 | struct ieee80211_vif *vif, | 135 | struct ieee80211_vif *vif, |
120 | struct ieee80211_sta *sta, | 136 | struct ieee80211_sta *sta, |
@@ -172,6 +188,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, | |||
172 | sizeof(priv_sta->supported_rates)); | 188 | sizeof(priv_sta->supported_rates)); |
173 | } else { | 189 | } else { |
174 | wcn36xx_set_default_rates(&sta_params->supported_rates); | 190 | wcn36xx_set_default_rates(&sta_params->supported_rates); |
191 | wcn36xx_smd_set_sta_default_ht_params(sta_params); | ||
175 | } | 192 | } |
176 | } | 193 | } |
177 | 194 | ||
@@ -1838,7 +1855,7 @@ out: | |||
1838 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) | 1855 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) |
1839 | { | 1856 | { |
1840 | struct wcn36xx_hal_trigger_ba_req_msg msg_body; | 1857 | struct wcn36xx_hal_trigger_ba_req_msg msg_body; |
1841 | struct wcn36xx_hal_trigget_ba_req_candidate *candidate; | 1858 | struct wcn36xx_hal_trigger_ba_req_candidate *candidate; |
1842 | int ret = 0; | 1859 | int ret = 0; |
1843 | 1860 | ||
1844 | mutex_lock(&wcn->hal_mutex); | 1861 | mutex_lock(&wcn->hal_mutex); |
@@ -1849,7 +1866,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) | |||
1849 | msg_body.header.len += sizeof(*candidate); | 1866 | msg_body.header.len += sizeof(*candidate); |
1850 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | 1867 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); |
1851 | 1868 | ||
1852 | candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) | 1869 | candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *) |
1853 | (wcn->hal_buf + sizeof(msg_body)); | 1870 | (wcn->hal_buf + sizeof(msg_body)); |
1854 | candidate->sta_index = sta_index; | 1871 | candidate->sta_index = sta_index; |
1855 | candidate->tid_bitmap = 1; | 1872 | candidate->tid_bitmap = 1; |
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 58b63833e8e7..8fa5cbace5ab 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
@@ -54,7 +54,7 @@ enum wcn36xx_debug_mask { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | #define wcn36xx_err(fmt, arg...) \ | 56 | #define wcn36xx_err(fmt, arg...) \ |
57 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); | 57 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg) |
58 | 58 | ||
59 | #define wcn36xx_warn(fmt, arg...) \ | 59 | #define wcn36xx_warn(fmt, arg...) \ |
60 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) | 60 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) |
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 54e36fcb3954..fcfed6b99a62 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig | |||
@@ -4,13 +4,12 @@ config BRCMUTIL | |||
4 | config BRCMSMAC | 4 | config BRCMSMAC |
5 | tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" | 5 | tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" |
6 | depends on MAC80211 | 6 | depends on MAC80211 |
7 | depends on BCMA | 7 | depends on BCMA_POSSIBLE |
8 | select BCMA | ||
8 | select NEW_LEDS if BCMA_DRIVER_GPIO | 9 | select NEW_LEDS if BCMA_DRIVER_GPIO |
9 | select LEDS_CLASS if BCMA_DRIVER_GPIO | 10 | select LEDS_CLASS if BCMA_DRIVER_GPIO |
10 | select BRCMUTIL | 11 | select BRCMUTIL |
11 | select FW_LOADER | 12 | select FW_LOADER |
12 | select CRC_CCITT | ||
13 | select CRC8 | ||
14 | select CORDIC | 13 | select CORDIC |
15 | ---help--- | 14 | ---help--- |
16 | This module adds support for PCIe wireless adapters based on Broadcom | 15 | This module adds support for PCIe wireless adapters based on Broadcom |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 8e9b1221b32c..2082402d4b63 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -28,7 +28,8 @@ brcmfmac-objs += \ | |||
28 | fweh.o \ | 28 | fweh.o \ |
29 | fwsignal.o \ | 29 | fwsignal.o \ |
30 | p2p.o \ | 30 | p2p.o \ |
31 | dhd_cdc.o \ | 31 | proto.o \ |
32 | bcdc.o \ | ||
32 | dhd_common.o \ | 33 | dhd_common.o \ |
33 | dhd_linux.o \ | 34 | dhd_linux.o \ |
34 | btcoex.o | 35 | btcoex.o |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c new file mode 100644 index 000000000000..06848e426f9a --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | |||
@@ -0,0 +1,384 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /******************************************************************************* | ||
18 | * Communicates with the dongle by using dcmd codes. | ||
19 | * For certain dcmd codes, the dongle interprets string data from the host. | ||
20 | ******************************************************************************/ | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | #include <linux/netdevice.h> | ||
24 | |||
25 | #include <brcmu_utils.h> | ||
26 | #include <brcmu_wifi.h> | ||
27 | |||
28 | #include "dhd.h" | ||
29 | #include "dhd_bus.h" | ||
30 | #include "fwsignal.h" | ||
31 | #include "dhd_dbg.h" | ||
32 | #include "tracepoint.h" | ||
33 | #include "proto.h" | ||
34 | #include "bcdc.h" | ||
35 | |||
36 | struct brcmf_proto_bcdc_dcmd { | ||
37 | __le32 cmd; /* dongle command value */ | ||
38 | __le32 len; /* lower 16: output buflen; | ||
39 | * upper 16: input buflen (excludes header) */ | ||
40 | __le32 flags; /* flag defns given below */ | ||
41 | __le32 status; /* status code returned from the device */ | ||
42 | }; | ||
43 | |||
44 | /* Max valid buffer size that can be sent to the dongle */ | ||
45 | #define BCDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) | ||
46 | |||
47 | /* BCDC flag definitions */ | ||
48 | #define BCDC_DCMD_ERROR 0x01 /* 1=cmd failed */ | ||
49 | #define BCDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ | ||
50 | #define BCDC_DCMD_IF_MASK 0xF000 /* I/F index */ | ||
51 | #define BCDC_DCMD_IF_SHIFT 12 | ||
52 | #define BCDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ | ||
53 | #define BCDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ | ||
54 | #define BCDC_DCMD_ID(flags) \ | ||
55 | (((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT) | ||
56 | |||
57 | /* | ||
58 | * BCDC header - Broadcom specific extension of CDC. | ||
59 | * Used on data packets to convey priority across USB. | ||
60 | */ | ||
61 | #define BCDC_HEADER_LEN 4 | ||
62 | #define BCDC_PROTO_VER 2 /* Protocol version */ | ||
63 | #define BCDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ | ||
64 | #define BCDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ | ||
65 | #define BCDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ | ||
66 | #define BCDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ | ||
67 | #define BCDC_PRIORITY_MASK 0x7 | ||
68 | #define BCDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ | ||
69 | #define BCDC_FLAG2_IF_SHIFT 0 | ||
70 | |||
71 | #define BCDC_GET_IF_IDX(hdr) \ | ||
72 | ((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT)) | ||
73 | #define BCDC_SET_IF_IDX(hdr, idx) \ | ||
74 | ((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \ | ||
75 | ((idx) << BCDC_FLAG2_IF_SHIFT))) | ||
76 | |||
77 | /** | ||
78 | * struct brcmf_proto_bcdc_header - BCDC header format | ||
79 | * | ||
80 | * @flags: flags contain protocol and checksum info. | ||
81 | * @priority: 802.1d priority and USB flow control info (bit 4:7). | ||
82 | * @flags2: additional flags containing dongle interface index. | ||
83 | * @data_offset: start of packet data. header is following by firmware signals. | ||
84 | */ | ||
85 | struct brcmf_proto_bcdc_header { | ||
86 | u8 flags; | ||
87 | u8 priority; | ||
88 | u8 flags2; | ||
89 | u8 data_offset; | ||
90 | }; | ||
91 | |||
92 | /* | ||
93 | * maximum length of firmware signal data between | ||
94 | * the BCDC header and packet data in the tx path. | ||
95 | */ | ||
96 | #define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 | ||
97 | |||
98 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ | ||
99 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE | ||
100 | * (amount of header tha might be added) | ||
101 | * plus any space that might be needed | ||
102 | * for bus alignment padding. | ||
103 | */ | ||
104 | #define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for | ||
105 | * round off at the end of buffer | ||
106 | * Currently is SDIO | ||
107 | */ | ||
108 | |||
109 | struct brcmf_bcdc { | ||
110 | u16 reqid; | ||
111 | u8 bus_header[BUS_HEADER_LEN]; | ||
112 | struct brcmf_proto_bcdc_dcmd msg; | ||
113 | unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; | ||
114 | }; | ||
115 | |||
116 | static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr) | ||
117 | { | ||
118 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; | ||
119 | int len = le32_to_cpu(bcdc->msg.len) + | ||
120 | sizeof(struct brcmf_proto_bcdc_dcmd); | ||
121 | |||
122 | brcmf_dbg(BCDC, "Enter\n"); | ||
123 | |||
124 | /* NOTE : bcdc->msg.len holds the desired length of the buffer to be | ||
125 | * returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area | ||
126 | * is actually sent to the dongle | ||
127 | */ | ||
128 | if (len > BCDC_MAX_MSG_SIZE) | ||
129 | len = BCDC_MAX_MSG_SIZE; | ||
130 | |||
131 | /* Send request */ | ||
132 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); | ||
133 | } | ||
134 | |||
135 | static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | ||
136 | { | ||
137 | int ret; | ||
138 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; | ||
139 | |||
140 | brcmf_dbg(BCDC, "Enter\n"); | ||
141 | len += sizeof(struct brcmf_proto_bcdc_dcmd); | ||
142 | do { | ||
143 | ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg, | ||
144 | len); | ||
145 | if (ret < 0) | ||
146 | break; | ||
147 | } while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id); | ||
148 | |||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static int | ||
153 | brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
154 | void *buf, uint len) | ||
155 | { | ||
156 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; | ||
157 | struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; | ||
158 | void *info; | ||
159 | int ret = 0, retries = 0; | ||
160 | u32 id, flags; | ||
161 | |||
162 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); | ||
163 | |||
164 | memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); | ||
165 | |||
166 | msg->cmd = cpu_to_le32(cmd); | ||
167 | msg->len = cpu_to_le32(len); | ||
168 | flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT); | ||
169 | flags = (flags & ~BCDC_DCMD_IF_MASK) | | ||
170 | (ifidx << BCDC_DCMD_IF_SHIFT); | ||
171 | msg->flags = cpu_to_le32(flags); | ||
172 | |||
173 | if (buf) | ||
174 | memcpy(bcdc->buf, buf, len); | ||
175 | |||
176 | ret = brcmf_proto_bcdc_msg(drvr); | ||
177 | if (ret < 0) { | ||
178 | brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", | ||
179 | ret); | ||
180 | goto done; | ||
181 | } | ||
182 | |||
183 | retry: | ||
184 | /* wait for interrupt and get first fragment */ | ||
185 | ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len); | ||
186 | if (ret < 0) | ||
187 | goto done; | ||
188 | |||
189 | flags = le32_to_cpu(msg->flags); | ||
190 | id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT; | ||
191 | |||
192 | if ((id < bcdc->reqid) && (++retries < RETRIES)) | ||
193 | goto retry; | ||
194 | if (id != bcdc->reqid) { | ||
195 | brcmf_err("%s: unexpected request id %d (expected %d)\n", | ||
196 | brcmf_ifname(drvr, ifidx), id, bcdc->reqid); | ||
197 | ret = -EINVAL; | ||
198 | goto done; | ||
199 | } | ||
200 | |||
201 | /* Check info buffer */ | ||
202 | info = (void *)&msg[1]; | ||
203 | |||
204 | /* Copy info buffer */ | ||
205 | if (buf) { | ||
206 | if (ret < (int)len) | ||
207 | len = ret; | ||
208 | memcpy(buf, info, len); | ||
209 | } | ||
210 | |||
211 | /* Check the ERROR flag */ | ||
212 | if (flags & BCDC_DCMD_ERROR) | ||
213 | ret = le32_to_cpu(msg->status); | ||
214 | |||
215 | done: | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int | ||
220 | brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
221 | void *buf, uint len) | ||
222 | { | ||
223 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; | ||
224 | struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; | ||
225 | int ret = 0; | ||
226 | u32 flags, id; | ||
227 | |||
228 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); | ||
229 | |||
230 | memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); | ||
231 | |||
232 | msg->cmd = cpu_to_le32(cmd); | ||
233 | msg->len = cpu_to_le32(len); | ||
234 | flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET; | ||
235 | flags = (flags & ~BCDC_DCMD_IF_MASK) | | ||
236 | (ifidx << BCDC_DCMD_IF_SHIFT); | ||
237 | msg->flags = cpu_to_le32(flags); | ||
238 | |||
239 | if (buf) | ||
240 | memcpy(bcdc->buf, buf, len); | ||
241 | |||
242 | ret = brcmf_proto_bcdc_msg(drvr); | ||
243 | if (ret < 0) | ||
244 | goto done; | ||
245 | |||
246 | ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len); | ||
247 | if (ret < 0) | ||
248 | goto done; | ||
249 | |||
250 | flags = le32_to_cpu(msg->flags); | ||
251 | id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT; | ||
252 | |||
253 | if (id != bcdc->reqid) { | ||
254 | brcmf_err("%s: unexpected request id %d (expected %d)\n", | ||
255 | brcmf_ifname(drvr, ifidx), id, bcdc->reqid); | ||
256 | ret = -EINVAL; | ||
257 | goto done; | ||
258 | } | ||
259 | |||
260 | /* Check the ERROR flag */ | ||
261 | if (flags & BCDC_DCMD_ERROR) | ||
262 | ret = le32_to_cpu(msg->status); | ||
263 | |||
264 | done: | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static void | ||
269 | brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
270 | struct sk_buff *pktbuf) | ||
271 | { | ||
272 | struct brcmf_proto_bcdc_header *h; | ||
273 | |||
274 | brcmf_dbg(BCDC, "Enter\n"); | ||
275 | |||
276 | /* Push BDC header used to convey priority for buses that don't */ | ||
277 | skb_push(pktbuf, BCDC_HEADER_LEN); | ||
278 | |||
279 | h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); | ||
280 | |||
281 | h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT); | ||
282 | if (pktbuf->ip_summed == CHECKSUM_PARTIAL) | ||
283 | h->flags |= BCDC_FLAG_SUM_NEEDED; | ||
284 | |||
285 | h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK); | ||
286 | h->flags2 = 0; | ||
287 | h->data_offset = offset; | ||
288 | BCDC_SET_IF_IDX(h, ifidx); | ||
289 | trace_brcmf_bcdchdr(pktbuf->data); | ||
290 | } | ||
291 | |||
292 | static int | ||
293 | brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | ||
294 | struct sk_buff *pktbuf) | ||
295 | { | ||
296 | struct brcmf_proto_bcdc_header *h; | ||
297 | |||
298 | brcmf_dbg(BCDC, "Enter\n"); | ||
299 | |||
300 | /* Pop BCDC header used to convey priority for buses that don't */ | ||
301 | if (pktbuf->len <= BCDC_HEADER_LEN) { | ||
302 | brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", | ||
303 | pktbuf->len, BCDC_HEADER_LEN); | ||
304 | return -EBADE; | ||
305 | } | ||
306 | |||
307 | trace_brcmf_bcdchdr(pktbuf->data); | ||
308 | h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); | ||
309 | |||
310 | *ifidx = BCDC_GET_IF_IDX(h); | ||
311 | if (*ifidx >= BRCMF_MAX_IFS) { | ||
312 | brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); | ||
313 | return -EBADE; | ||
314 | } | ||
315 | /* The ifidx is the idx to map to matching netdev/ifp. When receiving | ||
316 | * events this is easy because it contains the bssidx which maps | ||
317 | * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. | ||
318 | * bssidx 1 is used for p2p0 and no data can be received or | ||
319 | * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 | ||
320 | */ | ||
321 | if (*ifidx) | ||
322 | (*ifidx)++; | ||
323 | |||
324 | if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != | ||
325 | BCDC_PROTO_VER) { | ||
326 | brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", | ||
327 | brcmf_ifname(drvr, *ifidx), h->flags); | ||
328 | return -EBADE; | ||
329 | } | ||
330 | |||
331 | if (h->flags & BCDC_FLAG_SUM_GOOD) { | ||
332 | brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", | ||
333 | brcmf_ifname(drvr, *ifidx), h->flags); | ||
334 | pktbuf->ip_summed = CHECKSUM_UNNECESSARY; | ||
335 | } | ||
336 | |||
337 | pktbuf->priority = h->priority & BCDC_PRIORITY_MASK; | ||
338 | |||
339 | skb_pull(pktbuf, BCDC_HEADER_LEN); | ||
340 | if (do_fws) | ||
341 | brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); | ||
342 | else | ||
343 | skb_pull(pktbuf, h->data_offset << 2); | ||
344 | |||
345 | if (pktbuf->len == 0) | ||
346 | return -ENODATA; | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) | ||
351 | { | ||
352 | struct brcmf_bcdc *bcdc; | ||
353 | |||
354 | bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC); | ||
355 | if (!bcdc) | ||
356 | goto fail; | ||
357 | |||
358 | /* ensure that the msg buf directly follows the cdc msg struct */ | ||
359 | if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) { | ||
360 | brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n"); | ||
361 | goto fail; | ||
362 | } | ||
363 | |||
364 | drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush; | ||
365 | drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull; | ||
366 | drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd; | ||
367 | drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd; | ||
368 | drvr->proto->pd = bcdc; | ||
369 | |||
370 | drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; | ||
371 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + | ||
372 | sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN; | ||
373 | return 0; | ||
374 | |||
375 | fail: | ||
376 | kfree(bcdc); | ||
377 | return -ENOMEM; | ||
378 | } | ||
379 | |||
380 | void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) | ||
381 | { | ||
382 | kfree(drvr->proto->pd); | ||
383 | drvr->proto->pd = NULL; | ||
384 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h new file mode 100644 index 000000000000..17e8c039ff32 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef BRCMFMAC_BCDC_H | ||
17 | #define BRCMFMAC_BCDC_H | ||
18 | |||
19 | |||
20 | int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); | ||
21 | void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); | ||
22 | |||
23 | |||
24 | #endif /* BRCMFMAC_BCDC_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 3e10b801eee8..91651ec7f13f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/export.h> | ||
21 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
22 | #include <linux/pci_ids.h> | 21 | #include <linux/pci_ids.h> |
23 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
@@ -774,7 +773,6 @@ out: | |||
774 | 773 | ||
775 | return ret; | 774 | return ret; |
776 | } | 775 | } |
777 | EXPORT_SYMBOL(brcmf_sdio_probe); | ||
778 | 776 | ||
779 | int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) | 777 | int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) |
780 | { | 778 | { |
@@ -791,7 +789,6 @@ int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) | |||
791 | 789 | ||
792 | return 0; | 790 | return 0; |
793 | } | 791 | } |
794 | EXPORT_SYMBOL(brcmf_sdio_remove); | ||
795 | 792 | ||
796 | void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) | 793 | void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) |
797 | { | 794 | { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index abc9ceca70f3..a511c27122b8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -158,10 +158,21 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | |||
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | if (err_ret) | 161 | if (err_ret) { |
162 | brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | 162 | /* |
163 | rw ? "write" : "read", func, regaddr, *byte, err_ret); | 163 | * SleepCSR register access can fail when |
164 | 164 | * waking up the device so reduce this noise | |
165 | * in the logs. | ||
166 | */ | ||
167 | if (regaddr != SBSDIO_FUNC1_SLEEPCSR) | ||
168 | brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
169 | rw ? "write" : "read", func, regaddr, *byte, | ||
170 | err_ret); | ||
171 | else | ||
172 | brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
173 | rw ? "write" : "read", func, regaddr, *byte, | ||
174 | err_ret); | ||
175 | } | ||
165 | return err_ret; | 176 | return err_ret; |
166 | } | 177 | } |
167 | 178 | ||
@@ -269,6 +280,9 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | |||
269 | int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | 280 | int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) |
270 | { | 281 | { |
271 | int err_ret = 0; | 282 | int err_ret = 0; |
283 | struct mmc_host *host; | ||
284 | struct sdio_func *func; | ||
285 | uint max_blocks; | ||
272 | 286 | ||
273 | brcmf_dbg(SDIO, "\n"); | 287 | brcmf_dbg(SDIO, "\n"); |
274 | 288 | ||
@@ -290,6 +304,20 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | |||
290 | 304 | ||
291 | brcmf_sdioh_enablefuncs(sdiodev); | 305 | brcmf_sdioh_enablefuncs(sdiodev); |
292 | 306 | ||
307 | /* | ||
308 | * determine host related variables after brcmf_sdio_probe() | ||
309 | * as func->cur_blksize is properly set and F2 init has been | ||
310 | * completed successfully. | ||
311 | */ | ||
312 | func = sdiodev->func[2]; | ||
313 | host = func->card->host; | ||
314 | sdiodev->sg_support = host->max_segs > 1; | ||
315 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
316 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
317 | max_blocks * func->cur_blksize); | ||
318 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
319 | SG_MAX_SINGLE_ALLOC); | ||
320 | sdiodev->max_segment_size = host->max_seg_size; | ||
293 | out: | 321 | out: |
294 | sdio_release_host(sdiodev->func[1]); | 322 | sdio_release_host(sdiodev->func[1]); |
295 | brcmf_dbg(SDIO, "Done\n"); | 323 | brcmf_dbg(SDIO, "Done\n"); |
@@ -318,8 +346,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
318 | int err; | 346 | int err; |
319 | struct brcmf_sdio_dev *sdiodev; | 347 | struct brcmf_sdio_dev *sdiodev; |
320 | struct brcmf_bus *bus_if; | 348 | struct brcmf_bus *bus_if; |
321 | struct mmc_host *host; | ||
322 | uint max_blocks; | ||
323 | 349 | ||
324 | brcmf_dbg(SDIO, "Enter\n"); | 350 | brcmf_dbg(SDIO, "Enter\n"); |
325 | brcmf_dbg(SDIO, "Class=%x\n", func->class); | 351 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
@@ -367,19 +393,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
367 | goto fail; | 393 | goto fail; |
368 | } | 394 | } |
369 | 395 | ||
370 | /* | ||
371 | * determine host related variables after brcmf_sdio_probe() | ||
372 | * as func->cur_blksize is properly set and F2 init has been | ||
373 | * completed successfully. | ||
374 | */ | ||
375 | host = func->card->host; | ||
376 | sdiodev->sg_support = host->max_segs > 1; | ||
377 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
378 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
379 | max_blocks * func->cur_blksize); | ||
380 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
381 | SG_MAX_SINGLE_ALLOC); | ||
382 | sdiodev->max_segment_size = host->max_seg_size; | ||
383 | brcmf_dbg(SDIO, "F2 init completed...\n"); | 396 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
384 | return 0; | 397 | return 0; |
385 | 398 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 899a2ada5b82..252024bcbc3b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -25,184 +25,14 @@ | |||
25 | 25 | ||
26 | #include "fweh.h" | 26 | #include "fweh.h" |
27 | 27 | ||
28 | /******************************************************************************* | ||
29 | * IO codes that are interpreted by dongle firmware | ||
30 | ******************************************************************************/ | ||
31 | #define BRCMF_C_GET_VERSION 1 | ||
32 | #define BRCMF_C_UP 2 | ||
33 | #define BRCMF_C_DOWN 3 | ||
34 | #define BRCMF_C_SET_PROMISC 10 | ||
35 | #define BRCMF_C_GET_RATE 12 | ||
36 | #define BRCMF_C_GET_INFRA 19 | ||
37 | #define BRCMF_C_SET_INFRA 20 | ||
38 | #define BRCMF_C_GET_AUTH 21 | ||
39 | #define BRCMF_C_SET_AUTH 22 | ||
40 | #define BRCMF_C_GET_BSSID 23 | ||
41 | #define BRCMF_C_GET_SSID 25 | ||
42 | #define BRCMF_C_SET_SSID 26 | ||
43 | #define BRCMF_C_TERMINATED 28 | ||
44 | #define BRCMF_C_GET_CHANNEL 29 | ||
45 | #define BRCMF_C_SET_CHANNEL 30 | ||
46 | #define BRCMF_C_GET_SRL 31 | ||
47 | #define BRCMF_C_SET_SRL 32 | ||
48 | #define BRCMF_C_GET_LRL 33 | ||
49 | #define BRCMF_C_SET_LRL 34 | ||
50 | #define BRCMF_C_GET_RADIO 37 | ||
51 | #define BRCMF_C_SET_RADIO 38 | ||
52 | #define BRCMF_C_GET_PHYTYPE 39 | ||
53 | #define BRCMF_C_SET_KEY 45 | ||
54 | #define BRCMF_C_SET_PASSIVE_SCAN 49 | ||
55 | #define BRCMF_C_SCAN 50 | ||
56 | #define BRCMF_C_SCAN_RESULTS 51 | ||
57 | #define BRCMF_C_DISASSOC 52 | ||
58 | #define BRCMF_C_REASSOC 53 | ||
59 | #define BRCMF_C_SET_ROAM_TRIGGER 55 | ||
60 | #define BRCMF_C_SET_ROAM_DELTA 57 | ||
61 | #define BRCMF_C_GET_BCNPRD 75 | ||
62 | #define BRCMF_C_SET_BCNPRD 76 | ||
63 | #define BRCMF_C_GET_DTIMPRD 77 | ||
64 | #define BRCMF_C_SET_DTIMPRD 78 | ||
65 | #define BRCMF_C_SET_COUNTRY 84 | ||
66 | #define BRCMF_C_GET_PM 85 | ||
67 | #define BRCMF_C_SET_PM 86 | ||
68 | #define BRCMF_C_GET_CURR_RATESET 114 | ||
69 | #define BRCMF_C_GET_AP 117 | ||
70 | #define BRCMF_C_SET_AP 118 | ||
71 | #define BRCMF_C_GET_RSSI 127 | ||
72 | #define BRCMF_C_GET_WSEC 133 | ||
73 | #define BRCMF_C_SET_WSEC 134 | ||
74 | #define BRCMF_C_GET_PHY_NOISE 135 | ||
75 | #define BRCMF_C_GET_BSS_INFO 136 | ||
76 | #define BRCMF_C_GET_BANDLIST 140 | ||
77 | #define BRCMF_C_SET_SCB_TIMEOUT 158 | ||
78 | #define BRCMF_C_GET_PHYLIST 180 | ||
79 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 | ||
80 | #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 | ||
81 | #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 | ||
82 | #define BRCMF_C_GET_VALID_CHANNELS 217 | ||
83 | #define BRCMF_C_GET_KEY_PRIMARY 235 | ||
84 | #define BRCMF_C_SET_KEY_PRIMARY 236 | ||
85 | #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 | ||
86 | #define BRCMF_C_GET_VAR 262 | ||
87 | #define BRCMF_C_SET_VAR 263 | ||
88 | |||
89 | /* phy types (returned by WLC_GET_PHYTPE) */ | ||
90 | #define WLC_PHY_TYPE_A 0 | ||
91 | #define WLC_PHY_TYPE_B 1 | ||
92 | #define WLC_PHY_TYPE_G 2 | ||
93 | #define WLC_PHY_TYPE_N 4 | ||
94 | #define WLC_PHY_TYPE_LP 5 | ||
95 | #define WLC_PHY_TYPE_SSN 6 | ||
96 | #define WLC_PHY_TYPE_HT 7 | ||
97 | #define WLC_PHY_TYPE_LCN 8 | ||
98 | #define WLC_PHY_TYPE_NULL 0xf | ||
99 | |||
100 | #define TOE_TX_CSUM_OL 0x00000001 | 28 | #define TOE_TX_CSUM_OL 0x00000001 |
101 | #define TOE_RX_CSUM_OL 0x00000002 | 29 | #define TOE_RX_CSUM_OL 0x00000002 |
102 | 30 | ||
103 | #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ | ||
104 | |||
105 | /* size of brcmf_scan_params not including variable length array */ | ||
106 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 | ||
107 | |||
108 | /* masks for channel and ssid count */ | ||
109 | #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff | ||
110 | #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 | ||
111 | |||
112 | /* primary (ie tx) key */ | ||
113 | #define BRCMF_PRIMARY_KEY (1 << 1) | ||
114 | |||
115 | /* For supporting multiple interfaces */ | 31 | /* For supporting multiple interfaces */ |
116 | #define BRCMF_MAX_IFS 16 | 32 | #define BRCMF_MAX_IFS 16 |
117 | 33 | ||
118 | #define DOT11_BSSTYPE_ANY 2 | ||
119 | #define DOT11_MAX_DEFAULT_KEYS 4 | 34 | #define DOT11_MAX_DEFAULT_KEYS 4 |
120 | 35 | ||
121 | #define BRCMF_ESCAN_REQ_VERSION 1 | ||
122 | |||
123 | #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 | ||
124 | |||
125 | #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ | ||
126 | #define BRCMF_STA_ASSOC 0x10 /* Associated */ | ||
127 | |||
128 | #define BRCMF_E_STATUS_SUCCESS 0 | ||
129 | #define BRCMF_E_STATUS_FAIL 1 | ||
130 | #define BRCMF_E_STATUS_TIMEOUT 2 | ||
131 | #define BRCMF_E_STATUS_NO_NETWORKS 3 | ||
132 | #define BRCMF_E_STATUS_ABORT 4 | ||
133 | #define BRCMF_E_STATUS_NO_ACK 5 | ||
134 | #define BRCMF_E_STATUS_UNSOLICITED 6 | ||
135 | #define BRCMF_E_STATUS_ATTEMPT 7 | ||
136 | #define BRCMF_E_STATUS_PARTIAL 8 | ||
137 | #define BRCMF_E_STATUS_NEWSCAN 9 | ||
138 | #define BRCMF_E_STATUS_NEWASSOC 10 | ||
139 | #define BRCMF_E_STATUS_11HQUIET 11 | ||
140 | #define BRCMF_E_STATUS_SUPPRESS 12 | ||
141 | #define BRCMF_E_STATUS_NOCHANS 13 | ||
142 | #define BRCMF_E_STATUS_CS_ABORT 15 | ||
143 | #define BRCMF_E_STATUS_ERROR 16 | ||
144 | |||
145 | #define BRCMF_E_REASON_INITIAL_ASSOC 0 | ||
146 | #define BRCMF_E_REASON_LOW_RSSI 1 | ||
147 | #define BRCMF_E_REASON_DEAUTH 2 | ||
148 | #define BRCMF_E_REASON_DISASSOC 3 | ||
149 | #define BRCMF_E_REASON_BCNS_LOST 4 | ||
150 | #define BRCMF_E_REASON_MINTXRATE 9 | ||
151 | #define BRCMF_E_REASON_TXFAIL 10 | ||
152 | |||
153 | #define BRCMF_E_REASON_LINK_BSSCFG_DIS 4 | ||
154 | #define BRCMF_E_REASON_FAST_ROAM_FAILED 5 | ||
155 | #define BRCMF_E_REASON_DIRECTED_ROAM 6 | ||
156 | #define BRCMF_E_REASON_TSPEC_REJECTED 7 | ||
157 | #define BRCMF_E_REASON_BETTER_AP 8 | ||
158 | |||
159 | #define BRCMF_E_PRUNE_ENCR_MISMATCH 1 | ||
160 | #define BRCMF_E_PRUNE_BCAST_BSSID 2 | ||
161 | #define BRCMF_E_PRUNE_MAC_DENY 3 | ||
162 | #define BRCMF_E_PRUNE_MAC_NA 4 | ||
163 | #define BRCMF_E_PRUNE_REG_PASSV 5 | ||
164 | #define BRCMF_E_PRUNE_SPCT_MGMT 6 | ||
165 | #define BRCMF_E_PRUNE_RADAR 7 | ||
166 | #define BRCMF_E_RSN_MISMATCH 8 | ||
167 | #define BRCMF_E_PRUNE_NO_COMMON_RATES 9 | ||
168 | #define BRCMF_E_PRUNE_BASIC_RATES 10 | ||
169 | #define BRCMF_E_PRUNE_CIPHER_NA 12 | ||
170 | #define BRCMF_E_PRUNE_KNOWN_STA 13 | ||
171 | #define BRCMF_E_PRUNE_WDS_PEER 15 | ||
172 | #define BRCMF_E_PRUNE_QBSS_LOAD 16 | ||
173 | #define BRCMF_E_PRUNE_HOME_AP 17 | ||
174 | |||
175 | #define BRCMF_E_SUP_OTHER 0 | ||
176 | #define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 | ||
177 | #define BRCMF_E_SUP_BAD_UCAST_WEP128 2 | ||
178 | #define BRCMF_E_SUP_BAD_UCAST_WEP40 3 | ||
179 | #define BRCMF_E_SUP_UNSUP_KEY_LEN 4 | ||
180 | #define BRCMF_E_SUP_PW_KEY_CIPHER 5 | ||
181 | #define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 | ||
182 | #define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 | ||
183 | #define BRCMF_E_SUP_NO_INSTALL_FLAG 8 | ||
184 | #define BRCMF_E_SUP_MSG3_NO_GTK 9 | ||
185 | #define BRCMF_E_SUP_GRP_KEY_CIPHER 10 | ||
186 | #define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 | ||
187 | #define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 | ||
188 | #define BRCMF_E_SUP_SEND_FAIL 13 | ||
189 | #define BRCMF_E_SUP_DEAUTH 14 | ||
190 | |||
191 | #define BRCMF_E_IF_ADD 1 | ||
192 | #define BRCMF_E_IF_DEL 2 | ||
193 | #define BRCMF_E_IF_CHANGE 3 | ||
194 | |||
195 | #define BRCMF_E_IF_FLAG_NOIF 1 | ||
196 | |||
197 | #define BRCMF_E_IF_ROLE_STA 0 | ||
198 | #define BRCMF_E_IF_ROLE_AP 1 | ||
199 | #define BRCMF_E_IF_ROLE_WDS 2 | ||
200 | |||
201 | #define BRCMF_E_LINK_BCN_LOSS 1 | ||
202 | #define BRCMF_E_LINK_DISASSOC 2 | ||
203 | #define BRCMF_E_LINK_ASSOC_REC 3 | ||
204 | #define BRCMF_E_LINK_BSSCFG_DIS 4 | ||
205 | |||
206 | /* Small, medium and maximum buffer size for dcmd | 36 | /* Small, medium and maximum buffer size for dcmd |
207 | */ | 37 | */ |
208 | #define BRCMF_DCMD_SMLEN 256 | 38 | #define BRCMF_DCMD_SMLEN 256 |
@@ -211,291 +41,10 @@ | |||
211 | 41 | ||
212 | #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256 | 42 | #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS 256 |
213 | 43 | ||
214 | /* Pattern matching filter. Specifies an offset within received packets to | 44 | /* Length of firmware version string stored for |
215 | * start matching, the pattern to match, the size of the pattern, and a bitmask | 45 | * ethtool driver info which uses 32 bytes as well. |
216 | * that indicates which bits within the pattern should be matched. | ||
217 | */ | ||
218 | struct brcmf_pkt_filter_pattern_le { | ||
219 | /* | ||
220 | * Offset within received packet to start pattern matching. | ||
221 | * Offset '0' is the first byte of the ethernet header. | ||
222 | */ | ||
223 | __le32 offset; | ||
224 | /* Size of the pattern. Bitmask must be the same size.*/ | ||
225 | __le32 size_bytes; | ||
226 | /* | ||
227 | * Variable length mask and pattern data. mask starts at offset 0. | ||
228 | * Pattern immediately follows mask. | ||
229 | */ | ||
230 | u8 mask_and_pattern[1]; | ||
231 | }; | ||
232 | |||
233 | /* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ | ||
234 | struct brcmf_pkt_filter_le { | ||
235 | __le32 id; /* Unique filter id, specified by app. */ | ||
236 | __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ | ||
237 | __le32 negate_match; /* Negate the result of filter matches */ | ||
238 | union { /* Filter definitions */ | ||
239 | struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ | ||
240 | } u; | ||
241 | }; | ||
242 | |||
243 | /* IOVAR "pkt_filter_enable" parameter. */ | ||
244 | struct brcmf_pkt_filter_enable_le { | ||
245 | __le32 id; /* Unique filter id */ | ||
246 | __le32 enable; /* Enable/disable bool */ | ||
247 | }; | ||
248 | |||
249 | /* BSS info structure | ||
250 | * Applications MUST CHECK ie_offset field and length field to access IEs and | ||
251 | * next bss_info structure in a vector (in struct brcmf_scan_results) | ||
252 | */ | ||
253 | struct brcmf_bss_info_le { | ||
254 | __le32 version; /* version field */ | ||
255 | __le32 length; /* byte length of data in this record, | ||
256 | * starting at version and including IEs | ||
257 | */ | ||
258 | u8 BSSID[ETH_ALEN]; | ||
259 | __le16 beacon_period; /* units are Kusec */ | ||
260 | __le16 capability; /* Capability information */ | ||
261 | u8 SSID_len; | ||
262 | u8 SSID[32]; | ||
263 | struct { | ||
264 | __le32 count; /* # rates in this set */ | ||
265 | u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ | ||
266 | } rateset; /* supported rates */ | ||
267 | __le16 chanspec; /* chanspec for bss */ | ||
268 | __le16 atim_window; /* units are Kusec */ | ||
269 | u8 dtim_period; /* DTIM period */ | ||
270 | __le16 RSSI; /* receive signal strength (in dBm) */ | ||
271 | s8 phy_noise; /* noise (in dBm) */ | ||
272 | |||
273 | u8 n_cap; /* BSS is 802.11N Capable */ | ||
274 | /* 802.11N BSS Capabilities (based on HT_CAP_*): */ | ||
275 | __le32 nbss_cap; | ||
276 | u8 ctl_ch; /* 802.11N BSS control channel number */ | ||
277 | __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ | ||
278 | u8 flags; /* flags */ | ||
279 | u8 reserved[3]; /* Reserved for expansion of BSS properties */ | ||
280 | u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ | ||
281 | |||
282 | __le16 ie_offset; /* offset at which IEs start, from beginning */ | ||
283 | __le32 ie_length; /* byte length of Information Elements */ | ||
284 | __le16 SNR; /* average SNR of during frame reception */ | ||
285 | /* Add new fields here */ | ||
286 | /* variable length Information Elements */ | ||
287 | }; | ||
288 | |||
289 | struct brcm_rateset_le { | ||
290 | /* # rates in this set */ | ||
291 | __le32 count; | ||
292 | /* rates in 500kbps units w/hi bit set if basic */ | ||
293 | u8 rates[BRCMF_MAXRATES_IN_SET]; | ||
294 | }; | ||
295 | |||
296 | struct brcmf_ssid { | ||
297 | u32 SSID_len; | ||
298 | unsigned char SSID[32]; | ||
299 | }; | ||
300 | |||
301 | struct brcmf_ssid_le { | ||
302 | __le32 SSID_len; | ||
303 | unsigned char SSID[32]; | ||
304 | }; | ||
305 | |||
306 | struct brcmf_scan_params_le { | ||
307 | struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ | ||
308 | u8 bssid[ETH_ALEN]; /* default: bcast */ | ||
309 | s8 bss_type; /* default: any, | ||
310 | * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT | ||
311 | */ | ||
312 | u8 scan_type; /* flags, 0 use default */ | ||
313 | __le32 nprobes; /* -1 use default, number of probes per channel */ | ||
314 | __le32 active_time; /* -1 use default, dwell time per channel for | ||
315 | * active scanning | ||
316 | */ | ||
317 | __le32 passive_time; /* -1 use default, dwell time per channel | ||
318 | * for passive scanning | ||
319 | */ | ||
320 | __le32 home_time; /* -1 use default, dwell time for the | ||
321 | * home channel between channel scans | ||
322 | */ | ||
323 | __le32 channel_num; /* count of channels and ssids that follow | ||
324 | * | ||
325 | * low half is count of channels in | ||
326 | * channel_list, 0 means default (use all | ||
327 | * available channels) | ||
328 | * | ||
329 | * high half is entries in struct brcmf_ssid | ||
330 | * array that follows channel_list, aligned for | ||
331 | * s32 (4 bytes) meaning an odd channel count | ||
332 | * implies a 2-byte pad between end of | ||
333 | * channel_list and first ssid | ||
334 | * | ||
335 | * if ssid count is zero, single ssid in the | ||
336 | * fixed parameter portion is assumed, otherwise | ||
337 | * ssid in the fixed portion is ignored | ||
338 | */ | ||
339 | __le16 channel_list[1]; /* list of chanspecs */ | ||
340 | }; | ||
341 | |||
342 | struct brcmf_scan_results { | ||
343 | u32 buflen; | ||
344 | u32 version; | ||
345 | u32 count; | ||
346 | struct brcmf_bss_info_le bss_info_le[]; | ||
347 | }; | ||
348 | |||
349 | struct brcmf_escan_params_le { | ||
350 | __le32 version; | ||
351 | __le16 action; | ||
352 | __le16 sync_id; | ||
353 | struct brcmf_scan_params_le params_le; | ||
354 | }; | ||
355 | |||
356 | struct brcmf_escan_result_le { | ||
357 | __le32 buflen; | ||
358 | __le32 version; | ||
359 | __le16 sync_id; | ||
360 | __le16 bss_count; | ||
361 | struct brcmf_bss_info_le bss_info_le; | ||
362 | }; | ||
363 | |||
364 | #define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \ | ||
365 | sizeof(struct brcmf_bss_info_le)) | ||
366 | |||
367 | /* used for association with a specific BSSID and chanspec list */ | ||
368 | struct brcmf_assoc_params_le { | ||
369 | /* 00:00:00:00:00:00: broadcast scan */ | ||
370 | u8 bssid[ETH_ALEN]; | ||
371 | /* 0: all available channels, otherwise count of chanspecs in | ||
372 | * chanspec_list */ | ||
373 | __le32 chanspec_num; | ||
374 | /* list of chanspecs */ | ||
375 | __le16 chanspec_list[1]; | ||
376 | }; | ||
377 | |||
378 | /* used for join with or without a specific bssid and channel list */ | ||
379 | struct brcmf_join_params { | ||
380 | struct brcmf_ssid_le ssid_le; | ||
381 | struct brcmf_assoc_params_le params_le; | ||
382 | }; | ||
383 | |||
384 | /* scan params for extended join */ | ||
385 | struct brcmf_join_scan_params_le { | ||
386 | u8 scan_type; /* 0 use default, active or passive scan */ | ||
387 | __le32 nprobes; /* -1 use default, nr of probes per channel */ | ||
388 | __le32 active_time; /* -1 use default, dwell time per channel for | ||
389 | * active scanning | ||
390 | */ | ||
391 | __le32 passive_time; /* -1 use default, dwell time per channel | ||
392 | * for passive scanning | ||
393 | */ | ||
394 | __le32 home_time; /* -1 use default, dwell time for the home | ||
395 | * channel between channel scans | ||
396 | */ | ||
397 | }; | ||
398 | |||
399 | /* extended join params */ | ||
400 | struct brcmf_ext_join_params_le { | ||
401 | struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */ | ||
402 | struct brcmf_join_scan_params_le scan_le; | ||
403 | struct brcmf_assoc_params_le assoc_le; | ||
404 | }; | ||
405 | |||
406 | struct brcmf_wsec_key { | ||
407 | u32 index; /* key index */ | ||
408 | u32 len; /* key length */ | ||
409 | u8 data[WLAN_MAX_KEY_LEN]; /* key data */ | ||
410 | u32 pad_1[18]; | ||
411 | u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ | ||
412 | u32 flags; /* misc flags */ | ||
413 | u32 pad_2[3]; | ||
414 | u32 iv_initialized; /* has IV been initialized already? */ | ||
415 | u32 pad_3; | ||
416 | /* Rx IV */ | ||
417 | struct { | ||
418 | u32 hi; /* upper 32 bits of IV */ | ||
419 | u16 lo; /* lower 16 bits of IV */ | ||
420 | } rxiv; | ||
421 | u32 pad_4[2]; | ||
422 | u8 ea[ETH_ALEN]; /* per station */ | ||
423 | }; | ||
424 | |||
425 | /* | ||
426 | * dongle requires same struct as above but with fields in little endian order | ||
427 | */ | 46 | */ |
428 | struct brcmf_wsec_key_le { | 47 | #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32 |
429 | __le32 index; /* key index */ | ||
430 | __le32 len; /* key length */ | ||
431 | u8 data[WLAN_MAX_KEY_LEN]; /* key data */ | ||
432 | __le32 pad_1[18]; | ||
433 | __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ | ||
434 | __le32 flags; /* misc flags */ | ||
435 | __le32 pad_2[3]; | ||
436 | __le32 iv_initialized; /* has IV been initialized already? */ | ||
437 | __le32 pad_3; | ||
438 | /* Rx IV */ | ||
439 | struct { | ||
440 | __le32 hi; /* upper 32 bits of IV */ | ||
441 | __le16 lo; /* lower 16 bits of IV */ | ||
442 | } rxiv; | ||
443 | __le32 pad_4[2]; | ||
444 | u8 ea[ETH_ALEN]; /* per station */ | ||
445 | }; | ||
446 | |||
447 | /* Used to get specific STA parameters */ | ||
448 | struct brcmf_scb_val_le { | ||
449 | __le32 val; | ||
450 | u8 ea[ETH_ALEN]; | ||
451 | }; | ||
452 | |||
453 | /* channel encoding */ | ||
454 | struct brcmf_channel_info_le { | ||
455 | __le32 hw_channel; | ||
456 | __le32 target_channel; | ||
457 | __le32 scan_channel; | ||
458 | }; | ||
459 | |||
460 | struct brcmf_sta_info_le { | ||
461 | __le16 ver; /* version of this struct */ | ||
462 | __le16 len; /* length in bytes of this structure */ | ||
463 | __le16 cap; /* sta's advertised capabilities */ | ||
464 | __le32 flags; /* flags defined below */ | ||
465 | __le32 idle; /* time since data pkt rx'd from sta */ | ||
466 | u8 ea[ETH_ALEN]; /* Station address */ | ||
467 | __le32 count; /* # rates in this set */ | ||
468 | u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ | ||
469 | /* w/hi bit set if basic */ | ||
470 | __le32 in; /* seconds elapsed since associated */ | ||
471 | __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ | ||
472 | __le32 tx_pkts; /* # of packets transmitted */ | ||
473 | __le32 tx_failures; /* # of packets failed */ | ||
474 | __le32 rx_ucast_pkts; /* # of unicast packets received */ | ||
475 | __le32 rx_mcast_pkts; /* # of multicast packets received */ | ||
476 | __le32 tx_rate; /* Rate of last successful tx frame */ | ||
477 | __le32 rx_rate; /* Rate of last successful rx frame */ | ||
478 | __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ | ||
479 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ | ||
480 | }; | ||
481 | |||
482 | struct brcmf_chanspec_list { | ||
483 | __le32 count; /* # of entries */ | ||
484 | __le32 element[1]; /* variable length uint32 list */ | ||
485 | }; | ||
486 | |||
487 | /* | ||
488 | * WLC_E_PROBRESP_MSG | ||
489 | * WLC_E_P2P_PROBREQ_MSG | ||
490 | * WLC_E_ACTION_FRAME_RX | ||
491 | */ | ||
492 | struct brcmf_rx_mgmt_data { | ||
493 | __be16 version; | ||
494 | __be16 chanspec; | ||
495 | __be32 rssi; | ||
496 | __be32 mactime; | ||
497 | __be32 rate; | ||
498 | }; | ||
499 | 48 | ||
500 | /* Bus independent dongle command */ | 49 | /* Bus independent dongle command */ |
501 | struct brcmf_dcmd { | 50 | struct brcmf_dcmd { |
@@ -535,7 +84,7 @@ struct brcmf_fws_info; /* firmware signalling info */ | |||
535 | struct brcmf_pub { | 84 | struct brcmf_pub { |
536 | /* Linkage ponters */ | 85 | /* Linkage ponters */ |
537 | struct brcmf_bus *bus_if; | 86 | struct brcmf_bus *bus_if; |
538 | struct brcmf_proto *prot; | 87 | struct brcmf_proto *proto; |
539 | struct brcmf_cfg80211_info *config; | 88 | struct brcmf_cfg80211_info *config; |
540 | 89 | ||
541 | /* Internal brcmf items */ | 90 | /* Internal brcmf items */ |
@@ -544,7 +93,7 @@ struct brcmf_pub { | |||
544 | u8 wme_dp; /* wme discard priority */ | 93 | u8 wme_dp; /* wme discard priority */ |
545 | 94 | ||
546 | /* Dongle media info */ | 95 | /* Dongle media info */ |
547 | unsigned long drv_version; /* Version of dongle-resident driver */ | 96 | char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; |
548 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ | 97 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ |
549 | 98 | ||
550 | /* Multicast data packets sent to dongle */ | 99 | /* Multicast data packets sent to dongle */ |
@@ -566,14 +115,6 @@ struct brcmf_pub { | |||
566 | #endif | 115 | #endif |
567 | }; | 116 | }; |
568 | 117 | ||
569 | struct brcmf_if_event { | ||
570 | u8 ifidx; | ||
571 | u8 action; | ||
572 | u8 flags; | ||
573 | u8 bssidx; | ||
574 | u8 role; | ||
575 | }; | ||
576 | |||
577 | /* forward declarations */ | 118 | /* forward declarations */ |
578 | struct brcmf_cfg80211_vif; | 119 | struct brcmf_cfg80211_vif; |
579 | struct brcmf_fws_mac_descriptor; | 120 | struct brcmf_fws_mac_descriptor; |
@@ -635,16 +176,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev); | |||
635 | /* Return pointer to interface name */ | 176 | /* Return pointer to interface name */ |
636 | char *brcmf_ifname(struct brcmf_pub *drvr, int idx); | 177 | char *brcmf_ifname(struct brcmf_pub *drvr, int idx); |
637 | 178 | ||
638 | /* Query dongle */ | ||
639 | int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
640 | void *buf, uint len); | ||
641 | int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
642 | void *buf, uint len); | ||
643 | |||
644 | /* Remove any protocol-specific data header. */ | ||
645 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | ||
646 | struct sk_buff *rxp); | ||
647 | |||
648 | int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | 179 | int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); |
649 | struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | 180 | struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, |
650 | char *name, u8 *mac_addr); | 181 | char *name, u8 *mac_addr); |
@@ -655,4 +186,7 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp); | |||
655 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 186 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, |
656 | bool success); | 187 | bool success); |
657 | 188 | ||
189 | /* Sets dongle media info (drv_version, mac address). */ | ||
190 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | ||
191 | |||
658 | #endif /* _BRCMF_H_ */ | 192 | #endif /* _BRCMF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index a6eb09e5d46f..6a54905528be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -34,6 +34,7 @@ struct brcmf_bus_dcmd { | |||
34 | /** | 34 | /** |
35 | * struct brcmf_bus_ops - bus callback operations. | 35 | * struct brcmf_bus_ops - bus callback operations. |
36 | * | 36 | * |
37 | * @preinit: execute bus/device specific dongle init commands (optional). | ||
37 | * @init: prepare for communication with dongle. | 38 | * @init: prepare for communication with dongle. |
38 | * @stop: clear pending frames, disable data flow. | 39 | * @stop: clear pending frames, disable data flow. |
39 | * @txdata: send a data frame to the dongle. When the data | 40 | * @txdata: send a data frame to the dongle. When the data |
@@ -51,6 +52,7 @@ struct brcmf_bus_dcmd { | |||
51 | * indicated otherwise these callbacks are mandatory. | 52 | * indicated otherwise these callbacks are mandatory. |
52 | */ | 53 | */ |
53 | struct brcmf_bus_ops { | 54 | struct brcmf_bus_ops { |
55 | int (*preinit)(struct device *dev); | ||
54 | int (*init)(struct device *dev); | 56 | int (*init)(struct device *dev); |
55 | void (*stop)(struct device *dev); | 57 | void (*stop)(struct device *dev); |
56 | int (*txdata)(struct device *dev, struct sk_buff *skb); | 58 | int (*txdata)(struct device *dev, struct sk_buff *skb); |
@@ -85,7 +87,6 @@ struct brcmf_bus { | |||
85 | unsigned long tx_realloc; | 87 | unsigned long tx_realloc; |
86 | u32 chip; | 88 | u32 chip; |
87 | u32 chiprev; | 89 | u32 chiprev; |
88 | struct list_head dcmd_list; | ||
89 | 90 | ||
90 | struct brcmf_bus_ops *ops; | 91 | struct brcmf_bus_ops *ops; |
91 | }; | 92 | }; |
@@ -93,6 +94,13 @@ struct brcmf_bus { | |||
93 | /* | 94 | /* |
94 | * callback wrappers | 95 | * callback wrappers |
95 | */ | 96 | */ |
97 | static inline int brcmf_bus_preinit(struct brcmf_bus *bus) | ||
98 | { | ||
99 | if (!bus->ops->preinit) | ||
100 | return 0; | ||
101 | return bus->ops->preinit(bus->dev); | ||
102 | } | ||
103 | |||
96 | static inline int brcmf_bus_init(struct brcmf_bus *bus) | 104 | static inline int brcmf_bus_init(struct brcmf_bus *bus) |
97 | { | 105 | { |
98 | return bus->ops->init(bus->dev); | 106 | return bus->ops->init(bus->dev); |
@@ -139,7 +147,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, | |||
139 | void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); | 147 | void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); |
140 | 148 | ||
141 | /* Indication from bus module regarding presence/insertion of dongle. */ | 149 | /* Indication from bus module regarding presence/insertion of dongle. */ |
142 | int brcmf_attach(uint bus_hdrlen, struct device *dev); | 150 | int brcmf_attach(struct device *dev); |
143 | /* Indication from bus module regarding removal/absence of dongle */ | 151 | /* Indication from bus module regarding removal/absence of dongle */ |
144 | void brcmf_detach(struct device *dev); | 152 | void brcmf_detach(struct device *dev); |
145 | /* Indication from bus module that dongle should be reset */ | 153 | /* Indication from bus module that dongle should be reset */ |
@@ -151,6 +159,9 @@ void brcmf_txflowblock(struct device *dev, bool state); | |||
151 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); | 159 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
152 | 160 | ||
153 | int brcmf_bus_start(struct device *dev); | 161 | int brcmf_bus_start(struct device *dev); |
162 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, | ||
163 | u32 len); | ||
164 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); | ||
154 | 165 | ||
155 | #ifdef CONFIG_BRCMFMAC_SDIO | 166 | #ifdef CONFIG_BRCMFMAC_SDIO |
156 | void brcmf_sdio_exit(void); | 167 | void brcmf_sdio_exit(void); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c deleted file mode 100644 index dd85401063cb..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ /dev/null | |||
@@ -1,392 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /******************************************************************************* | ||
18 | * Communicates with the dongle by using dcmd codes. | ||
19 | * For certain dcmd codes, the dongle interprets string data from the host. | ||
20 | ******************************************************************************/ | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | #include <linux/netdevice.h> | ||
24 | |||
25 | #include <brcmu_utils.h> | ||
26 | #include <brcmu_wifi.h> | ||
27 | |||
28 | #include "dhd.h" | ||
29 | #include "dhd_proto.h" | ||
30 | #include "dhd_bus.h" | ||
31 | #include "fwsignal.h" | ||
32 | #include "dhd_dbg.h" | ||
33 | #include "tracepoint.h" | ||
34 | |||
35 | struct brcmf_proto_cdc_dcmd { | ||
36 | __le32 cmd; /* dongle command value */ | ||
37 | __le32 len; /* lower 16: output buflen; | ||
38 | * upper 16: input buflen (excludes header) */ | ||
39 | __le32 flags; /* flag defns given below */ | ||
40 | __le32 status; /* status code returned from the device */ | ||
41 | }; | ||
42 | |||
43 | /* Max valid buffer size that can be sent to the dongle */ | ||
44 | #define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) | ||
45 | |||
46 | /* CDC flag definitions */ | ||
47 | #define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ | ||
48 | #define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ | ||
49 | #define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ | ||
50 | #define CDC_DCMD_IF_SHIFT 12 | ||
51 | #define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ | ||
52 | #define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ | ||
53 | #define CDC_DCMD_ID(flags) \ | ||
54 | (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) | ||
55 | |||
56 | /* | ||
57 | * BDC header - Broadcom specific extension of CDC. | ||
58 | * Used on data packets to convey priority across USB. | ||
59 | */ | ||
60 | #define BDC_HEADER_LEN 4 | ||
61 | #define BDC_PROTO_VER 2 /* Protocol version */ | ||
62 | #define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ | ||
63 | #define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ | ||
64 | #define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ | ||
65 | #define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ | ||
66 | #define BDC_PRIORITY_MASK 0x7 | ||
67 | #define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ | ||
68 | #define BDC_FLAG2_IF_SHIFT 0 | ||
69 | |||
70 | #define BDC_GET_IF_IDX(hdr) \ | ||
71 | ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) | ||
72 | #define BDC_SET_IF_IDX(hdr, idx) \ | ||
73 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ | ||
74 | ((idx) << BDC_FLAG2_IF_SHIFT))) | ||
75 | |||
76 | /** | ||
77 | * struct brcmf_proto_bdc_header - BDC header format | ||
78 | * | ||
79 | * @flags: flags contain protocol and checksum info. | ||
80 | * @priority: 802.1d priority and USB flow control info (bit 4:7). | ||
81 | * @flags2: additional flags containing dongle interface index. | ||
82 | * @data_offset: start of packet data. header is following by firmware signals. | ||
83 | */ | ||
84 | struct brcmf_proto_bdc_header { | ||
85 | u8 flags; | ||
86 | u8 priority; | ||
87 | u8 flags2; | ||
88 | u8 data_offset; | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * maximum length of firmware signal data between | ||
93 | * the BDC header and packet data in the tx path. | ||
94 | */ | ||
95 | #define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 | ||
96 | |||
97 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ | ||
98 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE | ||
99 | * (amount of header tha might be added) | ||
100 | * plus any space that might be needed | ||
101 | * for bus alignment padding. | ||
102 | */ | ||
103 | #define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for | ||
104 | * round off at the end of buffer | ||
105 | * Currently is SDIO | ||
106 | */ | ||
107 | |||
108 | struct brcmf_proto { | ||
109 | u16 reqid; | ||
110 | u8 bus_header[BUS_HEADER_LEN]; | ||
111 | struct brcmf_proto_cdc_dcmd msg; | ||
112 | unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; | ||
113 | }; | ||
114 | |||
115 | static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) | ||
116 | { | ||
117 | struct brcmf_proto *prot = drvr->prot; | ||
118 | int len = le32_to_cpu(prot->msg.len) + | ||
119 | sizeof(struct brcmf_proto_cdc_dcmd); | ||
120 | |||
121 | brcmf_dbg(CDC, "Enter\n"); | ||
122 | |||
123 | /* NOTE : cdc->msg.len holds the desired length of the buffer to be | ||
124 | * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area | ||
125 | * is actually sent to the dongle | ||
126 | */ | ||
127 | if (len > CDC_MAX_MSG_SIZE) | ||
128 | len = CDC_MAX_MSG_SIZE; | ||
129 | |||
130 | /* Send request */ | ||
131 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len); | ||
132 | } | ||
133 | |||
134 | static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | ||
135 | { | ||
136 | int ret; | ||
137 | struct brcmf_proto *prot = drvr->prot; | ||
138 | |||
139 | brcmf_dbg(CDC, "Enter\n"); | ||
140 | len += sizeof(struct brcmf_proto_cdc_dcmd); | ||
141 | do { | ||
142 | ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, | ||
143 | len); | ||
144 | if (ret < 0) | ||
145 | break; | ||
146 | } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | int | ||
152 | brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
153 | void *buf, uint len) | ||
154 | { | ||
155 | struct brcmf_proto *prot = drvr->prot; | ||
156 | struct brcmf_proto_cdc_dcmd *msg = &prot->msg; | ||
157 | void *info; | ||
158 | int ret = 0, retries = 0; | ||
159 | u32 id, flags; | ||
160 | |||
161 | brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); | ||
162 | |||
163 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); | ||
164 | |||
165 | msg->cmd = cpu_to_le32(cmd); | ||
166 | msg->len = cpu_to_le32(len); | ||
167 | flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); | ||
168 | flags = (flags & ~CDC_DCMD_IF_MASK) | | ||
169 | (ifidx << CDC_DCMD_IF_SHIFT); | ||
170 | msg->flags = cpu_to_le32(flags); | ||
171 | |||
172 | if (buf) | ||
173 | memcpy(prot->buf, buf, len); | ||
174 | |||
175 | ret = brcmf_proto_cdc_msg(drvr); | ||
176 | if (ret < 0) { | ||
177 | brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n", | ||
178 | ret); | ||
179 | goto done; | ||
180 | } | ||
181 | |||
182 | retry: | ||
183 | /* wait for interrupt and get first fragment */ | ||
184 | ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); | ||
185 | if (ret < 0) | ||
186 | goto done; | ||
187 | |||
188 | flags = le32_to_cpu(msg->flags); | ||
189 | id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; | ||
190 | |||
191 | if ((id < prot->reqid) && (++retries < RETRIES)) | ||
192 | goto retry; | ||
193 | if (id != prot->reqid) { | ||
194 | brcmf_err("%s: unexpected request id %d (expected %d)\n", | ||
195 | brcmf_ifname(drvr, ifidx), id, prot->reqid); | ||
196 | ret = -EINVAL; | ||
197 | goto done; | ||
198 | } | ||
199 | |||
200 | /* Check info buffer */ | ||
201 | info = (void *)&msg[1]; | ||
202 | |||
203 | /* Copy info buffer */ | ||
204 | if (buf) { | ||
205 | if (ret < (int)len) | ||
206 | len = ret; | ||
207 | memcpy(buf, info, len); | ||
208 | } | ||
209 | |||
210 | /* Check the ERROR flag */ | ||
211 | if (flags & CDC_DCMD_ERROR) | ||
212 | ret = le32_to_cpu(msg->status); | ||
213 | |||
214 | done: | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
219 | void *buf, uint len) | ||
220 | { | ||
221 | struct brcmf_proto *prot = drvr->prot; | ||
222 | struct brcmf_proto_cdc_dcmd *msg = &prot->msg; | ||
223 | int ret = 0; | ||
224 | u32 flags, id; | ||
225 | |||
226 | brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); | ||
227 | |||
228 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); | ||
229 | |||
230 | msg->cmd = cpu_to_le32(cmd); | ||
231 | msg->len = cpu_to_le32(len); | ||
232 | flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; | ||
233 | flags = (flags & ~CDC_DCMD_IF_MASK) | | ||
234 | (ifidx << CDC_DCMD_IF_SHIFT); | ||
235 | msg->flags = cpu_to_le32(flags); | ||
236 | |||
237 | if (buf) | ||
238 | memcpy(prot->buf, buf, len); | ||
239 | |||
240 | ret = brcmf_proto_cdc_msg(drvr); | ||
241 | if (ret < 0) | ||
242 | goto done; | ||
243 | |||
244 | ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); | ||
245 | if (ret < 0) | ||
246 | goto done; | ||
247 | |||
248 | flags = le32_to_cpu(msg->flags); | ||
249 | id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; | ||
250 | |||
251 | if (id != prot->reqid) { | ||
252 | brcmf_err("%s: unexpected request id %d (expected %d)\n", | ||
253 | brcmf_ifname(drvr, ifidx), id, prot->reqid); | ||
254 | ret = -EINVAL; | ||
255 | goto done; | ||
256 | } | ||
257 | |||
258 | /* Check the ERROR flag */ | ||
259 | if (flags & CDC_DCMD_ERROR) | ||
260 | ret = le32_to_cpu(msg->status); | ||
261 | |||
262 | done: | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | static bool pkt_sum_needed(struct sk_buff *skb) | ||
267 | { | ||
268 | return skb->ip_summed == CHECKSUM_PARTIAL; | ||
269 | } | ||
270 | |||
271 | static void pkt_set_sum_good(struct sk_buff *skb, bool x) | ||
272 | { | ||
273 | skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); | ||
274 | } | ||
275 | |||
276 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
277 | struct sk_buff *pktbuf) | ||
278 | { | ||
279 | struct brcmf_proto_bdc_header *h; | ||
280 | |||
281 | brcmf_dbg(CDC, "Enter\n"); | ||
282 | |||
283 | /* Push BDC header used to convey priority for buses that don't */ | ||
284 | skb_push(pktbuf, BDC_HEADER_LEN); | ||
285 | |||
286 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | ||
287 | |||
288 | h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); | ||
289 | if (pkt_sum_needed(pktbuf)) | ||
290 | h->flags |= BDC_FLAG_SUM_NEEDED; | ||
291 | |||
292 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); | ||
293 | h->flags2 = 0; | ||
294 | h->data_offset = offset; | ||
295 | BDC_SET_IF_IDX(h, ifidx); | ||
296 | trace_brcmf_bdchdr(pktbuf->data); | ||
297 | } | ||
298 | |||
299 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | ||
300 | struct sk_buff *pktbuf) | ||
301 | { | ||
302 | struct brcmf_proto_bdc_header *h; | ||
303 | |||
304 | brcmf_dbg(CDC, "Enter\n"); | ||
305 | |||
306 | /* Pop BDC header used to convey priority for buses that don't */ | ||
307 | |||
308 | if (pktbuf->len <= BDC_HEADER_LEN) { | ||
309 | brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", | ||
310 | pktbuf->len, BDC_HEADER_LEN); | ||
311 | return -EBADE; | ||
312 | } | ||
313 | |||
314 | trace_brcmf_bdchdr(pktbuf->data); | ||
315 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | ||
316 | |||
317 | *ifidx = BDC_GET_IF_IDX(h); | ||
318 | if (*ifidx >= BRCMF_MAX_IFS) { | ||
319 | brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); | ||
320 | return -EBADE; | ||
321 | } | ||
322 | /* The ifidx is the idx to map to matching netdev/ifp. When receiving | ||
323 | * events this is easy because it contains the bssidx which maps | ||
324 | * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. | ||
325 | * bssidx 1 is used for p2p0 and no data can be received or | ||
326 | * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 | ||
327 | */ | ||
328 | if (*ifidx) | ||
329 | (*ifidx)++; | ||
330 | |||
331 | if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != | ||
332 | BDC_PROTO_VER) { | ||
333 | brcmf_err("%s: non-BDC packet received, flags 0x%x\n", | ||
334 | brcmf_ifname(drvr, *ifidx), h->flags); | ||
335 | return -EBADE; | ||
336 | } | ||
337 | |||
338 | if (h->flags & BDC_FLAG_SUM_GOOD) { | ||
339 | brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n", | ||
340 | brcmf_ifname(drvr, *ifidx), h->flags); | ||
341 | pkt_set_sum_good(pktbuf, true); | ||
342 | } | ||
343 | |||
344 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; | ||
345 | |||
346 | skb_pull(pktbuf, BDC_HEADER_LEN); | ||
347 | if (do_fws) | ||
348 | brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); | ||
349 | else | ||
350 | skb_pull(pktbuf, h->data_offset << 2); | ||
351 | |||
352 | if (pktbuf->len == 0) | ||
353 | return -ENODATA; | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | int brcmf_proto_attach(struct brcmf_pub *drvr) | ||
358 | { | ||
359 | struct brcmf_proto *cdc; | ||
360 | |||
361 | cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); | ||
362 | if (!cdc) | ||
363 | goto fail; | ||
364 | |||
365 | /* ensure that the msg buf directly follows the cdc msg struct */ | ||
366 | if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { | ||
367 | brcmf_err("struct brcmf_proto is not correctly defined\n"); | ||
368 | goto fail; | ||
369 | } | ||
370 | |||
371 | drvr->prot = cdc; | ||
372 | drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; | ||
373 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + | ||
374 | sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; | ||
375 | return 0; | ||
376 | |||
377 | fail: | ||
378 | kfree(cdc); | ||
379 | return -ENOMEM; | ||
380 | } | ||
381 | |||
382 | /* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ | ||
383 | void brcmf_proto_detach(struct brcmf_pub *drvr) | ||
384 | { | ||
385 | kfree(drvr->prot); | ||
386 | drvr->prot = NULL; | ||
387 | } | ||
388 | |||
389 | void brcmf_proto_stop(struct brcmf_pub *drvr) | ||
390 | { | ||
391 | /* Nothing to do for CDC */ | ||
392 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 9431af2465f3..548dbb5542c6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -21,9 +21,9 @@ | |||
21 | #include <brcmu_utils.h> | 21 | #include <brcmu_utils.h> |
22 | #include "dhd.h" | 22 | #include "dhd.h" |
23 | #include "dhd_bus.h" | 23 | #include "dhd_bus.h" |
24 | #include "dhd_proto.h" | ||
25 | #include "dhd_dbg.h" | 24 | #include "dhd_dbg.h" |
26 | #include "fwil.h" | 25 | #include "fwil.h" |
26 | #include "fwil_types.h" | ||
27 | #include "tracepoint.h" | 27 | #include "tracepoint.h" |
28 | 28 | ||
29 | #define PKTFILTER_BUF_SIZE 128 | 29 | #define PKTFILTER_BUF_SIZE 128 |
@@ -257,8 +257,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
257 | u8 buf[BRCMF_DCMD_SMLEN]; | 257 | u8 buf[BRCMF_DCMD_SMLEN]; |
258 | char *ptr; | 258 | char *ptr; |
259 | s32 err; | 259 | s32 err; |
260 | struct brcmf_bus_dcmd *cmdlst; | ||
261 | struct list_head *cur, *q; | ||
262 | 260 | ||
263 | /* retreive mac address */ | 261 | /* retreive mac address */ |
264 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | 262 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, |
@@ -281,9 +279,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
281 | } | 279 | } |
282 | ptr = (char *)buf; | 280 | ptr = (char *)buf; |
283 | strsep(&ptr, "\n"); | 281 | strsep(&ptr, "\n"); |
282 | |||
284 | /* Print fw version info */ | 283 | /* Print fw version info */ |
285 | brcmf_err("Firmware version = %s\n", buf); | 284 | brcmf_err("Firmware version = %s\n", buf); |
286 | 285 | ||
286 | /* locate firmware version number for ethtool */ | ||
287 | ptr = strrchr(buf, ' ') + 1; | ||
288 | strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); | ||
289 | |||
287 | /* | 290 | /* |
288 | * Setup timeout if Beacons are lost and roam is off to report | 291 | * Setup timeout if Beacons are lost and roam is off to report |
289 | * link down | 292 | * link down |
@@ -342,17 +345,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
342 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | 345 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, |
343 | 0, true); | 346 | 0, true); |
344 | 347 | ||
345 | /* set bus specific command if there is any */ | 348 | /* do bus specific preinit here */ |
346 | list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) { | 349 | err = brcmf_bus_preinit(ifp->drvr->bus_if); |
347 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); | ||
348 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { | ||
349 | brcmf_fil_iovar_data_set(ifp, cmdlst->name, | ||
350 | cmdlst->param, | ||
351 | cmdlst->param_len); | ||
352 | } | ||
353 | list_del(cur); | ||
354 | kfree(cmdlst); | ||
355 | } | ||
356 | done: | 350 | done: |
357 | return err; | 351 | return err; |
358 | } | 352 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 0f9e9057e7dd..03fe8aca4d32 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "dhd.h" | 22 | #include "dhd.h" |
23 | #include "dhd_bus.h" | 23 | #include "dhd_bus.h" |
24 | #include "dhd_dbg.h" | 24 | #include "dhd_dbg.h" |
25 | #include "tracepoint.h" | ||
26 | 25 | ||
27 | static struct dentry *root_folder; | 26 | static struct dentry *root_folder; |
28 | 27 | ||
@@ -42,6 +41,40 @@ void brcmf_debugfs_exit(void) | |||
42 | root_folder = NULL; | 41 | root_folder = NULL; |
43 | } | 42 | } |
44 | 43 | ||
44 | static | ||
45 | ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data, | ||
46 | size_t count, loff_t *ppos) | ||
47 | { | ||
48 | struct brcmf_pub *drvr = f->private_data; | ||
49 | struct brcmf_bus *bus = drvr->bus_if; | ||
50 | char buf[40]; | ||
51 | int res; | ||
52 | |||
53 | /* only allow read from start */ | ||
54 | if (*ppos > 0) | ||
55 | return 0; | ||
56 | |||
57 | res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n", | ||
58 | bus->chip, bus->chip, bus->chiprev); | ||
59 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
60 | } | ||
61 | |||
62 | static const struct file_operations brcmf_debugfs_chipinfo_ops = { | ||
63 | .owner = THIS_MODULE, | ||
64 | .open = simple_open, | ||
65 | .read = brcmf_debugfs_chipinfo_read | ||
66 | }; | ||
67 | |||
68 | static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr) | ||
69 | { | ||
70 | struct dentry *dentry = drvr->dbgfs_dir; | ||
71 | |||
72 | if (!IS_ERR_OR_NULL(dentry)) | ||
73 | debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, | ||
74 | &brcmf_debugfs_chipinfo_ops); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
45 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) | 78 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) |
46 | { | 79 | { |
47 | struct device *dev = drvr->bus_if->dev; | 80 | struct device *dev = drvr->bus_if->dev; |
@@ -50,6 +83,7 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
50 | return -ENODEV; | 83 | return -ENODEV; |
51 | 84 | ||
52 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); | 85 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); |
86 | brcmf_debugfs_create_chipinfo(drvr); | ||
53 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); | 87 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); |
54 | } | 88 | } |
55 | 89 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 0af1f5dc583a..ef52ed7abc69 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define BRCMF_USB_VAL 0x00002000 | 33 | #define BRCMF_USB_VAL 0x00002000 |
34 | #define BRCMF_SCAN_VAL 0x00004000 | 34 | #define BRCMF_SCAN_VAL 0x00004000 |
35 | #define BRCMF_CONN_VAL 0x00008000 | 35 | #define BRCMF_CONN_VAL 0x00008000 |
36 | #define BRCMF_CDC_VAL 0x00010000 | 36 | #define BRCMF_BCDC_VAL 0x00010000 |
37 | #define BRCMF_SDIO_VAL 0x00020000 | 37 | #define BRCMF_SDIO_VAL 0x00020000 |
38 | 38 | ||
39 | /* set default print format */ | 39 | /* set default print format */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 64e9cff241b9..bce0b8e511fd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -24,13 +24,13 @@ | |||
24 | 24 | ||
25 | #include "dhd.h" | 25 | #include "dhd.h" |
26 | #include "dhd_bus.h" | 26 | #include "dhd_bus.h" |
27 | #include "dhd_proto.h" | ||
28 | #include "dhd_dbg.h" | 27 | #include "dhd_dbg.h" |
29 | #include "fwil_types.h" | 28 | #include "fwil_types.h" |
30 | #include "p2p.h" | 29 | #include "p2p.h" |
31 | #include "wl_cfg80211.h" | 30 | #include "wl_cfg80211.h" |
32 | #include "fwil.h" | 31 | #include "fwil.h" |
33 | #include "fwsignal.h" | 32 | #include "fwsignal.h" |
33 | #include "proto.h" | ||
34 | 34 | ||
35 | MODULE_AUTHOR("Broadcom Corporation"); | 35 | MODULE_AUTHOR("Broadcom Corporation"); |
36 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | 36 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); |
@@ -592,28 +592,6 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) | |||
592 | return &ifp->stats; | 592 | return &ifp->stats; |
593 | } | 593 | } |
594 | 594 | ||
595 | /* | ||
596 | * Set current toe component enables in toe_ol iovar, | ||
597 | * and set toe global enable iovar | ||
598 | */ | ||
599 | static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol) | ||
600 | { | ||
601 | s32 err; | ||
602 | |||
603 | err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol); | ||
604 | if (err < 0) { | ||
605 | brcmf_err("Setting toe_ol failed, %d\n", err); | ||
606 | return err; | ||
607 | } | ||
608 | |||
609 | err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0)); | ||
610 | if (err < 0) | ||
611 | brcmf_err("Setting toe failed, %d\n", err); | ||
612 | |||
613 | return err; | ||
614 | |||
615 | } | ||
616 | |||
617 | static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, | 595 | static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, |
618 | struct ethtool_drvinfo *info) | 596 | struct ethtool_drvinfo *info) |
619 | { | 597 | { |
@@ -621,8 +599,8 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, | |||
621 | struct brcmf_pub *drvr = ifp->drvr; | 599 | struct brcmf_pub *drvr = ifp->drvr; |
622 | 600 | ||
623 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); | 601 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); |
624 | snprintf(info->version, sizeof(info->version), "%lu", | 602 | snprintf(info->version, sizeof(info->version), "n/a"); |
625 | drvr->drv_version); | 603 | strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); |
626 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), | 604 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), |
627 | sizeof(info->bus_info)); | 605 | sizeof(info->bus_info)); |
628 | } | 606 | } |
@@ -631,124 +609,6 @@ static const struct ethtool_ops brcmf_ethtool_ops = { | |||
631 | .get_drvinfo = brcmf_ethtool_get_drvinfo, | 609 | .get_drvinfo = brcmf_ethtool_get_drvinfo, |
632 | }; | 610 | }; |
633 | 611 | ||
634 | static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) | ||
635 | { | ||
636 | struct brcmf_pub *drvr = ifp->drvr; | ||
637 | struct ethtool_drvinfo info; | ||
638 | char drvname[sizeof(info.driver)]; | ||
639 | u32 cmd; | ||
640 | struct ethtool_value edata; | ||
641 | u32 toe_cmpnt, csum_dir; | ||
642 | int ret; | ||
643 | |||
644 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); | ||
645 | |||
646 | /* all ethtool calls start with a cmd word */ | ||
647 | if (copy_from_user(&cmd, uaddr, sizeof(u32))) | ||
648 | return -EFAULT; | ||
649 | |||
650 | switch (cmd) { | ||
651 | case ETHTOOL_GDRVINFO: | ||
652 | /* Copy out any request driver name */ | ||
653 | if (copy_from_user(&info, uaddr, sizeof(info))) | ||
654 | return -EFAULT; | ||
655 | strncpy(drvname, info.driver, sizeof(info.driver)); | ||
656 | drvname[sizeof(info.driver) - 1] = '\0'; | ||
657 | |||
658 | /* clear struct for return */ | ||
659 | memset(&info, 0, sizeof(info)); | ||
660 | info.cmd = cmd; | ||
661 | |||
662 | /* if requested, identify ourselves */ | ||
663 | if (strcmp(drvname, "?dhd") == 0) { | ||
664 | sprintf(info.driver, "dhd"); | ||
665 | strcpy(info.version, BRCMF_VERSION_STR); | ||
666 | } | ||
667 | /* report dongle driver type */ | ||
668 | else | ||
669 | sprintf(info.driver, "wl"); | ||
670 | |||
671 | sprintf(info.version, "%lu", drvr->drv_version); | ||
672 | if (copy_to_user(uaddr, &info, sizeof(info))) | ||
673 | return -EFAULT; | ||
674 | brcmf_dbg(TRACE, "given %*s, returning %s\n", | ||
675 | (int)sizeof(drvname), drvname, info.driver); | ||
676 | break; | ||
677 | |||
678 | /* Get toe offload components from dongle */ | ||
679 | case ETHTOOL_GRXCSUM: | ||
680 | case ETHTOOL_GTXCSUM: | ||
681 | ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt); | ||
682 | if (ret < 0) | ||
683 | return ret; | ||
684 | |||
685 | csum_dir = | ||
686 | (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; | ||
687 | |||
688 | edata.cmd = cmd; | ||
689 | edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; | ||
690 | |||
691 | if (copy_to_user(uaddr, &edata, sizeof(edata))) | ||
692 | return -EFAULT; | ||
693 | break; | ||
694 | |||
695 | /* Set toe offload components in dongle */ | ||
696 | case ETHTOOL_SRXCSUM: | ||
697 | case ETHTOOL_STXCSUM: | ||
698 | if (copy_from_user(&edata, uaddr, sizeof(edata))) | ||
699 | return -EFAULT; | ||
700 | |||
701 | /* Read the current settings, update and write back */ | ||
702 | ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt); | ||
703 | if (ret < 0) | ||
704 | return ret; | ||
705 | |||
706 | csum_dir = | ||
707 | (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; | ||
708 | |||
709 | if (edata.data != 0) | ||
710 | toe_cmpnt |= csum_dir; | ||
711 | else | ||
712 | toe_cmpnt &= ~csum_dir; | ||
713 | |||
714 | ret = brcmf_toe_set(ifp, toe_cmpnt); | ||
715 | if (ret < 0) | ||
716 | return ret; | ||
717 | |||
718 | /* If setting TX checksum mode, tell Linux the new mode */ | ||
719 | if (cmd == ETHTOOL_STXCSUM) { | ||
720 | if (edata.data) | ||
721 | ifp->ndev->features |= NETIF_F_IP_CSUM; | ||
722 | else | ||
723 | ifp->ndev->features &= ~NETIF_F_IP_CSUM; | ||
724 | } | ||
725 | |||
726 | break; | ||
727 | |||
728 | default: | ||
729 | return -EOPNOTSUPP; | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, | ||
736 | int cmd) | ||
737 | { | ||
738 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
739 | struct brcmf_pub *drvr = ifp->drvr; | ||
740 | |||
741 | brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd); | ||
742 | |||
743 | if (!drvr->iflist[ifp->bssidx]) | ||
744 | return -1; | ||
745 | |||
746 | if (cmd == SIOCETHTOOL) | ||
747 | return brcmf_ethtool(ifp, ifr->ifr_data); | ||
748 | |||
749 | return -EOPNOTSUPP; | ||
750 | } | ||
751 | |||
752 | static int brcmf_netdev_stop(struct net_device *ndev) | 612 | static int brcmf_netdev_stop(struct net_device *ndev) |
753 | { | 613 | { |
754 | struct brcmf_if *ifp = netdev_priv(ndev); | 614 | struct brcmf_if *ifp = netdev_priv(ndev); |
@@ -769,7 +629,6 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
769 | struct brcmf_pub *drvr = ifp->drvr; | 629 | struct brcmf_pub *drvr = ifp->drvr; |
770 | struct brcmf_bus *bus_if = drvr->bus_if; | 630 | struct brcmf_bus *bus_if = drvr->bus_if; |
771 | u32 toe_ol; | 631 | u32 toe_ol; |
772 | s32 ret = 0; | ||
773 | 632 | ||
774 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); | 633 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); |
775 | 634 | ||
@@ -788,21 +647,20 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
788 | else | 647 | else |
789 | ndev->features &= ~NETIF_F_IP_CSUM; | 648 | ndev->features &= ~NETIF_F_IP_CSUM; |
790 | 649 | ||
791 | /* Allow transmit calls */ | ||
792 | netif_start_queue(ndev); | ||
793 | if (brcmf_cfg80211_up(ndev)) { | 650 | if (brcmf_cfg80211_up(ndev)) { |
794 | brcmf_err("failed to bring up cfg80211\n"); | 651 | brcmf_err("failed to bring up cfg80211\n"); |
795 | return -1; | 652 | return -EIO; |
796 | } | 653 | } |
797 | 654 | ||
798 | return ret; | 655 | /* Allow transmit calls */ |
656 | netif_start_queue(ndev); | ||
657 | return 0; | ||
799 | } | 658 | } |
800 | 659 | ||
801 | static const struct net_device_ops brcmf_netdev_ops_pri = { | 660 | static const struct net_device_ops brcmf_netdev_ops_pri = { |
802 | .ndo_open = brcmf_netdev_open, | 661 | .ndo_open = brcmf_netdev_open, |
803 | .ndo_stop = brcmf_netdev_stop, | 662 | .ndo_stop = brcmf_netdev_stop, |
804 | .ndo_get_stats = brcmf_netdev_get_stats, | 663 | .ndo_get_stats = brcmf_netdev_get_stats, |
805 | .ndo_do_ioctl = brcmf_netdev_ioctl_entry, | ||
806 | .ndo_start_xmit = brcmf_netdev_start_xmit, | 664 | .ndo_start_xmit = brcmf_netdev_start_xmit, |
807 | .ndo_set_mac_address = brcmf_netdev_set_mac_address, | 665 | .ndo_set_mac_address = brcmf_netdev_set_mac_address, |
808 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list | 666 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list |
@@ -868,13 +726,6 @@ static int brcmf_net_p2p_stop(struct net_device *ndev) | |||
868 | return brcmf_cfg80211_down(ndev); | 726 | return brcmf_cfg80211_down(ndev); |
869 | } | 727 | } |
870 | 728 | ||
871 | static int brcmf_net_p2p_do_ioctl(struct net_device *ndev, | ||
872 | struct ifreq *ifr, int cmd) | ||
873 | { | ||
874 | brcmf_dbg(TRACE, "Enter\n"); | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, | 729 | static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, |
879 | struct net_device *ndev) | 730 | struct net_device *ndev) |
880 | { | 731 | { |
@@ -887,7 +738,6 @@ static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, | |||
887 | static const struct net_device_ops brcmf_netdev_ops_p2p = { | 738 | static const struct net_device_ops brcmf_netdev_ops_p2p = { |
888 | .ndo_open = brcmf_net_p2p_open, | 739 | .ndo_open = brcmf_net_p2p_open, |
889 | .ndo_stop = brcmf_net_p2p_stop, | 740 | .ndo_stop = brcmf_net_p2p_stop, |
890 | .ndo_do_ioctl = brcmf_net_p2p_do_ioctl, | ||
891 | .ndo_start_xmit = brcmf_net_p2p_start_xmit | 741 | .ndo_start_xmit = brcmf_net_p2p_start_xmit |
892 | }; | 742 | }; |
893 | 743 | ||
@@ -1016,7 +866,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
1016 | } | 866 | } |
1017 | } | 867 | } |
1018 | 868 | ||
1019 | int brcmf_attach(uint bus_hdrlen, struct device *dev) | 869 | int brcmf_attach(struct device *dev) |
1020 | { | 870 | { |
1021 | struct brcmf_pub *drvr = NULL; | 871 | struct brcmf_pub *drvr = NULL; |
1022 | int ret = 0; | 872 | int ret = 0; |
@@ -1031,7 +881,7 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) | |||
1031 | mutex_init(&drvr->proto_block); | 881 | mutex_init(&drvr->proto_block); |
1032 | 882 | ||
1033 | /* Link to bus module */ | 883 | /* Link to bus module */ |
1034 | drvr->hdrlen = bus_hdrlen; | 884 | drvr->hdrlen = 0; |
1035 | drvr->bus_if = dev_get_drvdata(dev); | 885 | drvr->bus_if = dev_get_drvdata(dev); |
1036 | drvr->bus_if->drvr = drvr; | 886 | drvr->bus_if->drvr = drvr; |
1037 | 887 | ||
@@ -1048,8 +898,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) | |||
1048 | /* attach firmware event handler */ | 898 | /* attach firmware event handler */ |
1049 | brcmf_fweh_attach(drvr); | 899 | brcmf_fweh_attach(drvr); |
1050 | 900 | ||
1051 | INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); | ||
1052 | |||
1053 | return ret; | 901 | return ret; |
1054 | 902 | ||
1055 | fail: | 903 | fail: |
@@ -1138,14 +986,21 @@ fail: | |||
1138 | return 0; | 986 | return 0; |
1139 | } | 987 | } |
1140 | 988 | ||
989 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len) | ||
990 | { | ||
991 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
992 | struct brcmf_pub *drvr = bus_if->drvr; | ||
993 | |||
994 | if (drvr) { | ||
995 | drvr->hdrlen += len; | ||
996 | } | ||
997 | } | ||
998 | |||
1141 | static void brcmf_bus_detach(struct brcmf_pub *drvr) | 999 | static void brcmf_bus_detach(struct brcmf_pub *drvr) |
1142 | { | 1000 | { |
1143 | brcmf_dbg(TRACE, "Enter\n"); | 1001 | brcmf_dbg(TRACE, "Enter\n"); |
1144 | 1002 | ||
1145 | if (drvr) { | 1003 | if (drvr) { |
1146 | /* Stop the protocol module */ | ||
1147 | brcmf_proto_stop(drvr); | ||
1148 | |||
1149 | /* Stop the bus module */ | 1004 | /* Stop the bus module */ |
1150 | brcmf_bus_stop(drvr->bus_if); | 1005 | brcmf_bus_stop(drvr->bus_if); |
1151 | } | 1006 | } |
@@ -1186,8 +1041,7 @@ void brcmf_detach(struct device *dev) | |||
1186 | 1041 | ||
1187 | brcmf_bus_detach(drvr); | 1042 | brcmf_bus_detach(drvr); |
1188 | 1043 | ||
1189 | if (drvr->prot) | 1044 | brcmf_proto_detach(drvr); |
1190 | brcmf_proto_detach(drvr); | ||
1191 | 1045 | ||
1192 | brcmf_fws_deinit(drvr); | 1046 | brcmf_fws_deinit(drvr); |
1193 | 1047 | ||
@@ -1196,6 +1050,14 @@ void brcmf_detach(struct device *dev) | |||
1196 | kfree(drvr); | 1050 | kfree(drvr); |
1197 | } | 1051 | } |
1198 | 1052 | ||
1053 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len) | ||
1054 | { | ||
1055 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1056 | struct brcmf_if *ifp = bus_if->drvr->iflist[0]; | ||
1057 | |||
1058 | return brcmf_fil_iovar_data_set(ifp, name, data, len); | ||
1059 | } | ||
1060 | |||
1199 | static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) | 1061 | static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) |
1200 | { | 1062 | { |
1201 | return atomic_read(&ifp->pend_8021x_cnt); | 1063 | return atomic_read(&ifp->pend_8021x_cnt); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h deleted file mode 100644 index 53c6e710f2cb..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _BRCMF_PROTO_H_ | ||
18 | #define _BRCMF_PROTO_H_ | ||
19 | |||
20 | /* | ||
21 | * Exported from the brcmf protocol module (brcmf_cdc) | ||
22 | */ | ||
23 | |||
24 | /* Linkage, sets prot link and updates hdrlen in pub */ | ||
25 | int brcmf_proto_attach(struct brcmf_pub *drvr); | ||
26 | |||
27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ | ||
28 | void brcmf_proto_detach(struct brcmf_pub *drvr); | ||
29 | |||
30 | /* Stop protocol: sync w/dongle state. */ | ||
31 | void brcmf_proto_stop(struct brcmf_pub *drvr); | ||
32 | |||
33 | /* Add any protocol-specific data header. | ||
34 | * Caller must reserve prot_hdrlen prepend space. | ||
35 | */ | ||
36 | void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, | ||
37 | struct sk_buff *txp); | ||
38 | |||
39 | /* Sets dongle media info (drv_version, mac address). */ | ||
40 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | ||
41 | |||
42 | #endif /* _BRCMF_PROTO_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index b02953c4ade7..0f95f3e79c10 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/platform_data/brcmfmac-sdio.h> | 34 | #include <linux/platform_data/brcmfmac-sdio.h> |
35 | #include <linux/moduleparam.h> | ||
35 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
36 | #include <defs.h> | 37 | #include <defs.h> |
37 | #include <brcmu_wifi.h> | 38 | #include <brcmu_wifi.h> |
@@ -110,6 +111,8 @@ struct rte_console { | |||
110 | #define BRCMF_TXBOUND 20 /* Default for max tx frames in | 111 | #define BRCMF_TXBOUND 20 /* Default for max tx frames in |
111 | one scheduling */ | 112 | one scheduling */ |
112 | 113 | ||
114 | #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ | ||
115 | |||
113 | #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ | 116 | #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ |
114 | 117 | ||
115 | #define MEMBLOCK 2048 /* Block size used for downloading | 118 | #define MEMBLOCK 2048 /* Block size used for downloading |
@@ -360,6 +363,8 @@ struct brcmf_sdio_hdrinfo { | |||
360 | u16 len_left; | 363 | u16 len_left; |
361 | u16 len_nxtfrm; | 364 | u16 len_nxtfrm; |
362 | u8 dat_offset; | 365 | u8 dat_offset; |
366 | bool lastfrm; | ||
367 | u16 tail_pad; | ||
363 | }; | 368 | }; |
364 | 369 | ||
365 | /* misc chip info needed by some of the routines */ | 370 | /* misc chip info needed by some of the routines */ |
@@ -384,7 +389,7 @@ struct brcmf_sdio { | |||
384 | u8 tx_seq; /* Transmit sequence number (next) */ | 389 | u8 tx_seq; /* Transmit sequence number (next) */ |
385 | u8 tx_max; /* Maximum transmit sequence allowed */ | 390 | u8 tx_max; /* Maximum transmit sequence allowed */ |
386 | 391 | ||
387 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; | 392 | u8 *hdrbuf; /* buffer for handling rx frame */ |
388 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ | 393 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ |
389 | u8 rx_seq; /* Receive sequence number (expected) */ | 394 | u8 rx_seq; /* Receive sequence number (expected) */ |
390 | struct brcmf_sdio_hdrinfo cur_read; | 395 | struct brcmf_sdio_hdrinfo cur_read; |
@@ -455,6 +460,10 @@ struct brcmf_sdio { | |||
455 | bool sleeping; /* SDIO bus sleeping */ | 460 | bool sleeping; /* SDIO bus sleeping */ |
456 | 461 | ||
457 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ | 462 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ |
463 | bool txglom; /* host tx glomming enable flag */ | ||
464 | struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */ | ||
465 | u16 head_align; /* buffer pointer alignment */ | ||
466 | u16 sgentry_align; /* scatter-gather buffer alignment */ | ||
458 | }; | 467 | }; |
459 | 468 | ||
460 | /* clkstate */ | 469 | /* clkstate */ |
@@ -479,6 +488,10 @@ static const uint max_roundup = 512; | |||
479 | 488 | ||
480 | #define ALIGNMENT 4 | 489 | #define ALIGNMENT 4 |
481 | 490 | ||
491 | static int brcmf_sdio_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; | ||
492 | module_param_named(txglomsz, brcmf_sdio_txglomsz, int, 0); | ||
493 | MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); | ||
494 | |||
482 | enum brcmf_sdio_frmtype { | 495 | enum brcmf_sdio_frmtype { |
483 | BRCMF_SDIO_FT_NORMAL, | 496 | BRCMF_SDIO_FT_NORMAL, |
484 | BRCMF_SDIO_FT_SUPER, | 497 | BRCMF_SDIO_FT_SUPER, |
@@ -499,6 +512,8 @@ enum brcmf_sdio_frmtype { | |||
499 | #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" | 512 | #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" |
500 | #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" | 513 | #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" |
501 | #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" | 514 | #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" |
515 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" | ||
516 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" | ||
502 | 517 | ||
503 | MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); | 518 | MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); |
504 | MODULE_FIRMWARE(BCM43143_NVRAM_NAME); | 519 | MODULE_FIRMWARE(BCM43143_NVRAM_NAME); |
@@ -514,6 +529,8 @@ MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME); | |||
514 | MODULE_FIRMWARE(BCM4334_NVRAM_NAME); | 529 | MODULE_FIRMWARE(BCM4334_NVRAM_NAME); |
515 | MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); | 530 | MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); |
516 | MODULE_FIRMWARE(BCM4335_NVRAM_NAME); | 531 | MODULE_FIRMWARE(BCM4335_NVRAM_NAME); |
532 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); | ||
533 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); | ||
517 | 534 | ||
518 | struct brcmf_firmware_names { | 535 | struct brcmf_firmware_names { |
519 | u32 chipid; | 536 | u32 chipid; |
@@ -537,7 +554,8 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { | |||
537 | { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, | 554 | { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, |
538 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, | 555 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, |
539 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | 556 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, |
540 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) } | 557 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
558 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) } | ||
541 | }; | 559 | }; |
542 | 560 | ||
543 | 561 | ||
@@ -1097,10 +1115,18 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1097 | * host and WiFi dongle which contains information needed for SDIO core and | 1115 | * host and WiFi dongle which contains information needed for SDIO core and |
1098 | * firmware | 1116 | * firmware |
1099 | * | 1117 | * |
1100 | * It consists of 2 parts: hw header and software header | 1118 | * It consists of 3 parts: hardware header, hardware extension header and |
1119 | * software header | ||
1101 | * hardware header (frame tag) - 4 bytes | 1120 | * hardware header (frame tag) - 4 bytes |
1102 | * Byte 0~1: Frame length | 1121 | * Byte 0~1: Frame length |
1103 | * Byte 2~3: Checksum, bit-wise inverse of frame length | 1122 | * Byte 2~3: Checksum, bit-wise inverse of frame length |
1123 | * hardware extension header - 8 bytes | ||
1124 | * Tx glom mode only, N/A for Rx or normal Tx | ||
1125 | * Byte 0~1: Packet length excluding hw frame tag | ||
1126 | * Byte 2: Reserved | ||
1127 | * Byte 3: Frame flags, bit 0: last frame indication | ||
1128 | * Byte 4~5: Reserved | ||
1129 | * Byte 6~7: Tail padding length | ||
1104 | * software header - 8 bytes | 1130 | * software header - 8 bytes |
1105 | * Byte 0: Rx/Tx sequence number | 1131 | * Byte 0: Rx/Tx sequence number |
1106 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag | 1132 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag |
@@ -1111,6 +1137,7 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1111 | * Byte 6~7: Reserved | 1137 | * Byte 6~7: Reserved |
1112 | */ | 1138 | */ |
1113 | #define SDPCM_HWHDR_LEN 4 | 1139 | #define SDPCM_HWHDR_LEN 4 |
1140 | #define SDPCM_HWEXT_LEN 8 | ||
1114 | #define SDPCM_SWHDR_LEN 8 | 1141 | #define SDPCM_SWHDR_LEN 8 |
1115 | #define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN) | 1142 | #define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN) |
1116 | /* software header */ | 1143 | /* software header */ |
@@ -1147,7 +1174,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
1147 | u8 rx_seq, fc, tx_seq_max; | 1174 | u8 rx_seq, fc, tx_seq_max; |
1148 | u32 swheader; | 1175 | u32 swheader; |
1149 | 1176 | ||
1150 | trace_brcmf_sdpcm_hdr(false, header); | 1177 | trace_brcmf_sdpcm_hdr(SDPCM_RX, header); |
1151 | 1178 | ||
1152 | /* hw header */ | 1179 | /* hw header */ |
1153 | len = get_unaligned_le16(header); | 1180 | len = get_unaligned_le16(header); |
@@ -1260,25 +1287,34 @@ static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length) | |||
1260 | static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, | 1287 | static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, |
1261 | struct brcmf_sdio_hdrinfo *hd_info) | 1288 | struct brcmf_sdio_hdrinfo *hd_info) |
1262 | { | 1289 | { |
1263 | u32 sw_header; | 1290 | u32 hdrval; |
1291 | u8 hdr_offset; | ||
1264 | 1292 | ||
1265 | brcmf_sdio_update_hwhdr(header, hd_info->len); | 1293 | brcmf_sdio_update_hwhdr(header, hd_info->len); |
1266 | 1294 | hdr_offset = SDPCM_HWHDR_LEN; | |
1267 | sw_header = bus->tx_seq; | 1295 | |
1268 | sw_header |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) & | 1296 | if (bus->txglom) { |
1269 | SDPCM_CHANNEL_MASK; | 1297 | hdrval = (hd_info->len - hdr_offset) | (hd_info->lastfrm << 24); |
1270 | sw_header |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) & | 1298 | *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval); |
1271 | SDPCM_DOFFSET_MASK; | 1299 | hdrval = (u16)hd_info->tail_pad << 16; |
1272 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); | 1300 | *(((__le32 *)(header + hdr_offset)) + 1) = cpu_to_le32(hdrval); |
1273 | *(((__le32 *)header) + 2) = 0; | 1301 | hdr_offset += SDPCM_HWEXT_LEN; |
1274 | trace_brcmf_sdpcm_hdr(true, header); | 1302 | } |
1303 | |||
1304 | hdrval = hd_info->seq_num; | ||
1305 | hdrval |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) & | ||
1306 | SDPCM_CHANNEL_MASK; | ||
1307 | hdrval |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) & | ||
1308 | SDPCM_DOFFSET_MASK; | ||
1309 | *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval); | ||
1310 | *(((__le32 *)(header + hdr_offset)) + 1) = 0; | ||
1311 | trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header); | ||
1275 | } | 1312 | } |
1276 | 1313 | ||
1277 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1314 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
1278 | { | 1315 | { |
1279 | u16 dlen, totlen; | 1316 | u16 dlen, totlen; |
1280 | u8 *dptr, num = 0; | 1317 | u8 *dptr, num = 0; |
1281 | u32 align = 0; | ||
1282 | u16 sublen; | 1318 | u16 sublen; |
1283 | struct sk_buff *pfirst, *pnext; | 1319 | struct sk_buff *pfirst, *pnext; |
1284 | 1320 | ||
@@ -1293,11 +1329,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1293 | brcmf_dbg(SDIO, "start: glomd %p glom %p\n", | 1329 | brcmf_dbg(SDIO, "start: glomd %p glom %p\n", |
1294 | bus->glomd, skb_peek(&bus->glom)); | 1330 | bus->glomd, skb_peek(&bus->glom)); |
1295 | 1331 | ||
1296 | if (bus->sdiodev->pdata) | ||
1297 | align = bus->sdiodev->pdata->sd_sgentry_align; | ||
1298 | if (align < 4) | ||
1299 | align = 4; | ||
1300 | |||
1301 | /* If there's a descriptor, generate the packet chain */ | 1332 | /* If there's a descriptor, generate the packet chain */ |
1302 | if (bus->glomd) { | 1333 | if (bus->glomd) { |
1303 | pfirst = pnext = NULL; | 1334 | pfirst = pnext = NULL; |
@@ -1321,9 +1352,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1321 | pnext = NULL; | 1352 | pnext = NULL; |
1322 | break; | 1353 | break; |
1323 | } | 1354 | } |
1324 | if (sublen % align) { | 1355 | if (sublen % bus->sgentry_align) { |
1325 | brcmf_err("sublen %d not multiple of %d\n", | 1356 | brcmf_err("sublen %d not multiple of %d\n", |
1326 | sublen, align); | 1357 | sublen, bus->sgentry_align); |
1327 | } | 1358 | } |
1328 | totlen += sublen; | 1359 | totlen += sublen; |
1329 | 1360 | ||
@@ -1336,7 +1367,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1336 | } | 1367 | } |
1337 | 1368 | ||
1338 | /* Allocate/chain packet for next subframe */ | 1369 | /* Allocate/chain packet for next subframe */ |
1339 | pnext = brcmu_pkt_buf_get_skb(sublen + align); | 1370 | pnext = brcmu_pkt_buf_get_skb(sublen + bus->sgentry_align); |
1340 | if (pnext == NULL) { | 1371 | if (pnext == NULL) { |
1341 | brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n", | 1372 | brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n", |
1342 | num, sublen); | 1373 | num, sublen); |
@@ -1345,7 +1376,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1345 | skb_queue_tail(&bus->glom, pnext); | 1376 | skb_queue_tail(&bus->glom, pnext); |
1346 | 1377 | ||
1347 | /* Adhere to start alignment requirements */ | 1378 | /* Adhere to start alignment requirements */ |
1348 | pkt_align(pnext, sublen, align); | 1379 | pkt_align(pnext, sublen, bus->sgentry_align); |
1349 | } | 1380 | } |
1350 | 1381 | ||
1351 | /* If all allocations succeeded, save packet chain | 1382 | /* If all allocations succeeded, save packet chain |
@@ -1549,9 +1580,9 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1549 | goto done; | 1580 | goto done; |
1550 | 1581 | ||
1551 | rbuf = bus->rxbuf; | 1582 | rbuf = bus->rxbuf; |
1552 | pad = ((unsigned long)rbuf % BRCMF_SDALIGN); | 1583 | pad = ((unsigned long)rbuf % bus->head_align); |
1553 | if (pad) | 1584 | if (pad) |
1554 | rbuf += (BRCMF_SDALIGN - pad); | 1585 | rbuf += (bus->head_align - pad); |
1555 | 1586 | ||
1556 | /* Copy the already-read portion over */ | 1587 | /* Copy the already-read portion over */ |
1557 | memcpy(buf, hdr, BRCMF_FIRSTREAD); | 1588 | memcpy(buf, hdr, BRCMF_FIRSTREAD); |
@@ -1565,14 +1596,10 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1565 | if ((pad <= bus->roundup) && (pad < bus->blocksize) && | 1596 | if ((pad <= bus->roundup) && (pad < bus->blocksize) && |
1566 | ((len + pad) < bus->sdiodev->bus_if->maxctl)) | 1597 | ((len + pad) < bus->sdiodev->bus_if->maxctl)) |
1567 | rdlen += pad; | 1598 | rdlen += pad; |
1568 | } else if (rdlen % BRCMF_SDALIGN) { | 1599 | } else if (rdlen % bus->head_align) { |
1569 | rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); | 1600 | rdlen += bus->head_align - (rdlen % bus->head_align); |
1570 | } | 1601 | } |
1571 | 1602 | ||
1572 | /* Satisfy length-alignment requirements */ | ||
1573 | if (rdlen & (ALIGNMENT - 1)) | ||
1574 | rdlen = roundup(rdlen, ALIGNMENT); | ||
1575 | |||
1576 | /* Drop if the read is too big or it exceeds our maximum */ | 1603 | /* Drop if the read is too big or it exceeds our maximum */ |
1577 | if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { | 1604 | if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { |
1578 | brcmf_err("%d-byte control read exceeds %d-byte buffer\n", | 1605 | brcmf_err("%d-byte control read exceeds %d-byte buffer\n", |
@@ -1637,8 +1664,8 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | |||
1637 | if (*pad <= bus->roundup && *pad < bus->blocksize && | 1664 | if (*pad <= bus->roundup && *pad < bus->blocksize && |
1638 | *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) | 1665 | *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) |
1639 | *rdlen += *pad; | 1666 | *rdlen += *pad; |
1640 | } else if (*rdlen % BRCMF_SDALIGN) { | 1667 | } else if (*rdlen % bus->head_align) { |
1641 | *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN); | 1668 | *rdlen += bus->head_align - (*rdlen % bus->head_align); |
1642 | } | 1669 | } |
1643 | } | 1670 | } |
1644 | 1671 | ||
@@ -1726,7 +1753,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1726 | brcmf_pad(bus, &pad, &rd->len_left); | 1753 | brcmf_pad(bus, &pad, &rd->len_left); |
1727 | 1754 | ||
1728 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + | 1755 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + |
1729 | BRCMF_SDALIGN); | 1756 | bus->head_align); |
1730 | if (!pkt) { | 1757 | if (!pkt) { |
1731 | /* Give up on data, request rtx of events */ | 1758 | /* Give up on data, request rtx of events */ |
1732 | brcmf_err("brcmu_pkt_buf_get_skb failed\n"); | 1759 | brcmf_err("brcmu_pkt_buf_get_skb failed\n"); |
@@ -1736,7 +1763,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1736 | continue; | 1763 | continue; |
1737 | } | 1764 | } |
1738 | skb_pull(pkt, head_read); | 1765 | skb_pull(pkt, head_read); |
1739 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | 1766 | pkt_align(pkt, rd->len_left, bus->head_align); |
1740 | 1767 | ||
1741 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1768 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1742 | SDIO_FUNC_2, F2SYNC, pkt); | 1769 | SDIO_FUNC_2, F2SYNC, pkt); |
@@ -1871,6 +1898,29 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
1871 | return; | 1898 | return; |
1872 | } | 1899 | } |
1873 | 1900 | ||
1901 | static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt) | ||
1902 | { | ||
1903 | u16 head_pad; | ||
1904 | u8 *dat_buf; | ||
1905 | |||
1906 | dat_buf = (u8 *)(pkt->data); | ||
1907 | |||
1908 | /* Check head padding */ | ||
1909 | head_pad = ((unsigned long)dat_buf % bus->head_align); | ||
1910 | if (head_pad) { | ||
1911 | if (skb_headroom(pkt) < head_pad) { | ||
1912 | bus->sdiodev->bus_if->tx_realloc++; | ||
1913 | head_pad = 0; | ||
1914 | if (skb_cow(pkt, head_pad)) | ||
1915 | return -ENOMEM; | ||
1916 | } | ||
1917 | skb_push(pkt, head_pad); | ||
1918 | dat_buf = (u8 *)(pkt->data); | ||
1919 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); | ||
1920 | } | ||
1921 | return head_pad; | ||
1922 | } | ||
1923 | |||
1874 | /** | 1924 | /** |
1875 | * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for | 1925 | * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for |
1876 | * bus layer usage. | 1926 | * bus layer usage. |
@@ -1880,32 +1930,40 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
1880 | /* bit mask of data length chopped from the previous packet */ | 1930 | /* bit mask of data length chopped from the previous packet */ |
1881 | #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff | 1931 | #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff |
1882 | 1932 | ||
1883 | static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, | 1933 | static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, |
1884 | struct sk_buff_head *pktq, | 1934 | struct sk_buff_head *pktq, |
1885 | struct sk_buff *pkt, uint chan) | 1935 | struct sk_buff *pkt, u16 total_len) |
1886 | { | 1936 | { |
1937 | struct brcmf_sdio_dev *sdiodev; | ||
1887 | struct sk_buff *pkt_pad; | 1938 | struct sk_buff *pkt_pad; |
1888 | u16 tail_pad, tail_chop, sg_align; | 1939 | u16 tail_pad, tail_chop, chain_pad; |
1889 | unsigned int blksize; | 1940 | unsigned int blksize; |
1890 | u8 *dat_buf; | 1941 | bool lastfrm; |
1891 | int ntail; | 1942 | int ntail, ret; |
1892 | 1943 | ||
1944 | sdiodev = bus->sdiodev; | ||
1893 | blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; | 1945 | blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; |
1894 | sg_align = 4; | ||
1895 | if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4) | ||
1896 | sg_align = sdiodev->pdata->sd_sgentry_align; | ||
1897 | /* sg entry alignment should be a divisor of block size */ | 1946 | /* sg entry alignment should be a divisor of block size */ |
1898 | WARN_ON(blksize % sg_align); | 1947 | WARN_ON(blksize % bus->sgentry_align); |
1899 | 1948 | ||
1900 | /* Check tail padding */ | 1949 | /* Check tail padding */ |
1901 | pkt_pad = NULL; | 1950 | lastfrm = skb_queue_is_last(pktq, pkt); |
1902 | tail_chop = pkt->len % sg_align; | 1951 | tail_pad = 0; |
1903 | tail_pad = sg_align - tail_chop; | 1952 | tail_chop = pkt->len % bus->sgentry_align; |
1904 | tail_pad += blksize - (pkt->len + tail_pad) % blksize; | 1953 | if (tail_chop) |
1954 | tail_pad = bus->sgentry_align - tail_chop; | ||
1955 | chain_pad = (total_len + tail_pad) % blksize; | ||
1956 | if (lastfrm && chain_pad) | ||
1957 | tail_pad += blksize - chain_pad; | ||
1905 | if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { | 1958 | if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { |
1906 | pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | 1959 | pkt_pad = bus->txglom_sgpad; |
1960 | if (pkt_pad == NULL) | ||
1961 | brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | ||
1907 | if (pkt_pad == NULL) | 1962 | if (pkt_pad == NULL) |
1908 | return -ENOMEM; | 1963 | return -ENOMEM; |
1964 | ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad); | ||
1965 | if (unlikely(ret < 0)) | ||
1966 | return ret; | ||
1909 | memcpy(pkt_pad->data, | 1967 | memcpy(pkt_pad->data, |
1910 | pkt->data + pkt->len - tail_chop, | 1968 | pkt->data + pkt->len - tail_chop, |
1911 | tail_chop); | 1969 | tail_chop); |
@@ -1920,14 +1978,10 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, | |||
1920 | return -ENOMEM; | 1978 | return -ENOMEM; |
1921 | if (skb_linearize(pkt)) | 1979 | if (skb_linearize(pkt)) |
1922 | return -ENOMEM; | 1980 | return -ENOMEM; |
1923 | dat_buf = (u8 *)(pkt->data); | ||
1924 | __skb_put(pkt, tail_pad); | 1981 | __skb_put(pkt, tail_pad); |
1925 | } | 1982 | } |
1926 | 1983 | ||
1927 | if (pkt_pad) | 1984 | return tail_pad; |
1928 | return pkt->len + tail_chop; | ||
1929 | else | ||
1930 | return pkt->len - tail_pad; | ||
1931 | } | 1985 | } |
1932 | 1986 | ||
1933 | /** | 1987 | /** |
@@ -1946,58 +2000,66 @@ static int | |||
1946 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | 2000 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
1947 | uint chan) | 2001 | uint chan) |
1948 | { | 2002 | { |
1949 | u16 head_pad, head_align; | 2003 | u16 head_pad, total_len; |
1950 | struct sk_buff *pkt_next; | 2004 | struct sk_buff *pkt_next; |
1951 | u8 *dat_buf; | 2005 | u8 txseq; |
1952 | int err; | 2006 | int ret; |
1953 | struct brcmf_sdio_hdrinfo hd_info = {0}; | 2007 | struct brcmf_sdio_hdrinfo hd_info = {0}; |
1954 | 2008 | ||
1955 | /* SDIO ADMA requires at least 32 bit alignment */ | 2009 | txseq = bus->tx_seq; |
1956 | head_align = 4; | 2010 | total_len = 0; |
1957 | if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) | 2011 | skb_queue_walk(pktq, pkt_next) { |
1958 | head_align = bus->sdiodev->pdata->sd_head_align; | 2012 | /* alignment packet inserted in previous |
2013 | * loop cycle can be skipped as it is | ||
2014 | * already properly aligned and does not | ||
2015 | * need an sdpcm header. | ||
2016 | */ | ||
2017 | if (*(u32 *)(pkt_next->cb) & ALIGN_SKB_FLAG) | ||
2018 | continue; | ||
1959 | 2019 | ||
1960 | pkt_next = pktq->next; | 2020 | /* align packet data pointer */ |
1961 | dat_buf = (u8 *)(pkt_next->data); | 2021 | ret = brcmf_sdio_txpkt_hdalign(bus, pkt_next); |
2022 | if (ret < 0) | ||
2023 | return ret; | ||
2024 | head_pad = (u16)ret; | ||
2025 | if (head_pad) | ||
2026 | memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen); | ||
1962 | 2027 | ||
1963 | /* Check head padding */ | 2028 | total_len += pkt_next->len; |
1964 | head_pad = ((unsigned long)dat_buf % head_align); | ||
1965 | if (head_pad) { | ||
1966 | if (skb_headroom(pkt_next) < head_pad) { | ||
1967 | bus->sdiodev->bus_if->tx_realloc++; | ||
1968 | head_pad = 0; | ||
1969 | if (skb_cow(pkt_next, head_pad)) | ||
1970 | return -ENOMEM; | ||
1971 | } | ||
1972 | skb_push(pkt_next, head_pad); | ||
1973 | dat_buf = (u8 *)(pkt_next->data); | ||
1974 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); | ||
1975 | } | ||
1976 | 2029 | ||
1977 | if (bus->sdiodev->sg_support && pktq->qlen > 1) { | ||
1978 | err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq, | ||
1979 | pkt_next, chan); | ||
1980 | if (err < 0) | ||
1981 | return err; | ||
1982 | hd_info.len = (u16)err; | ||
1983 | } else { | ||
1984 | hd_info.len = pkt_next->len; | 2030 | hd_info.len = pkt_next->len; |
1985 | } | 2031 | hd_info.lastfrm = skb_queue_is_last(pktq, pkt_next); |
1986 | 2032 | if (bus->txglom && pktq->qlen > 1) { | |
1987 | hd_info.channel = chan; | 2033 | ret = brcmf_sdio_txpkt_prep_sg(bus, pktq, |
1988 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; | 2034 | pkt_next, total_len); |
1989 | 2035 | if (ret < 0) | |
1990 | /* Now fill the header */ | 2036 | return ret; |
1991 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); | 2037 | hd_info.tail_pad = (u16)ret; |
1992 | 2038 | total_len += (u16)ret; | |
1993 | if (BRCMF_BYTES_ON() && | 2039 | } |
1994 | ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || | ||
1995 | (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) | ||
1996 | brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n"); | ||
1997 | else if (BRCMF_HDRS_ON()) | ||
1998 | brcmf_dbg_hex_dump(true, pkt_next, head_pad + bus->tx_hdrlen, | ||
1999 | "Tx Header:\n"); | ||
2000 | 2040 | ||
2041 | hd_info.channel = chan; | ||
2042 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; | ||
2043 | hd_info.seq_num = txseq++; | ||
2044 | |||
2045 | /* Now fill the header */ | ||
2046 | brcmf_sdio_hdpack(bus, pkt_next->data, &hd_info); | ||
2047 | |||
2048 | if (BRCMF_BYTES_ON() && | ||
2049 | ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || | ||
2050 | (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) | ||
2051 | brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, | ||
2052 | "Tx Frame:\n"); | ||
2053 | else if (BRCMF_HDRS_ON()) | ||
2054 | brcmf_dbg_hex_dump(true, pkt_next, | ||
2055 | head_pad + bus->tx_hdrlen, | ||
2056 | "Tx Header:\n"); | ||
2057 | } | ||
2058 | /* Hardware length tag of the first packet should be total | ||
2059 | * length of the chain (including padding) | ||
2060 | */ | ||
2061 | if (bus->txglom) | ||
2062 | brcmf_sdio_update_hwhdr(pktq->next->data, total_len); | ||
2001 | return 0; | 2063 | return 0; |
2002 | } | 2064 | } |
2003 | 2065 | ||
@@ -2015,6 +2077,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) | |||
2015 | { | 2077 | { |
2016 | u8 *hdr; | 2078 | u8 *hdr; |
2017 | u32 dat_offset; | 2079 | u32 dat_offset; |
2080 | u16 tail_pad; | ||
2018 | u32 dummy_flags, chop_len; | 2081 | u32 dummy_flags, chop_len; |
2019 | struct sk_buff *pkt_next, *tmp, *pkt_prev; | 2082 | struct sk_buff *pkt_next, *tmp, *pkt_prev; |
2020 | 2083 | ||
@@ -2024,42 +2087,42 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) | |||
2024 | chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK; | 2087 | chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK; |
2025 | if (chop_len) { | 2088 | if (chop_len) { |
2026 | pkt_prev = pkt_next->prev; | 2089 | pkt_prev = pkt_next->prev; |
2027 | memcpy(pkt_prev->data + pkt_prev->len, | ||
2028 | pkt_next->data, chop_len); | ||
2029 | skb_put(pkt_prev, chop_len); | 2090 | skb_put(pkt_prev, chop_len); |
2030 | } | 2091 | } |
2031 | __skb_unlink(pkt_next, pktq); | 2092 | __skb_unlink(pkt_next, pktq); |
2032 | brcmu_pkt_buf_free_skb(pkt_next); | 2093 | brcmu_pkt_buf_free_skb(pkt_next); |
2033 | } else { | 2094 | } else { |
2034 | hdr = pkt_next->data + SDPCM_HWHDR_LEN; | 2095 | hdr = pkt_next->data + bus->tx_hdrlen - SDPCM_SWHDR_LEN; |
2035 | dat_offset = le32_to_cpu(*(__le32 *)hdr); | 2096 | dat_offset = le32_to_cpu(*(__le32 *)hdr); |
2036 | dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >> | 2097 | dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >> |
2037 | SDPCM_DOFFSET_SHIFT; | 2098 | SDPCM_DOFFSET_SHIFT; |
2038 | skb_pull(pkt_next, dat_offset); | 2099 | skb_pull(pkt_next, dat_offset); |
2100 | if (bus->txglom) { | ||
2101 | tail_pad = le16_to_cpu(*(__le16 *)(hdr - 2)); | ||
2102 | skb_trim(pkt_next, pkt_next->len - tail_pad); | ||
2103 | } | ||
2039 | } | 2104 | } |
2040 | } | 2105 | } |
2041 | } | 2106 | } |
2042 | 2107 | ||
2043 | /* Writes a HW/SW header into the packet and sends it. */ | 2108 | /* Writes a HW/SW header into the packet and sends it. */ |
2044 | /* Assumes: (a) header space already there, (b) caller holds lock */ | 2109 | /* Assumes: (a) header space already there, (b) caller holds lock */ |
2045 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | 2110 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
2046 | uint chan) | 2111 | uint chan) |
2047 | { | 2112 | { |
2048 | int ret; | 2113 | int ret; |
2049 | int i; | 2114 | int i; |
2050 | struct sk_buff_head localq; | 2115 | struct sk_buff *pkt_next, *tmp; |
2051 | 2116 | ||
2052 | brcmf_dbg(TRACE, "Enter\n"); | 2117 | brcmf_dbg(TRACE, "Enter\n"); |
2053 | 2118 | ||
2054 | __skb_queue_head_init(&localq); | 2119 | ret = brcmf_sdio_txpkt_prep(bus, pktq, chan); |
2055 | __skb_queue_tail(&localq, pkt); | ||
2056 | ret = brcmf_sdio_txpkt_prep(bus, &localq, chan); | ||
2057 | if (ret) | 2120 | if (ret) |
2058 | goto done; | 2121 | goto done; |
2059 | 2122 | ||
2060 | sdio_claim_host(bus->sdiodev->func[1]); | 2123 | sdio_claim_host(bus->sdiodev->func[1]); |
2061 | ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 2124 | ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
2062 | SDIO_FUNC_2, F2SYNC, &localq); | 2125 | SDIO_FUNC_2, F2SYNC, pktq); |
2063 | bus->sdcnt.f2txdata++; | 2126 | bus->sdcnt.f2txdata++; |
2064 | 2127 | ||
2065 | if (ret < 0) { | 2128 | if (ret < 0) { |
@@ -2083,42 +2146,56 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
2083 | if ((hi == 0) && (lo == 0)) | 2146 | if ((hi == 0) && (lo == 0)) |
2084 | break; | 2147 | break; |
2085 | } | 2148 | } |
2086 | |||
2087 | } | 2149 | } |
2088 | sdio_release_host(bus->sdiodev->func[1]); | 2150 | sdio_release_host(bus->sdiodev->func[1]); |
2089 | if (ret == 0) | ||
2090 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; | ||
2091 | 2151 | ||
2092 | done: | 2152 | done: |
2093 | brcmf_sdio_txpkt_postp(bus, &localq); | 2153 | brcmf_sdio_txpkt_postp(bus, pktq); |
2094 | __skb_dequeue_tail(&localq); | 2154 | if (ret == 0) |
2095 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0); | 2155 | bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP; |
2156 | skb_queue_walk_safe(pktq, pkt_next, tmp) { | ||
2157 | __skb_unlink(pkt_next, pktq); | ||
2158 | brcmf_txcomplete(bus->sdiodev->dev, pkt_next, ret == 0); | ||
2159 | } | ||
2096 | return ret; | 2160 | return ret; |
2097 | } | 2161 | } |
2098 | 2162 | ||
2099 | static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | 2163 | static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) |
2100 | { | 2164 | { |
2101 | struct sk_buff *pkt; | 2165 | struct sk_buff *pkt; |
2166 | struct sk_buff_head pktq; | ||
2102 | u32 intstatus = 0; | 2167 | u32 intstatus = 0; |
2103 | int ret = 0, prec_out; | 2168 | int ret = 0, prec_out, i; |
2104 | uint cnt = 0; | 2169 | uint cnt = 0; |
2105 | u8 tx_prec_map; | 2170 | u8 tx_prec_map, pkt_num; |
2106 | 2171 | ||
2107 | brcmf_dbg(TRACE, "Enter\n"); | 2172 | brcmf_dbg(TRACE, "Enter\n"); |
2108 | 2173 | ||
2109 | tx_prec_map = ~bus->flowcontrol; | 2174 | tx_prec_map = ~bus->flowcontrol; |
2110 | 2175 | ||
2111 | /* Send frames until the limit or some other event */ | 2176 | /* Send frames until the limit or some other event */ |
2112 | for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) { | 2177 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { |
2178 | pkt_num = 1; | ||
2179 | __skb_queue_head_init(&pktq); | ||
2180 | if (bus->txglom) | ||
2181 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, | ||
2182 | brcmf_sdio_txglomsz); | ||
2183 | pkt_num = min_t(u32, pkt_num, | ||
2184 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); | ||
2113 | spin_lock_bh(&bus->txqlock); | 2185 | spin_lock_bh(&bus->txqlock); |
2114 | pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); | 2186 | for (i = 0; i < pkt_num; i++) { |
2115 | if (pkt == NULL) { | 2187 | pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, |
2116 | spin_unlock_bh(&bus->txqlock); | 2188 | &prec_out); |
2117 | break; | 2189 | if (pkt == NULL) |
2190 | break; | ||
2191 | __skb_queue_tail(&pktq, pkt); | ||
2118 | } | 2192 | } |
2119 | spin_unlock_bh(&bus->txqlock); | 2193 | spin_unlock_bh(&bus->txqlock); |
2194 | if (i == 0) | ||
2195 | break; | ||
2120 | 2196 | ||
2121 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); | 2197 | ret = brcmf_sdbrcm_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); |
2198 | cnt += i; | ||
2122 | 2199 | ||
2123 | /* In poll mode, need to check for other events */ | 2200 | /* In poll mode, need to check for other events */ |
2124 | if (!bus->intr && cnt) { | 2201 | if (!bus->intr && cnt) { |
@@ -2665,7 +2742,7 @@ static int | |||
2665 | brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | 2742 | brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) |
2666 | { | 2743 | { |
2667 | u8 *frame; | 2744 | u8 *frame; |
2668 | u16 len; | 2745 | u16 len, pad; |
2669 | uint retries = 0; | 2746 | uint retries = 0; |
2670 | u8 doff = 0; | 2747 | u8 doff = 0; |
2671 | int ret = -1; | 2748 | int ret = -1; |
@@ -2681,28 +2758,26 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2681 | len = (msglen += bus->tx_hdrlen); | 2758 | len = (msglen += bus->tx_hdrlen); |
2682 | 2759 | ||
2683 | /* Add alignment padding (optional for ctl frames) */ | 2760 | /* Add alignment padding (optional for ctl frames) */ |
2684 | doff = ((unsigned long)frame % BRCMF_SDALIGN); | 2761 | doff = ((unsigned long)frame % bus->head_align); |
2685 | if (doff) { | 2762 | if (doff) { |
2686 | frame -= doff; | 2763 | frame -= doff; |
2687 | len += doff; | 2764 | len += doff; |
2688 | msglen += doff; | 2765 | msglen += doff; |
2689 | memset(frame, 0, doff + bus->tx_hdrlen); | 2766 | memset(frame, 0, doff + bus->tx_hdrlen); |
2690 | } | 2767 | } |
2691 | /* precondition: doff < BRCMF_SDALIGN */ | 2768 | /* precondition: doff < bus->head_align */ |
2692 | doff += bus->tx_hdrlen; | 2769 | doff += bus->tx_hdrlen; |
2693 | 2770 | ||
2694 | /* Round send length to next SDIO block */ | 2771 | /* Round send length to next SDIO block */ |
2772 | pad = 0; | ||
2695 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { | 2773 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { |
2696 | u16 pad = bus->blocksize - (len % bus->blocksize); | 2774 | pad = bus->blocksize - (len % bus->blocksize); |
2697 | if ((pad <= bus->roundup) && (pad < bus->blocksize)) | 2775 | if ((pad > bus->roundup) || (pad >= bus->blocksize)) |
2698 | len += pad; | 2776 | pad = 0; |
2699 | } else if (len % BRCMF_SDALIGN) { | 2777 | } else if (len % bus->head_align) { |
2700 | len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); | 2778 | pad = bus->head_align - (len % bus->head_align); |
2701 | } | 2779 | } |
2702 | 2780 | len += pad; | |
2703 | /* Satisfy length-alignment requirements */ | ||
2704 | if (len & (ALIGNMENT - 1)) | ||
2705 | len = roundup(len, ALIGNMENT); | ||
2706 | 2781 | ||
2707 | /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ | 2782 | /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ |
2708 | 2783 | ||
@@ -2714,8 +2789,14 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2714 | hd_info.len = (u16)msglen; | 2789 | hd_info.len = (u16)msglen; |
2715 | hd_info.channel = SDPCM_CONTROL_CHANNEL; | 2790 | hd_info.channel = SDPCM_CONTROL_CHANNEL; |
2716 | hd_info.dat_offset = doff; | 2791 | hd_info.dat_offset = doff; |
2792 | hd_info.seq_num = bus->tx_seq; | ||
2793 | hd_info.lastfrm = true; | ||
2794 | hd_info.tail_pad = pad; | ||
2717 | brcmf_sdio_hdpack(bus, frame, &hd_info); | 2795 | brcmf_sdio_hdpack(bus, frame, &hd_info); |
2718 | 2796 | ||
2797 | if (bus->txglom) | ||
2798 | brcmf_sdio_update_hwhdr(frame, len); | ||
2799 | |||
2719 | if (!data_ok(bus)) { | 2800 | if (!data_ok(bus)) { |
2720 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", | 2801 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", |
2721 | bus->tx_max, bus->tx_seq); | 2802 | bus->tx_max, bus->tx_seq); |
@@ -3425,6 +3506,65 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | |||
3425 | return ret; | 3506 | return ret; |
3426 | } | 3507 | } |
3427 | 3508 | ||
3509 | static int brcmf_sdbrcm_bus_preinit(struct device *dev) | ||
3510 | { | ||
3511 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
3512 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
3513 | struct brcmf_sdio *bus = sdiodev->bus; | ||
3514 | uint pad_size; | ||
3515 | u32 value; | ||
3516 | u8 idx; | ||
3517 | int err; | ||
3518 | |||
3519 | /* the commands below use the terms tx and rx from | ||
3520 | * a device perspective, ie. bus:txglom affects the | ||
3521 | * bus transfers from device to host. | ||
3522 | */ | ||
3523 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
3524 | if (bus->ci->c_inf[idx].rev < 12) { | ||
3525 | /* for sdio core rev < 12, disable txgloming */ | ||
3526 | value = 0; | ||
3527 | err = brcmf_iovar_data_set(dev, "bus:txglom", &value, | ||
3528 | sizeof(u32)); | ||
3529 | } else { | ||
3530 | /* otherwise, set txglomalign */ | ||
3531 | value = 4; | ||
3532 | if (sdiodev->pdata) | ||
3533 | value = sdiodev->pdata->sd_sgentry_align; | ||
3534 | /* SDIO ADMA requires at least 32 bit alignment */ | ||
3535 | value = max_t(u32, value, 4); | ||
3536 | err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, | ||
3537 | sizeof(u32)); | ||
3538 | } | ||
3539 | |||
3540 | if (err < 0) | ||
3541 | goto done; | ||
3542 | |||
3543 | bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; | ||
3544 | if (sdiodev->sg_support) { | ||
3545 | bus->txglom = false; | ||
3546 | value = 1; | ||
3547 | pad_size = bus->sdiodev->func[2]->cur_blksize << 1; | ||
3548 | bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size); | ||
3549 | if (!bus->txglom_sgpad) | ||
3550 | brcmf_err("allocating txglom padding skb failed, reduced performance\n"); | ||
3551 | |||
3552 | err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom", | ||
3553 | &value, sizeof(u32)); | ||
3554 | if (err < 0) { | ||
3555 | /* bus:rxglom is allowed to fail */ | ||
3556 | err = 0; | ||
3557 | } else { | ||
3558 | bus->txglom = true; | ||
3559 | bus->tx_hdrlen += SDPCM_HWEXT_LEN; | ||
3560 | } | ||
3561 | } | ||
3562 | brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); | ||
3563 | |||
3564 | done: | ||
3565 | return err; | ||
3566 | } | ||
3567 | |||
3428 | static int brcmf_sdbrcm_bus_init(struct device *dev) | 3568 | static int brcmf_sdbrcm_bus_init(struct device *dev) |
3429 | { | 3569 | { |
3430 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 3570 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
@@ -3673,7 +3813,7 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) | |||
3673 | if (bus->sdiodev->bus_if->maxctl) { | 3813 | if (bus->sdiodev->bus_if->maxctl) { |
3674 | bus->rxblen = | 3814 | bus->rxblen = |
3675 | roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN), | 3815 | roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN), |
3676 | ALIGNMENT) + BRCMF_SDALIGN; | 3816 | ALIGNMENT) + bus->head_align; |
3677 | bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); | 3817 | bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); |
3678 | if (!(bus->rxbuf)) | 3818 | if (!(bus->rxbuf)) |
3679 | return false; | 3819 | return false; |
@@ -3774,9 +3914,13 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3774 | 3914 | ||
3775 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); | 3915 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); |
3776 | 3916 | ||
3917 | /* allocate header buffer */ | ||
3918 | bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL); | ||
3919 | if (!bus->hdrbuf) | ||
3920 | return false; | ||
3777 | /* Locate an appropriately-aligned portion of hdrbuf */ | 3921 | /* Locate an appropriately-aligned portion of hdrbuf */ |
3778 | bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], | 3922 | bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], |
3779 | BRCMF_SDALIGN); | 3923 | bus->head_align); |
3780 | 3924 | ||
3781 | /* Set the poll and/or interrupt flags */ | 3925 | /* Set the poll and/or interrupt flags */ |
3782 | bus->intr = true; | 3926 | bus->intr = true; |
@@ -3895,8 +4039,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | |||
3895 | brcmf_sdbrcm_release_dongle(bus); | 4039 | brcmf_sdbrcm_release_dongle(bus); |
3896 | } | 4040 | } |
3897 | 4041 | ||
4042 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); | ||
3898 | brcmf_sdbrcm_release_malloc(bus); | 4043 | brcmf_sdbrcm_release_malloc(bus); |
3899 | 4044 | kfree(bus->hdrbuf); | |
3900 | kfree(bus); | 4045 | kfree(bus); |
3901 | } | 4046 | } |
3902 | 4047 | ||
@@ -3905,6 +4050,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | |||
3905 | 4050 | ||
3906 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | 4051 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { |
3907 | .stop = brcmf_sdbrcm_bus_stop, | 4052 | .stop = brcmf_sdbrcm_bus_stop, |
4053 | .preinit = brcmf_sdbrcm_bus_preinit, | ||
3908 | .init = brcmf_sdbrcm_bus_init, | 4054 | .init = brcmf_sdbrcm_bus_init, |
3909 | .txdata = brcmf_sdbrcm_bus_txdata, | 4055 | .txdata = brcmf_sdbrcm_bus_txdata, |
3910 | .txctl = brcmf_sdbrcm_bus_txctl, | 4056 | .txctl = brcmf_sdbrcm_bus_txctl, |
@@ -3916,10 +4062,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3916 | { | 4062 | { |
3917 | int ret; | 4063 | int ret; |
3918 | struct brcmf_sdio *bus; | 4064 | struct brcmf_sdio *bus; |
3919 | struct brcmf_bus_dcmd *dlst; | ||
3920 | u32 dngl_txglom; | ||
3921 | u32 txglomalign = 0; | ||
3922 | u8 idx; | ||
3923 | 4065 | ||
3924 | brcmf_dbg(TRACE, "Enter\n"); | 4066 | brcmf_dbg(TRACE, "Enter\n"); |
3925 | 4067 | ||
@@ -3939,6 +4081,18 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3939 | bus->txminmax = BRCMF_TXMINMAX; | 4081 | bus->txminmax = BRCMF_TXMINMAX; |
3940 | bus->tx_seq = SDPCM_SEQ_WRAP - 1; | 4082 | bus->tx_seq = SDPCM_SEQ_WRAP - 1; |
3941 | 4083 | ||
4084 | /* platform specific configuration: | ||
4085 | * alignments must be at least 4 bytes for ADMA | ||
4086 | */ | ||
4087 | bus->head_align = ALIGNMENT; | ||
4088 | bus->sgentry_align = ALIGNMENT; | ||
4089 | if (sdiodev->pdata) { | ||
4090 | if (sdiodev->pdata->sd_head_align > ALIGNMENT) | ||
4091 | bus->head_align = sdiodev->pdata->sd_head_align; | ||
4092 | if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT) | ||
4093 | bus->sgentry_align = sdiodev->pdata->sd_sgentry_align; | ||
4094 | } | ||
4095 | |||
3942 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | 4096 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); |
3943 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); | 4097 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); |
3944 | if (bus->brcmf_wq == NULL) { | 4098 | if (bus->brcmf_wq == NULL) { |
@@ -3983,7 +4137,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3983 | bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; | 4137 | bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; |
3984 | 4138 | ||
3985 | /* Attach to the common layer, reserve hdr space */ | 4139 | /* Attach to the common layer, reserve hdr space */ |
3986 | ret = brcmf_attach(bus->tx_hdrlen, bus->sdiodev->dev); | 4140 | ret = brcmf_attach(bus->sdiodev->dev); |
3987 | if (ret != 0) { | 4141 | if (ret != 0) { |
3988 | brcmf_err("brcmf_attach failed\n"); | 4142 | brcmf_err("brcmf_attach failed\n"); |
3989 | goto fail; | 4143 | goto fail; |
@@ -4003,30 +4157,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4003 | brcmf_sdio_debugfs_create(bus); | 4157 | brcmf_sdio_debugfs_create(bus); |
4004 | brcmf_dbg(INFO, "completed!!\n"); | 4158 | brcmf_dbg(INFO, "completed!!\n"); |
4005 | 4159 | ||
4006 | /* sdio bus core specific dcmd */ | ||
4007 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
4008 | dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL); | ||
4009 | if (dlst) { | ||
4010 | if (bus->ci->c_inf[idx].rev < 12) { | ||
4011 | /* for sdio core rev < 12, disable txgloming */ | ||
4012 | dngl_txglom = 0; | ||
4013 | dlst->name = "bus:txglom"; | ||
4014 | dlst->param = (char *)&dngl_txglom; | ||
4015 | dlst->param_len = sizeof(u32); | ||
4016 | } else { | ||
4017 | /* otherwise, set txglomalign */ | ||
4018 | if (sdiodev->pdata) | ||
4019 | txglomalign = sdiodev->pdata->sd_sgentry_align; | ||
4020 | /* SDIO ADMA requires at least 32 bit alignment */ | ||
4021 | if (txglomalign < 4) | ||
4022 | txglomalign = 4; | ||
4023 | dlst->name = "bus:txglomalign"; | ||
4024 | dlst->param = (char *)&txglomalign; | ||
4025 | dlst->param_len = sizeof(u32); | ||
4026 | } | ||
4027 | list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); | ||
4028 | } | ||
4029 | |||
4030 | /* if firmware path present try to download and bring up bus */ | 4160 | /* if firmware path present try to download and bring up bus */ |
4031 | ret = brcmf_bus_start(bus->sdiodev->dev); | 4161 | ret = brcmf_bus_start(bus->sdiodev->dev); |
4032 | if (ret != 0) { | 4162 | if (ret != 0) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 14bc24dc5bae..51b53a73d074 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h | |||
@@ -122,6 +122,52 @@ enum brcmf_fweh_event_code { | |||
122 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 | 122 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 |
123 | #define BRCMF_EVENT_MSG_GROUP 0x04 | 123 | #define BRCMF_EVENT_MSG_GROUP 0x04 |
124 | 124 | ||
125 | /* status field values in struct brcmf_event_msg */ | ||
126 | #define BRCMF_E_STATUS_SUCCESS 0 | ||
127 | #define BRCMF_E_STATUS_FAIL 1 | ||
128 | #define BRCMF_E_STATUS_TIMEOUT 2 | ||
129 | #define BRCMF_E_STATUS_NO_NETWORKS 3 | ||
130 | #define BRCMF_E_STATUS_ABORT 4 | ||
131 | #define BRCMF_E_STATUS_NO_ACK 5 | ||
132 | #define BRCMF_E_STATUS_UNSOLICITED 6 | ||
133 | #define BRCMF_E_STATUS_ATTEMPT 7 | ||
134 | #define BRCMF_E_STATUS_PARTIAL 8 | ||
135 | #define BRCMF_E_STATUS_NEWSCAN 9 | ||
136 | #define BRCMF_E_STATUS_NEWASSOC 10 | ||
137 | #define BRCMF_E_STATUS_11HQUIET 11 | ||
138 | #define BRCMF_E_STATUS_SUPPRESS 12 | ||
139 | #define BRCMF_E_STATUS_NOCHANS 13 | ||
140 | #define BRCMF_E_STATUS_CS_ABORT 15 | ||
141 | #define BRCMF_E_STATUS_ERROR 16 | ||
142 | |||
143 | /* reason field values in struct brcmf_event_msg */ | ||
144 | #define BRCMF_E_REASON_INITIAL_ASSOC 0 | ||
145 | #define BRCMF_E_REASON_LOW_RSSI 1 | ||
146 | #define BRCMF_E_REASON_DEAUTH 2 | ||
147 | #define BRCMF_E_REASON_DISASSOC 3 | ||
148 | #define BRCMF_E_REASON_BCNS_LOST 4 | ||
149 | #define BRCMF_E_REASON_MINTXRATE 9 | ||
150 | #define BRCMF_E_REASON_TXFAIL 10 | ||
151 | |||
152 | #define BRCMF_E_REASON_LINK_BSSCFG_DIS 4 | ||
153 | #define BRCMF_E_REASON_FAST_ROAM_FAILED 5 | ||
154 | #define BRCMF_E_REASON_DIRECTED_ROAM 6 | ||
155 | #define BRCMF_E_REASON_TSPEC_REJECTED 7 | ||
156 | #define BRCMF_E_REASON_BETTER_AP 8 | ||
157 | |||
158 | /* action field values for brcmf_ifevent */ | ||
159 | #define BRCMF_E_IF_ADD 1 | ||
160 | #define BRCMF_E_IF_DEL 2 | ||
161 | #define BRCMF_E_IF_CHANGE 3 | ||
162 | |||
163 | /* flag field values for brcmf_ifevent */ | ||
164 | #define BRCMF_E_IF_FLAG_NOIF 1 | ||
165 | |||
166 | /* role field values for brcmf_ifevent */ | ||
167 | #define BRCMF_E_IF_ROLE_STA 0 | ||
168 | #define BRCMF_E_IF_ROLE_AP 1 | ||
169 | #define BRCMF_E_IF_ROLE_WDS 2 | ||
170 | |||
125 | /** | 171 | /** |
126 | * definitions for event packet validation. | 172 | * definitions for event packet validation. |
127 | */ | 173 | */ |
@@ -160,6 +206,14 @@ struct brcmf_event_msg { | |||
160 | u8 bsscfgidx; | 206 | u8 bsscfgidx; |
161 | }; | 207 | }; |
162 | 208 | ||
209 | struct brcmf_if_event { | ||
210 | u8 ifidx; | ||
211 | u8 action; | ||
212 | u8 flags; | ||
213 | u8 bssidx; | ||
214 | u8 role; | ||
215 | }; | ||
216 | |||
163 | typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, | 217 | typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, |
164 | const struct brcmf_event_msg *evtmsg, | 218 | const struct brcmf_event_msg *evtmsg, |
165 | void *data); | 219 | void *data); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 04f395930d86..b72d3395499a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "dhd_dbg.h" | 27 | #include "dhd_dbg.h" |
28 | #include "tracepoint.h" | 28 | #include "tracepoint.h" |
29 | #include "fwil.h" | 29 | #include "fwil.h" |
30 | #include "proto.h" | ||
30 | 31 | ||
31 | 32 | ||
32 | #define MAX_HEX_DUMP_LEN 64 | 33 | #define MAX_HEX_DUMP_LEN 64 |
@@ -46,11 +47,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | |||
46 | if (data != NULL) | 47 | if (data != NULL) |
47 | len = min_t(uint, len, BRCMF_DCMD_MAXLEN); | 48 | len = min_t(uint, len, BRCMF_DCMD_MAXLEN); |
48 | if (set) | 49 | if (set) |
49 | err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data, | 50 | err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); |
50 | len); | ||
51 | else | 51 | else |
52 | err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data, | 52 | err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); |
53 | len); | ||
54 | 53 | ||
55 | if (err >= 0) | 54 | if (err >= 0) |
56 | err = 0; | 55 | err = 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 16eb8202fb1e..77eae86e55c2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h | |||
@@ -17,6 +17,67 @@ | |||
17 | #ifndef _fwil_h_ | 17 | #ifndef _fwil_h_ |
18 | #define _fwil_h_ | 18 | #define _fwil_h_ |
19 | 19 | ||
20 | /******************************************************************************* | ||
21 | * Dongle command codes that are interpreted by firmware | ||
22 | ******************************************************************************/ | ||
23 | #define BRCMF_C_GET_VERSION 1 | ||
24 | #define BRCMF_C_UP 2 | ||
25 | #define BRCMF_C_DOWN 3 | ||
26 | #define BRCMF_C_SET_PROMISC 10 | ||
27 | #define BRCMF_C_GET_RATE 12 | ||
28 | #define BRCMF_C_GET_INFRA 19 | ||
29 | #define BRCMF_C_SET_INFRA 20 | ||
30 | #define BRCMF_C_GET_AUTH 21 | ||
31 | #define BRCMF_C_SET_AUTH 22 | ||
32 | #define BRCMF_C_GET_BSSID 23 | ||
33 | #define BRCMF_C_GET_SSID 25 | ||
34 | #define BRCMF_C_SET_SSID 26 | ||
35 | #define BRCMF_C_TERMINATED 28 | ||
36 | #define BRCMF_C_GET_CHANNEL 29 | ||
37 | #define BRCMF_C_SET_CHANNEL 30 | ||
38 | #define BRCMF_C_GET_SRL 31 | ||
39 | #define BRCMF_C_SET_SRL 32 | ||
40 | #define BRCMF_C_GET_LRL 33 | ||
41 | #define BRCMF_C_SET_LRL 34 | ||
42 | #define BRCMF_C_GET_RADIO 37 | ||
43 | #define BRCMF_C_SET_RADIO 38 | ||
44 | #define BRCMF_C_GET_PHYTYPE 39 | ||
45 | #define BRCMF_C_SET_KEY 45 | ||
46 | #define BRCMF_C_SET_PASSIVE_SCAN 49 | ||
47 | #define BRCMF_C_SCAN 50 | ||
48 | #define BRCMF_C_SCAN_RESULTS 51 | ||
49 | #define BRCMF_C_DISASSOC 52 | ||
50 | #define BRCMF_C_REASSOC 53 | ||
51 | #define BRCMF_C_SET_ROAM_TRIGGER 55 | ||
52 | #define BRCMF_C_SET_ROAM_DELTA 57 | ||
53 | #define BRCMF_C_GET_BCNPRD 75 | ||
54 | #define BRCMF_C_SET_BCNPRD 76 | ||
55 | #define BRCMF_C_GET_DTIMPRD 77 | ||
56 | #define BRCMF_C_SET_DTIMPRD 78 | ||
57 | #define BRCMF_C_SET_COUNTRY 84 | ||
58 | #define BRCMF_C_GET_PM 85 | ||
59 | #define BRCMF_C_SET_PM 86 | ||
60 | #define BRCMF_C_GET_CURR_RATESET 114 | ||
61 | #define BRCMF_C_GET_AP 117 | ||
62 | #define BRCMF_C_SET_AP 118 | ||
63 | #define BRCMF_C_GET_RSSI 127 | ||
64 | #define BRCMF_C_GET_WSEC 133 | ||
65 | #define BRCMF_C_SET_WSEC 134 | ||
66 | #define BRCMF_C_GET_PHY_NOISE 135 | ||
67 | #define BRCMF_C_GET_BSS_INFO 136 | ||
68 | #define BRCMF_C_GET_BANDLIST 140 | ||
69 | #define BRCMF_C_SET_SCB_TIMEOUT 158 | ||
70 | #define BRCMF_C_GET_PHYLIST 180 | ||
71 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 | ||
72 | #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 | ||
73 | #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 | ||
74 | #define BRCMF_C_GET_VALID_CHANNELS 217 | ||
75 | #define BRCMF_C_GET_KEY_PRIMARY 235 | ||
76 | #define BRCMF_C_SET_KEY_PRIMARY 236 | ||
77 | #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 | ||
78 | #define BRCMF_C_GET_VAR 262 | ||
79 | #define BRCMF_C_SET_VAR 263 | ||
80 | |||
20 | s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | 81 | s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); |
21 | s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | 82 | s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); |
22 | s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); | 83 | s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index ecabb04f33c3..af17a5bc8b83 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -29,6 +29,24 @@ | |||
29 | #define BRCMF_ARP_OL_HOST_AUTO_REPLY 0x00000004 | 29 | #define BRCMF_ARP_OL_HOST_AUTO_REPLY 0x00000004 |
30 | #define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008 | 30 | #define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008 |
31 | 31 | ||
32 | #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ | ||
33 | #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 | ||
34 | |||
35 | #define BRCMF_STA_ASSOC 0x10 /* Associated */ | ||
36 | |||
37 | /* size of brcmf_scan_params not including variable length array */ | ||
38 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 | ||
39 | |||
40 | /* masks for channel and ssid count */ | ||
41 | #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff | ||
42 | #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 | ||
43 | |||
44 | /* primary (ie tx) key */ | ||
45 | #define BRCMF_PRIMARY_KEY (1 << 1) | ||
46 | #define DOT11_BSSTYPE_ANY 2 | ||
47 | #define BRCMF_ESCAN_REQ_VERSION 1 | ||
48 | |||
49 | #define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ | ||
32 | 50 | ||
33 | enum brcmf_fil_p2p_if_types { | 51 | enum brcmf_fil_p2p_if_types { |
34 | BRCMF_FIL_P2P_IF_CLIENT, | 52 | BRCMF_FIL_P2P_IF_CLIENT, |
@@ -90,4 +108,290 @@ enum brcmf_tdls_manual_ep_ops { | |||
90 | BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6 | 108 | BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6 |
91 | }; | 109 | }; |
92 | 110 | ||
111 | /* Pattern matching filter. Specifies an offset within received packets to | ||
112 | * start matching, the pattern to match, the size of the pattern, and a bitmask | ||
113 | * that indicates which bits within the pattern should be matched. | ||
114 | */ | ||
115 | struct brcmf_pkt_filter_pattern_le { | ||
116 | /* | ||
117 | * Offset within received packet to start pattern matching. | ||
118 | * Offset '0' is the first byte of the ethernet header. | ||
119 | */ | ||
120 | __le32 offset; | ||
121 | /* Size of the pattern. Bitmask must be the same size.*/ | ||
122 | __le32 size_bytes; | ||
123 | /* | ||
124 | * Variable length mask and pattern data. mask starts at offset 0. | ||
125 | * Pattern immediately follows mask. | ||
126 | */ | ||
127 | u8 mask_and_pattern[1]; | ||
128 | }; | ||
129 | |||
130 | /* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ | ||
131 | struct brcmf_pkt_filter_le { | ||
132 | __le32 id; /* Unique filter id, specified by app. */ | ||
133 | __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ | ||
134 | __le32 negate_match; /* Negate the result of filter matches */ | ||
135 | union { /* Filter definitions */ | ||
136 | struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ | ||
137 | } u; | ||
138 | }; | ||
139 | |||
140 | /* IOVAR "pkt_filter_enable" parameter. */ | ||
141 | struct brcmf_pkt_filter_enable_le { | ||
142 | __le32 id; /* Unique filter id */ | ||
143 | __le32 enable; /* Enable/disable bool */ | ||
144 | }; | ||
145 | |||
146 | /* BSS info structure | ||
147 | * Applications MUST CHECK ie_offset field and length field to access IEs and | ||
148 | * next bss_info structure in a vector (in struct brcmf_scan_results) | ||
149 | */ | ||
150 | struct brcmf_bss_info_le { | ||
151 | __le32 version; /* version field */ | ||
152 | __le32 length; /* byte length of data in this record, | ||
153 | * starting at version and including IEs | ||
154 | */ | ||
155 | u8 BSSID[ETH_ALEN]; | ||
156 | __le16 beacon_period; /* units are Kusec */ | ||
157 | __le16 capability; /* Capability information */ | ||
158 | u8 SSID_len; | ||
159 | u8 SSID[32]; | ||
160 | struct { | ||
161 | __le32 count; /* # rates in this set */ | ||
162 | u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ | ||
163 | } rateset; /* supported rates */ | ||
164 | __le16 chanspec; /* chanspec for bss */ | ||
165 | __le16 atim_window; /* units are Kusec */ | ||
166 | u8 dtim_period; /* DTIM period */ | ||
167 | __le16 RSSI; /* receive signal strength (in dBm) */ | ||
168 | s8 phy_noise; /* noise (in dBm) */ | ||
169 | |||
170 | u8 n_cap; /* BSS is 802.11N Capable */ | ||
171 | /* 802.11N BSS Capabilities (based on HT_CAP_*): */ | ||
172 | __le32 nbss_cap; | ||
173 | u8 ctl_ch; /* 802.11N BSS control channel number */ | ||
174 | __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ | ||
175 | u8 flags; /* flags */ | ||
176 | u8 reserved[3]; /* Reserved for expansion of BSS properties */ | ||
177 | u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ | ||
178 | |||
179 | __le16 ie_offset; /* offset at which IEs start, from beginning */ | ||
180 | __le32 ie_length; /* byte length of Information Elements */ | ||
181 | __le16 SNR; /* average SNR of during frame reception */ | ||
182 | /* Add new fields here */ | ||
183 | /* variable length Information Elements */ | ||
184 | }; | ||
185 | |||
186 | struct brcm_rateset_le { | ||
187 | /* # rates in this set */ | ||
188 | __le32 count; | ||
189 | /* rates in 500kbps units w/hi bit set if basic */ | ||
190 | u8 rates[BRCMF_MAXRATES_IN_SET]; | ||
191 | }; | ||
192 | |||
193 | struct brcmf_ssid { | ||
194 | u32 SSID_len; | ||
195 | unsigned char SSID[32]; | ||
196 | }; | ||
197 | |||
198 | struct brcmf_ssid_le { | ||
199 | __le32 SSID_len; | ||
200 | unsigned char SSID[32]; | ||
201 | }; | ||
202 | |||
203 | struct brcmf_scan_params_le { | ||
204 | struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ | ||
205 | u8 bssid[ETH_ALEN]; /* default: bcast */ | ||
206 | s8 bss_type; /* default: any, | ||
207 | * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT | ||
208 | */ | ||
209 | u8 scan_type; /* flags, 0 use default */ | ||
210 | __le32 nprobes; /* -1 use default, number of probes per channel */ | ||
211 | __le32 active_time; /* -1 use default, dwell time per channel for | ||
212 | * active scanning | ||
213 | */ | ||
214 | __le32 passive_time; /* -1 use default, dwell time per channel | ||
215 | * for passive scanning | ||
216 | */ | ||
217 | __le32 home_time; /* -1 use default, dwell time for the | ||
218 | * home channel between channel scans | ||
219 | */ | ||
220 | __le32 channel_num; /* count of channels and ssids that follow | ||
221 | * | ||
222 | * low half is count of channels in | ||
223 | * channel_list, 0 means default (use all | ||
224 | * available channels) | ||
225 | * | ||
226 | * high half is entries in struct brcmf_ssid | ||
227 | * array that follows channel_list, aligned for | ||
228 | * s32 (4 bytes) meaning an odd channel count | ||
229 | * implies a 2-byte pad between end of | ||
230 | * channel_list and first ssid | ||
231 | * | ||
232 | * if ssid count is zero, single ssid in the | ||
233 | * fixed parameter portion is assumed, otherwise | ||
234 | * ssid in the fixed portion is ignored | ||
235 | */ | ||
236 | __le16 channel_list[1]; /* list of chanspecs */ | ||
237 | }; | ||
238 | |||
239 | struct brcmf_scan_results { | ||
240 | u32 buflen; | ||
241 | u32 version; | ||
242 | u32 count; | ||
243 | struct brcmf_bss_info_le bss_info_le[]; | ||
244 | }; | ||
245 | |||
246 | struct brcmf_escan_params_le { | ||
247 | __le32 version; | ||
248 | __le16 action; | ||
249 | __le16 sync_id; | ||
250 | struct brcmf_scan_params_le params_le; | ||
251 | }; | ||
252 | |||
253 | struct brcmf_escan_result_le { | ||
254 | __le32 buflen; | ||
255 | __le32 version; | ||
256 | __le16 sync_id; | ||
257 | __le16 bss_count; | ||
258 | struct brcmf_bss_info_le bss_info_le; | ||
259 | }; | ||
260 | |||
261 | #define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \ | ||
262 | sizeof(struct brcmf_bss_info_le)) | ||
263 | |||
264 | /* used for association with a specific BSSID and chanspec list */ | ||
265 | struct brcmf_assoc_params_le { | ||
266 | /* 00:00:00:00:00:00: broadcast scan */ | ||
267 | u8 bssid[ETH_ALEN]; | ||
268 | /* 0: all available channels, otherwise count of chanspecs in | ||
269 | * chanspec_list */ | ||
270 | __le32 chanspec_num; | ||
271 | /* list of chanspecs */ | ||
272 | __le16 chanspec_list[1]; | ||
273 | }; | ||
274 | |||
275 | /* used for join with or without a specific bssid and channel list */ | ||
276 | struct brcmf_join_params { | ||
277 | struct brcmf_ssid_le ssid_le; | ||
278 | struct brcmf_assoc_params_le params_le; | ||
279 | }; | ||
280 | |||
281 | /* scan params for extended join */ | ||
282 | struct brcmf_join_scan_params_le { | ||
283 | u8 scan_type; /* 0 use default, active or passive scan */ | ||
284 | __le32 nprobes; /* -1 use default, nr of probes per channel */ | ||
285 | __le32 active_time; /* -1 use default, dwell time per channel for | ||
286 | * active scanning | ||
287 | */ | ||
288 | __le32 passive_time; /* -1 use default, dwell time per channel | ||
289 | * for passive scanning | ||
290 | */ | ||
291 | __le32 home_time; /* -1 use default, dwell time for the home | ||
292 | * channel between channel scans | ||
293 | */ | ||
294 | }; | ||
295 | |||
296 | /* extended join params */ | ||
297 | struct brcmf_ext_join_params_le { | ||
298 | struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */ | ||
299 | struct brcmf_join_scan_params_le scan_le; | ||
300 | struct brcmf_assoc_params_le assoc_le; | ||
301 | }; | ||
302 | |||
303 | struct brcmf_wsec_key { | ||
304 | u32 index; /* key index */ | ||
305 | u32 len; /* key length */ | ||
306 | u8 data[WLAN_MAX_KEY_LEN]; /* key data */ | ||
307 | u32 pad_1[18]; | ||
308 | u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ | ||
309 | u32 flags; /* misc flags */ | ||
310 | u32 pad_2[3]; | ||
311 | u32 iv_initialized; /* has IV been initialized already? */ | ||
312 | u32 pad_3; | ||
313 | /* Rx IV */ | ||
314 | struct { | ||
315 | u32 hi; /* upper 32 bits of IV */ | ||
316 | u16 lo; /* lower 16 bits of IV */ | ||
317 | } rxiv; | ||
318 | u32 pad_4[2]; | ||
319 | u8 ea[ETH_ALEN]; /* per station */ | ||
320 | }; | ||
321 | |||
322 | /* | ||
323 | * dongle requires same struct as above but with fields in little endian order | ||
324 | */ | ||
325 | struct brcmf_wsec_key_le { | ||
326 | __le32 index; /* key index */ | ||
327 | __le32 len; /* key length */ | ||
328 | u8 data[WLAN_MAX_KEY_LEN]; /* key data */ | ||
329 | __le32 pad_1[18]; | ||
330 | __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ | ||
331 | __le32 flags; /* misc flags */ | ||
332 | __le32 pad_2[3]; | ||
333 | __le32 iv_initialized; /* has IV been initialized already? */ | ||
334 | __le32 pad_3; | ||
335 | /* Rx IV */ | ||
336 | struct { | ||
337 | __le32 hi; /* upper 32 bits of IV */ | ||
338 | __le16 lo; /* lower 16 bits of IV */ | ||
339 | } rxiv; | ||
340 | __le32 pad_4[2]; | ||
341 | u8 ea[ETH_ALEN]; /* per station */ | ||
342 | }; | ||
343 | |||
344 | /* Used to get specific STA parameters */ | ||
345 | struct brcmf_scb_val_le { | ||
346 | __le32 val; | ||
347 | u8 ea[ETH_ALEN]; | ||
348 | }; | ||
349 | |||
350 | /* channel encoding */ | ||
351 | struct brcmf_channel_info_le { | ||
352 | __le32 hw_channel; | ||
353 | __le32 target_channel; | ||
354 | __le32 scan_channel; | ||
355 | }; | ||
356 | |||
357 | struct brcmf_sta_info_le { | ||
358 | __le16 ver; /* version of this struct */ | ||
359 | __le16 len; /* length in bytes of this structure */ | ||
360 | __le16 cap; /* sta's advertised capabilities */ | ||
361 | __le32 flags; /* flags defined below */ | ||
362 | __le32 idle; /* time since data pkt rx'd from sta */ | ||
363 | u8 ea[ETH_ALEN]; /* Station address */ | ||
364 | __le32 count; /* # rates in this set */ | ||
365 | u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ | ||
366 | /* w/hi bit set if basic */ | ||
367 | __le32 in; /* seconds elapsed since associated */ | ||
368 | __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ | ||
369 | __le32 tx_pkts; /* # of packets transmitted */ | ||
370 | __le32 tx_failures; /* # of packets failed */ | ||
371 | __le32 rx_ucast_pkts; /* # of unicast packets received */ | ||
372 | __le32 rx_mcast_pkts; /* # of multicast packets received */ | ||
373 | __le32 tx_rate; /* Rate of last successful tx frame */ | ||
374 | __le32 rx_rate; /* Rate of last successful rx frame */ | ||
375 | __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ | ||
376 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ | ||
377 | }; | ||
378 | |||
379 | struct brcmf_chanspec_list { | ||
380 | __le32 count; /* # of entries */ | ||
381 | __le32 element[1]; /* variable length uint32 list */ | ||
382 | }; | ||
383 | |||
384 | /* | ||
385 | * WLC_E_PROBRESP_MSG | ||
386 | * WLC_E_P2P_PROBREQ_MSG | ||
387 | * WLC_E_ACTION_FRAME_RX | ||
388 | */ | ||
389 | struct brcmf_rx_mgmt_data { | ||
390 | __be16 version; | ||
391 | __be16 chanspec; | ||
392 | __be32 rssi; | ||
393 | __be32 mactime; | ||
394 | __be32 rate; | ||
395 | }; | ||
396 | |||
93 | #endif /* FWIL_TYPES_H_ */ | 397 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index d0cd0bf95c5a..e9bdfdb95d8f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <brcmu_utils.h> | 27 | #include <brcmu_utils.h> |
28 | #include <brcmu_wifi.h> | 28 | #include <brcmu_wifi.h> |
29 | #include "dhd.h" | 29 | #include "dhd.h" |
30 | #include "dhd_proto.h" | ||
31 | #include "dhd_dbg.h" | 30 | #include "dhd_dbg.h" |
32 | #include "dhd_bus.h" | 31 | #include "dhd_bus.h" |
33 | #include "fwil.h" | 32 | #include "fwil.h" |
@@ -36,6 +35,7 @@ | |||
36 | #include "fwsignal.h" | 35 | #include "fwsignal.h" |
37 | #include "p2p.h" | 36 | #include "p2p.h" |
38 | #include "wl_cfg80211.h" | 37 | #include "wl_cfg80211.h" |
38 | #include "proto.h" | ||
39 | 39 | ||
40 | /** | 40 | /** |
41 | * DOC: Firmware Signalling | 41 | * DOC: Firmware Signalling |
@@ -105,6 +105,7 @@ static struct { | |||
105 | }; | 105 | }; |
106 | #undef BRCMF_FWS_TLV_DEF | 106 | #undef BRCMF_FWS_TLV_DEF |
107 | 107 | ||
108 | |||
108 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | 109 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) |
109 | { | 110 | { |
110 | int i; | 111 | int i; |
@@ -123,6 +124,12 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | |||
123 | #endif /* DEBUG */ | 124 | #endif /* DEBUG */ |
124 | 125 | ||
125 | /* | 126 | /* |
127 | * The PKTTAG tlv has additional bytes when firmware-signalling | ||
128 | * mode has REUSESEQ flag set. | ||
129 | */ | ||
130 | #define BRCMF_FWS_TYPE_SEQ_LEN 2 | ||
131 | |||
132 | /* | ||
126 | * flags used to enable tlv signalling from firmware. | 133 | * flags used to enable tlv signalling from firmware. |
127 | */ | 134 | */ |
128 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 | 135 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 |
@@ -147,8 +154,15 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | |||
147 | #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 | 154 | #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 |
148 | #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02 | 155 | #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02 |
149 | 156 | ||
150 | #define BRCMF_FWS_RET_OK_NOSCHEDULE 0 | 157 | #define BRCMF_FWS_RET_OK_NOSCHEDULE 0 |
151 | #define BRCMF_FWS_RET_OK_SCHEDULE 1 | 158 | #define BRCMF_FWS_RET_OK_SCHEDULE 1 |
159 | |||
160 | #define BRCMF_FWS_MODE_REUSESEQ_SHIFT 3 /* seq reuse */ | ||
161 | #define BRCMF_FWS_MODE_SET_REUSESEQ(x, val) ((x) = \ | ||
162 | ((x) & ~(1 << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | \ | ||
163 | (((val) & 1) << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | ||
164 | #define BRCMF_FWS_MODE_GET_REUSESEQ(x) \ | ||
165 | (((x) >> BRCMF_FWS_MODE_REUSESEQ_SHIFT) & 1) | ||
152 | 166 | ||
153 | /** | 167 | /** |
154 | * enum brcmf_fws_skb_state - indicates processing state of skb. | 168 | * enum brcmf_fws_skb_state - indicates processing state of skb. |
@@ -171,6 +185,7 @@ enum brcmf_fws_skb_state { | |||
171 | * @bus_flags: 2 bytes reserved for bus specific parameters | 185 | * @bus_flags: 2 bytes reserved for bus specific parameters |
172 | * @if_flags: holds interface index and packet related flags. | 186 | * @if_flags: holds interface index and packet related flags. |
173 | * @htod: host to device packet identifier (used in PKTTAG tlv). | 187 | * @htod: host to device packet identifier (used in PKTTAG tlv). |
188 | * @htod_seq: this 16-bit is original seq number for every suppress packet. | ||
174 | * @state: transmit state of the packet. | 189 | * @state: transmit state of the packet. |
175 | * @mac: descriptor related to destination for this packet. | 190 | * @mac: descriptor related to destination for this packet. |
176 | * | 191 | * |
@@ -181,6 +196,7 @@ struct brcmf_skbuff_cb { | |||
181 | u16 bus_flags; | 196 | u16 bus_flags; |
182 | u16 if_flags; | 197 | u16 if_flags; |
183 | u32 htod; | 198 | u32 htod; |
199 | u16 htod_seq; | ||
184 | enum brcmf_fws_skb_state state; | 200 | enum brcmf_fws_skb_state state; |
185 | struct brcmf_fws_mac_descriptor *mac; | 201 | struct brcmf_fws_mac_descriptor *mac; |
186 | }; | 202 | }; |
@@ -257,6 +273,22 @@ struct brcmf_skbuff_cb { | |||
257 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | 273 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ |
258 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) | 274 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) |
259 | 275 | ||
276 | #define BRCMF_SKB_HTOD_SEQ_FROMFW_MASK 0x2000 | ||
277 | #define BRCMF_SKB_HTOD_SEQ_FROMFW_SHIFT 13 | ||
278 | #define BRCMF_SKB_HTOD_SEQ_FROMDRV_MASK 0x1000 | ||
279 | #define BRCMF_SKB_HTOD_SEQ_FROMDRV_SHIFT 12 | ||
280 | #define BRCMF_SKB_HTOD_SEQ_NR_MASK 0x0fff | ||
281 | #define BRCMF_SKB_HTOD_SEQ_NR_SHIFT 0 | ||
282 | |||
283 | #define brcmf_skb_htod_seq_set_field(skb, field, value) \ | ||
284 | brcmu_maskset16(&(brcmf_skbcb(skb)->htod_seq), \ | ||
285 | BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \ | ||
286 | BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT, (value)) | ||
287 | #define brcmf_skb_htod_seq_get_field(skb, field) \ | ||
288 | brcmu_maskget16(brcmf_skbcb(skb)->htod_seq, \ | ||
289 | BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \ | ||
290 | BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT) | ||
291 | |||
260 | #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000 | 292 | #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000 |
261 | #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31 | 293 | #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31 |
262 | #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000 | 294 | #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000 |
@@ -265,8 +297,8 @@ struct brcmf_skbuff_cb { | |||
265 | #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24 | 297 | #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24 |
266 | #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00 | 298 | #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00 |
267 | #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8 | 299 | #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8 |
268 | #define BRCMF_FWS_TXSTAT_PKTID_MASK 0x00FFFFFF | 300 | #define BRCMF_FWS_TXSTAT_FREERUN_MASK 0x000000FF |
269 | #define BRCMF_FWS_TXSTAT_PKTID_SHIFT 0 | 301 | #define BRCMF_FWS_TXSTAT_FREERUN_SHIFT 0 |
270 | 302 | ||
271 | #define brcmf_txstatus_get_field(txs, field) \ | 303 | #define brcmf_txstatus_get_field(txs, field) \ |
272 | brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \ | 304 | brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \ |
@@ -443,6 +475,7 @@ struct brcmf_fws_info { | |||
443 | unsigned long borrow_defer_timestamp; | 475 | unsigned long borrow_defer_timestamp; |
444 | bool bus_flow_blocked; | 476 | bool bus_flow_blocked; |
445 | bool creditmap_received; | 477 | bool creditmap_received; |
478 | u8 mode; | ||
446 | }; | 479 | }; |
447 | 480 | ||
448 | /* | 481 | /* |
@@ -812,13 +845,16 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | |||
812 | u16 data_offset = 0; | 845 | u16 data_offset = 0; |
813 | u8 fillers; | 846 | u8 fillers; |
814 | __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); | 847 | __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); |
848 | __le16 pktseq = cpu_to_le16(brcmf_skbcb(skb)->htod_seq); | ||
815 | 849 | ||
816 | brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n", | 850 | brcmf_dbg(TRACE, "enter: %s, idx=%d hslot=%d htod %X seq %X\n", |
817 | entry->name, brcmf_skb_if_flags_get_field(skb, INDEX), | 851 | entry->name, brcmf_skb_if_flags_get_field(skb, INDEX), |
818 | le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff); | 852 | (le32_to_cpu(pkttag) >> 8) & 0xffff, |
853 | brcmf_skbcb(skb)->htod, brcmf_skbcb(skb)->htod_seq); | ||
819 | if (entry->send_tim_signal) | 854 | if (entry->send_tim_signal) |
820 | data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; | 855 | data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; |
821 | 856 | if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) | |
857 | data_offset += BRCMF_FWS_TYPE_SEQ_LEN; | ||
822 | /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ | 858 | /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ |
823 | data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; | 859 | data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; |
824 | fillers = round_up(data_offset, 4) - data_offset; | 860 | fillers = round_up(data_offset, 4) - data_offset; |
@@ -830,7 +866,12 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | |||
830 | wlh[0] = BRCMF_FWS_TYPE_PKTTAG; | 866 | wlh[0] = BRCMF_FWS_TYPE_PKTTAG; |
831 | wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; | 867 | wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; |
832 | memcpy(&wlh[2], &pkttag, sizeof(pkttag)); | 868 | memcpy(&wlh[2], &pkttag, sizeof(pkttag)); |
833 | wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; | 869 | if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) { |
870 | wlh[1] += BRCMF_FWS_TYPE_SEQ_LEN; | ||
871 | memcpy(&wlh[2 + BRCMF_FWS_TYPE_PKTTAG_LEN], &pktseq, | ||
872 | sizeof(pktseq)); | ||
873 | } | ||
874 | wlh += wlh[1] + 2; | ||
834 | 875 | ||
835 | if (entry->send_tim_signal) { | 876 | if (entry->send_tim_signal) { |
836 | entry->send_tim_signal = 0; | 877 | entry->send_tim_signal = 0; |
@@ -875,6 +916,7 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, | |||
875 | /* create a dummy packet and sent that. The traffic */ | 916 | /* create a dummy packet and sent that. The traffic */ |
876 | /* bitmap info will automatically be attached to that packet */ | 917 | /* bitmap info will automatically be attached to that packet */ |
877 | len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 + | 918 | len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 + |
919 | BRCMF_FWS_TYPE_SEQ_LEN + | ||
878 | BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 + | 920 | BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 + |
879 | 4 + fws->drvr->hdrlen; | 921 | 4 + fws->drvr->hdrlen; |
880 | skb = brcmu_pkt_buf_get_skb(len); | 922 | skb = brcmu_pkt_buf_get_skb(len); |
@@ -884,6 +926,8 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, | |||
884 | skcb = brcmf_skbcb(skb); | 926 | skcb = brcmf_skbcb(skb); |
885 | skcb->mac = entry; | 927 | skcb->mac = entry; |
886 | skcb->state = BRCMF_FWS_SKBSTATE_TIM; | 928 | skcb->state = BRCMF_FWS_SKBSTATE_TIM; |
929 | skcb->htod = 0; | ||
930 | skcb->htod_seq = 0; | ||
887 | bus = fws->drvr->bus_if; | 931 | bus = fws->drvr->bus_if; |
888 | err = brcmf_fws_hdrpush(fws, skb); | 932 | err = brcmf_fws_hdrpush(fws, skb); |
889 | if (err == 0) { | 933 | if (err == 0) { |
@@ -1172,8 +1216,13 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, | |||
1172 | { | 1216 | { |
1173 | int prec = 2 * fifo; | 1217 | int prec = 2 * fifo; |
1174 | u32 *qfull_stat = &fws->stats.delayq_full_error; | 1218 | u32 *qfull_stat = &fws->stats.delayq_full_error; |
1175 | |||
1176 | struct brcmf_fws_mac_descriptor *entry; | 1219 | struct brcmf_fws_mac_descriptor *entry; |
1220 | struct pktq *pq; | ||
1221 | struct sk_buff_head *queue; | ||
1222 | struct sk_buff *p_head; | ||
1223 | struct sk_buff *p_tail; | ||
1224 | u32 fr_new; | ||
1225 | u32 fr_compare; | ||
1177 | 1226 | ||
1178 | entry = brcmf_skbcb(p)->mac; | 1227 | entry = brcmf_skbcb(p)->mac; |
1179 | if (entry == NULL) { | 1228 | if (entry == NULL) { |
@@ -1185,9 +1234,55 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, | |||
1185 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { | 1234 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { |
1186 | prec += 1; | 1235 | prec += 1; |
1187 | qfull_stat = &fws->stats.supprq_full_error; | 1236 | qfull_stat = &fws->stats.supprq_full_error; |
1188 | } | ||
1189 | 1237 | ||
1190 | if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { | 1238 | /* Fix out of order delivery of frames. Dont assume frame */ |
1239 | /* can be inserted at the end, but look for correct position */ | ||
1240 | pq = &entry->psq; | ||
1241 | if (pktq_full(pq) || pktq_pfull(pq, prec)) { | ||
1242 | *qfull_stat += 1; | ||
1243 | return -ENFILE; | ||
1244 | } | ||
1245 | queue = &pq->q[prec].skblist; | ||
1246 | |||
1247 | p_head = skb_peek(queue); | ||
1248 | p_tail = skb_peek_tail(queue); | ||
1249 | fr_new = brcmf_skb_htod_tag_get_field(p, FREERUN); | ||
1250 | |||
1251 | while (p_head != p_tail) { | ||
1252 | fr_compare = brcmf_skb_htod_tag_get_field(p_tail, | ||
1253 | FREERUN); | ||
1254 | /* be sure to handle wrap of 256 */ | ||
1255 | if (((fr_new > fr_compare) && | ||
1256 | ((fr_new - fr_compare) < 128)) || | ||
1257 | ((fr_new < fr_compare) && | ||
1258 | ((fr_compare - fr_new) > 128))) | ||
1259 | break; | ||
1260 | p_tail = skb_queue_prev(queue, p_tail); | ||
1261 | } | ||
1262 | /* Position found. Determine what to do */ | ||
1263 | if (p_tail == NULL) { | ||
1264 | /* empty list */ | ||
1265 | __skb_queue_tail(queue, p); | ||
1266 | } else { | ||
1267 | fr_compare = brcmf_skb_htod_tag_get_field(p_tail, | ||
1268 | FREERUN); | ||
1269 | if (((fr_new > fr_compare) && | ||
1270 | ((fr_new - fr_compare) < 128)) || | ||
1271 | ((fr_new < fr_compare) && | ||
1272 | ((fr_compare - fr_new) > 128))) { | ||
1273 | /* After tail */ | ||
1274 | __skb_queue_after(queue, p_tail, p); | ||
1275 | } else { | ||
1276 | /* Before tail */ | ||
1277 | __skb_insert(p, p_tail->prev, p_tail, queue); | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | /* Complete the counters and statistics */ | ||
1282 | pq->len++; | ||
1283 | if (pq->hi_prec < prec) | ||
1284 | pq->hi_prec = (u8) prec; | ||
1285 | } else if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { | ||
1191 | *qfull_stat += 1; | 1286 | *qfull_stat += 1; |
1192 | return -ENFILE; | 1287 | return -ENFILE; |
1193 | } | 1288 | } |
@@ -1277,7 +1372,8 @@ done: | |||
1277 | } | 1372 | } |
1278 | 1373 | ||
1279 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | 1374 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, |
1280 | struct sk_buff *skb, u32 genbit) | 1375 | struct sk_buff *skb, u32 genbit, |
1376 | u16 seq) | ||
1281 | { | 1377 | { |
1282 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | 1378 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; |
1283 | u32 hslot; | 1379 | u32 hslot; |
@@ -1298,6 +1394,14 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
1298 | 1394 | ||
1299 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | 1395 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); |
1300 | if (ret == 0) | 1396 | if (ret == 0) |
1397 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); | ||
1398 | brcmf_skbcb(skb)->htod_seq = seq; | ||
1399 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { | ||
1400 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); | ||
1401 | brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); | ||
1402 | } else { | ||
1403 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); | ||
1404 | } | ||
1301 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, | 1405 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, |
1302 | skb); | 1406 | skb); |
1303 | if (ret != 0) { | 1407 | if (ret != 0) { |
@@ -1317,7 +1421,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
1317 | 1421 | ||
1318 | static int | 1422 | static int |
1319 | brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | 1423 | brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, |
1320 | u32 genbit) | 1424 | u32 genbit, u16 seq) |
1321 | { | 1425 | { |
1322 | u32 fifo; | 1426 | u32 fifo; |
1323 | int ret; | 1427 | int ret; |
@@ -1360,8 +1464,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
1360 | if (entry->suppressed && entry->suppr_transit_count) | 1464 | if (entry->suppressed && entry->suppr_transit_count) |
1361 | entry->suppr_transit_count--; | 1465 | entry->suppr_transit_count--; |
1362 | 1466 | ||
1363 | brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, | 1467 | brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags, |
1364 | skcb->htod); | 1468 | skcb->htod, seq); |
1365 | 1469 | ||
1366 | /* pick up the implicit credit from this packet */ | 1470 | /* pick up the implicit credit from this packet */ |
1367 | fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); | 1471 | fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); |
@@ -1374,7 +1478,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
1374 | brcmf_fws_macdesc_return_req_credit(skb); | 1478 | brcmf_fws_macdesc_return_req_credit(skb); |
1375 | 1479 | ||
1376 | if (!remove_from_hanger) | 1480 | if (!remove_from_hanger) |
1377 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); | 1481 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, |
1482 | seq); | ||
1378 | 1483 | ||
1379 | if (remove_from_hanger || ret) | 1484 | if (remove_from_hanger || ret) |
1380 | brcmf_txfinalize(fws->drvr, skb, true); | 1485 | brcmf_txfinalize(fws->drvr, skb, true); |
@@ -1406,10 +1511,12 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, | |||
1406 | static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) | 1511 | static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) |
1407 | { | 1512 | { |
1408 | __le32 status_le; | 1513 | __le32 status_le; |
1514 | __le16 seq_le; | ||
1409 | u32 status; | 1515 | u32 status; |
1410 | u32 hslot; | 1516 | u32 hslot; |
1411 | u32 genbit; | 1517 | u32 genbit; |
1412 | u8 flags; | 1518 | u8 flags; |
1519 | u16 seq; | ||
1413 | 1520 | ||
1414 | fws->stats.txs_indicate++; | 1521 | fws->stats.txs_indicate++; |
1415 | memcpy(&status_le, data, sizeof(status_le)); | 1522 | memcpy(&status_le, data, sizeof(status_le)); |
@@ -1417,9 +1524,16 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) | |||
1417 | flags = brcmf_txstatus_get_field(status, FLAGS); | 1524 | flags = brcmf_txstatus_get_field(status, FLAGS); |
1418 | hslot = brcmf_txstatus_get_field(status, HSLOT); | 1525 | hslot = brcmf_txstatus_get_field(status, HSLOT); |
1419 | genbit = brcmf_txstatus_get_field(status, GENERATION); | 1526 | genbit = brcmf_txstatus_get_field(status, GENERATION); |
1527 | if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) { | ||
1528 | memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN], | ||
1529 | sizeof(seq_le)); | ||
1530 | seq = le16_to_cpu(seq_le); | ||
1531 | } else { | ||
1532 | seq = 0; | ||
1533 | } | ||
1420 | 1534 | ||
1421 | brcmf_fws_lock(fws); | 1535 | brcmf_fws_lock(fws); |
1422 | brcmf_fws_txs_process(fws, flags, hslot, genbit); | 1536 | brcmf_fws_txs_process(fws, flags, hslot, genbit, seq); |
1423 | brcmf_fws_unlock(fws); | 1537 | brcmf_fws_unlock(fws); |
1424 | return BRCMF_FWS_RET_OK_NOSCHEDULE; | 1538 | return BRCMF_FWS_RET_OK_NOSCHEDULE; |
1425 | } | 1539 | } |
@@ -1610,8 +1724,8 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, | |||
1610 | struct brcmf_fws_mac_descriptor *entry = skcb->mac; | 1724 | struct brcmf_fws_mac_descriptor *entry = skcb->mac; |
1611 | u8 flags; | 1725 | u8 flags; |
1612 | 1726 | ||
1613 | brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); | 1727 | if (skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED) |
1614 | brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); | 1728 | brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); |
1615 | flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; | 1729 | flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; |
1616 | if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { | 1730 | if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { |
1617 | /* | 1731 | /* |
@@ -1652,7 +1766,7 @@ static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, | |||
1652 | fws->stats.rollback_failed++; | 1766 | fws->stats.rollback_failed++; |
1653 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | 1767 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); |
1654 | brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, | 1768 | brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, |
1655 | hslot, 0); | 1769 | hslot, 0, 0); |
1656 | } else { | 1770 | } else { |
1657 | fws->stats.rollback_success++; | 1771 | fws->stats.rollback_success++; |
1658 | brcmf_fws_return_credits(fws, fifo, 1); | 1772 | brcmf_fws_return_credits(fws, fifo, 1); |
@@ -1732,6 +1846,8 @@ static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p, | |||
1732 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); | 1846 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); |
1733 | int rc, hslot; | 1847 | int rc, hslot; |
1734 | 1848 | ||
1849 | skcb->htod = 0; | ||
1850 | skcb->htod_seq = 0; | ||
1735 | hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); | 1851 | hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); |
1736 | brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); | 1852 | brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); |
1737 | brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]); | 1853 | brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]); |
@@ -1908,6 +2024,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr) | |||
1908 | struct brcmf_fws_info *fws; | 2024 | struct brcmf_fws_info *fws; |
1909 | u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; | 2025 | u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; |
1910 | int rc; | 2026 | int rc; |
2027 | u32 mode; | ||
1911 | 2028 | ||
1912 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | 2029 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); |
1913 | if (!drvr->fws) { | 2030 | if (!drvr->fws) { |
@@ -1966,6 +2083,18 @@ int brcmf_fws_init(struct brcmf_pub *drvr) | |||
1966 | if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) | 2083 | if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) |
1967 | brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); | 2084 | brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); |
1968 | 2085 | ||
2086 | /* Enable seq number reuse, if supported */ | ||
2087 | if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { | ||
2088 | if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { | ||
2089 | mode = 0; | ||
2090 | BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); | ||
2091 | if (brcmf_fil_iovar_int_set(drvr->iflist[0], | ||
2092 | "wlfc_mode", mode) == 0) { | ||
2093 | BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); | ||
2094 | } | ||
2095 | } | ||
2096 | } | ||
2097 | |||
1969 | brcmf_fws_hanger_init(&fws->hanger); | 2098 | brcmf_fws_hanger_init(&fws->hanger); |
1970 | brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0); | 2099 | brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0); |
1971 | brcmf_fws_macdesc_set_name(fws, &fws->desc.other); | 2100 | brcmf_fws_macdesc_set_name(fws, &fws->desc.other); |
@@ -2022,7 +2151,7 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) | |||
2022 | } | 2151 | } |
2023 | brcmf_fws_lock(fws); | 2152 | brcmf_fws_lock(fws); |
2024 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | 2153 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); |
2025 | brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0); | 2154 | brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0); |
2026 | brcmf_fws_unlock(fws); | 2155 | brcmf_fws_unlock(fws); |
2027 | } | 2156 | } |
2028 | 2157 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 4a2293041821..d31803607259 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -812,7 +812,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | |||
812 | struct ieee80211_channel *chan = request->channels[i]; | 812 | struct ieee80211_channel *chan = request->channels[i]; |
813 | 813 | ||
814 | if (chan->flags & (IEEE80211_CHAN_RADAR | | 814 | if (chan->flags & (IEEE80211_CHAN_RADAR | |
815 | IEEE80211_CHAN_PASSIVE_SCAN)) | 815 | IEEE80211_CHAN_NO_IR)) |
816 | continue; | 816 | continue; |
817 | 817 | ||
818 | chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, | 818 | chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c new file mode 100644 index 000000000000..87eb2bd4c072 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #include <linux/types.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | |||
22 | #include <brcmu_wifi.h> | ||
23 | #include "dhd.h" | ||
24 | #include "dhd_dbg.h" | ||
25 | #include "proto.h" | ||
26 | #include "bcdc.h" | ||
27 | |||
28 | |||
29 | int brcmf_proto_attach(struct brcmf_pub *drvr) | ||
30 | { | ||
31 | struct brcmf_proto *proto; | ||
32 | |||
33 | proto = kzalloc(sizeof(*proto), GFP_ATOMIC); | ||
34 | if (!proto) | ||
35 | goto fail; | ||
36 | |||
37 | drvr->proto = proto; | ||
38 | /* BCDC protocol is only protocol supported for the moment */ | ||
39 | if (brcmf_proto_bcdc_attach(drvr)) | ||
40 | goto fail; | ||
41 | |||
42 | if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) || | ||
43 | (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) { | ||
44 | brcmf_err("Not all proto handlers have been installed\n"); | ||
45 | goto fail; | ||
46 | } | ||
47 | return 0; | ||
48 | |||
49 | fail: | ||
50 | kfree(proto); | ||
51 | drvr->proto = NULL; | ||
52 | return -ENOMEM; | ||
53 | } | ||
54 | |||
55 | void brcmf_proto_detach(struct brcmf_pub *drvr) | ||
56 | { | ||
57 | if (drvr->proto) { | ||
58 | brcmf_proto_bcdc_detach(drvr); | ||
59 | kfree(drvr->proto); | ||
60 | drvr->proto = NULL; | ||
61 | } | ||
62 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h new file mode 100644 index 000000000000..8de1b3bce228 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef BRCMFMAC_PROTO_H | ||
17 | #define BRCMFMAC_PROTO_H | ||
18 | |||
19 | struct brcmf_proto { | ||
20 | void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
21 | struct sk_buff *skb); | ||
22 | int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | ||
23 | struct sk_buff *skb); | ||
24 | int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
25 | void *buf, uint len); | ||
26 | int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, | ||
27 | uint len); | ||
28 | void *pd; | ||
29 | }; | ||
30 | |||
31 | |||
32 | int brcmf_proto_attach(struct brcmf_pub *drvr); | ||
33 | void brcmf_proto_detach(struct brcmf_pub *drvr); | ||
34 | |||
35 | static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | ||
36 | u8 offset, struct sk_buff *skb) | ||
37 | { | ||
38 | drvr->proto->hdrpush(drvr, ifidx, offset, skb); | ||
39 | } | ||
40 | static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, | ||
41 | u8 *ifidx, struct sk_buff *skb) | ||
42 | { | ||
43 | return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); | ||
44 | } | ||
45 | static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, | ||
46 | uint cmd, void *buf, uint len) | ||
47 | { | ||
48 | return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len); | ||
49 | } | ||
50 | static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, | ||
51 | uint cmd, void *buf, uint len) | ||
52 | { | ||
53 | return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); | ||
54 | } | ||
55 | |||
56 | |||
57 | #endif /* BRCMFMAC_PROTO_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index 3c67529b9074..4d7d51f95716 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
@@ -89,7 +89,7 @@ TRACE_EVENT(brcmf_hexdump, | |||
89 | TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len) | 89 | TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len) |
90 | ); | 90 | ); |
91 | 91 | ||
92 | TRACE_EVENT(brcmf_bdchdr, | 92 | TRACE_EVENT(brcmf_bcdchdr, |
93 | TP_PROTO(void *data), | 93 | TP_PROTO(void *data), |
94 | TP_ARGS(data), | 94 | TP_ARGS(data), |
95 | TP_STRUCT__entry( | 95 | TP_STRUCT__entry( |
@@ -107,24 +107,35 @@ TRACE_EVENT(brcmf_bdchdr, | |||
107 | memcpy(__get_dynamic_array(signal), | 107 | memcpy(__get_dynamic_array(signal), |
108 | (u8 *)data + 4, __entry->siglen); | 108 | (u8 *)data + 4, __entry->siglen); |
109 | ), | 109 | ), |
110 | TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) | 110 | TP_printk("bcdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) |
111 | ); | 111 | ); |
112 | 112 | ||
113 | #ifndef SDPCM_RX | ||
114 | #define SDPCM_RX 0 | ||
115 | #endif | ||
116 | #ifndef SDPCM_TX | ||
117 | #define SDPCM_TX 1 | ||
118 | #endif | ||
119 | #ifndef SDPCM_GLOM | ||
120 | #define SDPCM_GLOM 2 | ||
121 | #endif | ||
122 | |||
113 | TRACE_EVENT(brcmf_sdpcm_hdr, | 123 | TRACE_EVENT(brcmf_sdpcm_hdr, |
114 | TP_PROTO(bool tx, void *data), | 124 | TP_PROTO(u8 dir, void *data), |
115 | TP_ARGS(tx, data), | 125 | TP_ARGS(dir, data), |
116 | TP_STRUCT__entry( | 126 | TP_STRUCT__entry( |
117 | __field(u8, tx) | 127 | __field(u8, dir) |
118 | __field(u16, len) | 128 | __field(u16, len) |
119 | __array(u8, hdr, 12) | 129 | __dynamic_array(u8, hdr, dir == SDPCM_GLOM ? 20 : 12) |
120 | ), | 130 | ), |
121 | TP_fast_assign( | 131 | TP_fast_assign( |
122 | memcpy(__entry->hdr, data, 12); | 132 | memcpy(__get_dynamic_array(hdr), data, dir == SDPCM_GLOM ? 20 : 12); |
123 | __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8); | 133 | __entry->len = *(u8 *)data | (*((u8 *)data + 1) << 8); |
124 | __entry->tx = tx ? 1 : 0; | 134 | __entry->dir = dir; |
125 | ), | 135 | ), |
126 | TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX", | 136 | TP_printk("sdpcm: %s len %u, seq %d", |
127 | __entry->len, __entry->hdr[4]) | 137 | __entry->dir == SDPCM_RX ? "RX" : "TX", |
138 | __entry->len, ((u8 *)__get_dynamic_array(hdr))[4]) | ||
128 | ); | 139 | ); |
129 | 140 | ||
130 | #ifdef CONFIG_BRCM_TRACING | 141 | #ifdef CONFIG_BRCM_TRACING |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 422f44c63175..51c4de054b15 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -1255,7 +1255,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
1255 | bus->chiprev = bus_pub->chiprev; | 1255 | bus->chiprev = bus_pub->chiprev; |
1256 | 1256 | ||
1257 | /* Attach to the common driver interface */ | 1257 | /* Attach to the common driver interface */ |
1258 | ret = brcmf_attach(0, dev); | 1258 | ret = brcmf_attach(dev); |
1259 | if (ret) { | 1259 | if (ret) { |
1260 | brcmf_err("brcmf_attach failed\n"); | 1260 | brcmf_err("brcmf_attach failed\n"); |
1261 | goto fail; | 1261 | goto fail; |
@@ -1454,7 +1454,7 @@ static int brcmf_usb_resume(struct usb_interface *intf) | |||
1454 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); | 1454 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); |
1455 | 1455 | ||
1456 | brcmf_dbg(USB, "Enter\n"); | 1456 | brcmf_dbg(USB, "Enter\n"); |
1457 | if (!brcmf_attach(0, devinfo->dev)) | 1457 | if (!brcmf_attach(devinfo->dev)) |
1458 | return brcmf_bus_start(&usb->dev); | 1458 | return brcmf_bus_start(&usb->dev); |
1459 | 1459 | ||
1460 | return 0; | 1460 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 571f013cebbb..3966fe0fcfd9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -202,9 +202,9 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { | |||
202 | 202 | ||
203 | /* This is to override regulatory domains defined in cfg80211 module (reg.c) | 203 | /* This is to override regulatory domains defined in cfg80211 module (reg.c) |
204 | * By default world regulatory domain defined in reg.c puts the flags | 204 | * By default world regulatory domain defined in reg.c puts the flags |
205 | * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for | 205 | * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165). |
206 | * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't | 206 | * With respect to these flags, wpa_supplicant doesn't * start p2p |
207 | * start p2p operations on 5GHz channels. All the changes in world regulatory | 207 | * operations on 5GHz channels. All the changes in world regulatory |
208 | * domain are to be done here. | 208 | * domain are to be done here. |
209 | */ | 209 | */ |
210 | static const struct ieee80211_regdomain brcmf_regdom = { | 210 | static const struct ieee80211_regdomain brcmf_regdom = { |
@@ -2556,8 +2556,8 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg, | |||
2556 | ch_bss.band == ch_bss_info_le.band && | 2556 | ch_bss.band == ch_bss_info_le.band && |
2557 | bss_info_le->SSID_len == bss->SSID_len && | 2557 | bss_info_le->SSID_len == bss->SSID_len && |
2558 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { | 2558 | !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) { |
2559 | if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == | 2559 | if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == |
2560 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) { | 2560 | (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) { |
2561 | s16 bss_rssi = le16_to_cpu(bss->RSSI); | 2561 | s16 bss_rssi = le16_to_cpu(bss->RSSI); |
2562 | s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI); | 2562 | s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI); |
2563 | 2563 | ||
@@ -2566,13 +2566,13 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg, | |||
2566 | */ | 2566 | */ |
2567 | if (bss_info_rssi > bss_rssi) | 2567 | if (bss_info_rssi > bss_rssi) |
2568 | bss->RSSI = bss_info_le->RSSI; | 2568 | bss->RSSI = bss_info_le->RSSI; |
2569 | } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && | 2569 | } else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) && |
2570 | (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { | 2570 | (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) { |
2571 | /* preserve the on-channel rssi measurement | 2571 | /* preserve the on-channel rssi measurement |
2572 | * if the new measurement is off channel | 2572 | * if the new measurement is off channel |
2573 | */ | 2573 | */ |
2574 | bss->RSSI = bss_info_le->RSSI; | 2574 | bss->RSSI = bss_info_le->RSSI; |
2575 | bss->flags |= WLC_BSS_RSSI_ON_CHANNEL; | 2575 | bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL; |
2576 | } | 2576 | } |
2577 | return 1; | 2577 | return 1; |
2578 | } | 2578 | } |
@@ -3973,11 +3973,12 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy, | |||
3973 | 3973 | ||
3974 | static int | 3974 | static int |
3975 | brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 3975 | brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
3976 | struct ieee80211_channel *chan, bool offchan, | 3976 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) |
3977 | unsigned int wait, const u8 *buf, size_t len, | ||
3978 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
3979 | { | 3977 | { |
3980 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3978 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3979 | struct ieee80211_channel *chan = params->chan; | ||
3980 | const u8 *buf = params->buf; | ||
3981 | size_t len = params->len; | ||
3981 | const struct ieee80211_mgmt *mgmt; | 3982 | const struct ieee80211_mgmt *mgmt; |
3982 | struct brcmf_cfg80211_vif *vif; | 3983 | struct brcmf_cfg80211_vif *vif; |
3983 | s32 err = 0; | 3984 | s32 err = 0; |
@@ -4341,7 +4342,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4341 | wiphy->max_remain_on_channel_duration = 5000; | 4342 | wiphy->max_remain_on_channel_duration = 5000; |
4342 | brcmf_wiphy_pno_params(wiphy); | 4343 | brcmf_wiphy_pno_params(wiphy); |
4343 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | 4344 | brcmf_dbg(INFO, "Registering custom regulatory\n"); |
4344 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 4345 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
4345 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | 4346 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); |
4346 | err = wiphy_register(wiphy); | 4347 | err = wiphy_register(wiphy); |
4347 | if (err < 0) { | 4348 | if (err < 0) { |
@@ -5197,10 +5198,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | |||
5197 | if (channel & WL_CHAN_RADAR) | 5198 | if (channel & WL_CHAN_RADAR) |
5198 | band_chan_arr[index].flags |= | 5199 | band_chan_arr[index].flags |= |
5199 | (IEEE80211_CHAN_RADAR | | 5200 | (IEEE80211_CHAN_RADAR | |
5200 | IEEE80211_CHAN_NO_IBSS); | 5201 | IEEE80211_CHAN_NO_IR); |
5201 | if (channel & WL_CHAN_PASSIVE) | 5202 | if (channel & WL_CHAN_PASSIVE) |
5202 | band_chan_arr[index].flags |= | 5203 | band_chan_arr[index].flags |= |
5203 | IEEE80211_CHAN_PASSIVE_SCAN; | 5204 | IEEE80211_CHAN_NO_IR; |
5204 | } | 5205 | } |
5205 | } | 5206 | } |
5206 | if (!update) | 5207 | if (!update) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index cc87926f5055..635ae034c7e5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
@@ -59,23 +59,18 @@ | |||
59 | 59 | ||
60 | #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) | 60 | #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) |
61 | #define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ | 61 | #define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ |
62 | NL80211_RRF_PASSIVE_SCAN | \ | 62 | NL80211_RRF_NO_IR) |
63 | NL80211_RRF_NO_IBSS) | ||
64 | 63 | ||
65 | #define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ | 64 | #define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ |
66 | NL80211_RRF_PASSIVE_SCAN | \ | 65 | NL80211_RRF_NO_IR) |
67 | NL80211_RRF_NO_IBSS) | ||
68 | #define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ | 66 | #define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ |
69 | NL80211_RRF_PASSIVE_SCAN | \ | ||
70 | NL80211_RRF_DFS | \ | 67 | NL80211_RRF_DFS | \ |
71 | NL80211_RRF_NO_IBSS) | 68 | NL80211_RRF_NO_IR) |
72 | #define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ | 69 | #define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ |
73 | NL80211_RRF_PASSIVE_SCAN | \ | ||
74 | NL80211_RRF_DFS | \ | 70 | NL80211_RRF_DFS | \ |
75 | NL80211_RRF_NO_IBSS) | 71 | NL80211_RRF_NO_IR) |
76 | #define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ | 72 | #define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ |
77 | NL80211_RRF_PASSIVE_SCAN | \ | 73 | NL80211_RRF_NO_IR) |
78 | NL80211_RRF_NO_IBSS) | ||
79 | 74 | ||
80 | static const struct ieee80211_regdomain brcms_regdom_x2 = { | 75 | static const struct ieee80211_regdomain brcms_regdom_x2 = { |
81 | .n_reg_rules = 6, | 76 | .n_reg_rules = 6, |
@@ -395,7 +390,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, | |||
395 | brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); | 390 | brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); |
396 | 391 | ||
397 | brcms_b_set_chanspec(wlc->hw, chanspec, | 392 | brcms_b_set_chanspec(wlc->hw, chanspec, |
398 | !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), | 393 | !!(ch->flags & IEEE80211_CHAN_NO_IR), |
399 | &txpwr); | 394 | &txpwr); |
400 | } | 395 | } |
401 | 396 | ||
@@ -657,8 +652,8 @@ static void brcms_reg_apply_radar_flags(struct wiphy *wiphy) | |||
657 | */ | 652 | */ |
658 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) | 653 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) |
659 | ch->flags |= IEEE80211_CHAN_RADAR | | 654 | ch->flags |= IEEE80211_CHAN_RADAR | |
660 | IEEE80211_CHAN_NO_IBSS | | 655 | IEEE80211_CHAN_NO_IR | |
661 | IEEE80211_CHAN_PASSIVE_SCAN; | 656 | IEEE80211_CHAN_NO_IR; |
662 | } | 657 | } |
663 | } | 658 | } |
664 | 659 | ||
@@ -684,18 +679,15 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
684 | continue; | 679 | continue; |
685 | 680 | ||
686 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 681 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
687 | rule = freq_reg_info(wiphy, ch->center_freq); | 682 | rule = freq_reg_info(wiphy, |
683 | MHZ_TO_KHZ(ch->center_freq)); | ||
688 | if (IS_ERR(rule)) | 684 | if (IS_ERR(rule)) |
689 | continue; | 685 | continue; |
690 | 686 | ||
691 | if (!(rule->flags & NL80211_RRF_NO_IBSS)) | 687 | if (!(rule->flags & NL80211_RRF_NO_IR)) |
692 | ch->flags &= ~IEEE80211_CHAN_NO_IBSS; | 688 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
693 | if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN)) | ||
694 | ch->flags &= | ||
695 | ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
696 | } else if (ch->beacon_found) { | 689 | } else if (ch->beacon_found) { |
697 | ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | | 690 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
698 | IEEE80211_CHAN_PASSIVE_SCAN); | ||
699 | } | 691 | } |
700 | } | 692 | } |
701 | } | 693 | } |
@@ -775,8 +767,8 @@ void brcms_c_regd_init(struct brcms_c_info *wlc) | |||
775 | } | 767 | } |
776 | 768 | ||
777 | wlc->wiphy->reg_notifier = brcms_reg_notifier; | 769 | wlc->wiphy->reg_notifier = brcms_reg_notifier; |
778 | wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 770 | wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
779 | WIPHY_FLAG_STRICT_REGULATORY; | 771 | REGULATORY_STRICT_REG; |
780 | wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain); | 772 | wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain); |
781 | brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER); | 773 | brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER); |
782 | } | 774 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index edc5d105ff98..e71ce8c842a2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -125,13 +125,13 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = { | |||
125 | CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), | 125 | CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), |
126 | CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), | 126 | CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), |
127 | CHAN2GHZ(12, 2467, | 127 | CHAN2GHZ(12, 2467, |
128 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | | 128 | IEEE80211_CHAN_NO_IR | |
129 | IEEE80211_CHAN_NO_HT40PLUS), | 129 | IEEE80211_CHAN_NO_HT40PLUS), |
130 | CHAN2GHZ(13, 2472, | 130 | CHAN2GHZ(13, 2472, |
131 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | | 131 | IEEE80211_CHAN_NO_IR | |
132 | IEEE80211_CHAN_NO_HT40PLUS), | 132 | IEEE80211_CHAN_NO_HT40PLUS), |
133 | CHAN2GHZ(14, 2484, | 133 | CHAN2GHZ(14, 2484, |
134 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | | 134 | IEEE80211_CHAN_NO_IR | |
135 | IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | | 135 | IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | |
136 | IEEE80211_CHAN_NO_OFDM) | 136 | IEEE80211_CHAN_NO_OFDM) |
137 | }; | 137 | }; |
@@ -144,51 +144,51 @@ static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { | |||
144 | CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), | 144 | CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), |
145 | /* UNII-2 */ | 145 | /* UNII-2 */ |
146 | CHAN5GHZ(52, | 146 | CHAN5GHZ(52, |
147 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 147 | IEEE80211_CHAN_RADAR | |
148 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 148 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
149 | CHAN5GHZ(56, | 149 | CHAN5GHZ(56, |
150 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 150 | IEEE80211_CHAN_RADAR | |
151 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 151 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
152 | CHAN5GHZ(60, | 152 | CHAN5GHZ(60, |
153 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 153 | IEEE80211_CHAN_RADAR | |
154 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 154 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
155 | CHAN5GHZ(64, | 155 | CHAN5GHZ(64, |
156 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 156 | IEEE80211_CHAN_RADAR | |
157 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 157 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
158 | /* MID */ | 158 | /* MID */ |
159 | CHAN5GHZ(100, | 159 | CHAN5GHZ(100, |
160 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 160 | IEEE80211_CHAN_RADAR | |
161 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 161 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
162 | CHAN5GHZ(104, | 162 | CHAN5GHZ(104, |
163 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 163 | IEEE80211_CHAN_RADAR | |
164 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 164 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
165 | CHAN5GHZ(108, | 165 | CHAN5GHZ(108, |
166 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 166 | IEEE80211_CHAN_RADAR | |
167 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 167 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
168 | CHAN5GHZ(112, | 168 | CHAN5GHZ(112, |
169 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 169 | IEEE80211_CHAN_RADAR | |
170 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 170 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
171 | CHAN5GHZ(116, | 171 | CHAN5GHZ(116, |
172 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 172 | IEEE80211_CHAN_RADAR | |
173 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 173 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
174 | CHAN5GHZ(120, | 174 | CHAN5GHZ(120, |
175 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 175 | IEEE80211_CHAN_RADAR | |
176 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 176 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
177 | CHAN5GHZ(124, | 177 | CHAN5GHZ(124, |
178 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 178 | IEEE80211_CHAN_RADAR | |
179 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 179 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
180 | CHAN5GHZ(128, | 180 | CHAN5GHZ(128, |
181 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 181 | IEEE80211_CHAN_RADAR | |
182 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 182 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
183 | CHAN5GHZ(132, | 183 | CHAN5GHZ(132, |
184 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 184 | IEEE80211_CHAN_RADAR | |
185 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), | 185 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), |
186 | CHAN5GHZ(136, | 186 | CHAN5GHZ(136, |
187 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 187 | IEEE80211_CHAN_RADAR | |
188 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), | 188 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), |
189 | CHAN5GHZ(140, | 189 | CHAN5GHZ(140, |
190 | IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | | 190 | IEEE80211_CHAN_RADAR | |
191 | IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | | 191 | IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS | |
192 | IEEE80211_CHAN_NO_HT40MINUS), | 192 | IEEE80211_CHAN_NO_HT40MINUS), |
193 | /* UNII-3 */ | 193 | /* UNII-3 */ |
194 | CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), | 194 | CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), |
diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index ebdcdf44f155..d3acc85932a5 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c | |||
@@ -108,9 +108,9 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) | |||
108 | struct hwbus_priv *self = dev_id; | 108 | struct hwbus_priv *self = dev_id; |
109 | 109 | ||
110 | if (self->core) { | 110 | if (self->core) { |
111 | sdio_claim_host(self->func); | 111 | cw1200_sdio_lock(self); |
112 | cw1200_irq_handler(self->core); | 112 | cw1200_irq_handler(self->core); |
113 | sdio_release_host(self->func); | 113 | cw1200_sdio_unlock(self); |
114 | return IRQ_HANDLED; | 114 | return IRQ_HANDLED; |
115 | } else { | 115 | } else { |
116 | return IRQ_NONE; | 116 | return IRQ_NONE; |
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index ee3c19037aac..9afcd4ce3368 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c | |||
@@ -173,8 +173,9 @@ void cw1200_scan_work(struct work_struct *work) | |||
173 | cw1200_set_pm(priv, &priv->powersave_mode); | 173 | cw1200_set_pm(priv, &priv->powersave_mode); |
174 | 174 | ||
175 | if (priv->scan.status < 0) | 175 | if (priv->scan.status < 0) |
176 | wiphy_dbg(priv->hw->wiphy, "[SCAN] Scan failed (%d).\n", | 176 | wiphy_warn(priv->hw->wiphy, |
177 | priv->scan.status); | 177 | "[SCAN] Scan failed (%d).\n", |
178 | priv->scan.status); | ||
178 | else if (priv->scan.req) | 179 | else if (priv->scan.req) |
179 | wiphy_dbg(priv->hw->wiphy, | 180 | wiphy_dbg(priv->hw->wiphy, |
180 | "[SCAN] Scan completed.\n"); | 181 | "[SCAN] Scan completed.\n"); |
@@ -197,9 +198,9 @@ void cw1200_scan_work(struct work_struct *work) | |||
197 | if ((*it)->band != first->band) | 198 | if ((*it)->band != first->band) |
198 | break; | 199 | break; |
199 | if (((*it)->flags ^ first->flags) & | 200 | if (((*it)->flags ^ first->flags) & |
200 | IEEE80211_CHAN_PASSIVE_SCAN) | 201 | IEEE80211_CHAN_NO_IR) |
201 | break; | 202 | break; |
202 | if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 203 | if (!(first->flags & IEEE80211_CHAN_NO_IR) && |
203 | (*it)->max_power != first->max_power) | 204 | (*it)->max_power != first->max_power) |
204 | break; | 205 | break; |
205 | } | 206 | } |
@@ -210,7 +211,7 @@ void cw1200_scan_work(struct work_struct *work) | |||
210 | else | 211 | else |
211 | scan.max_tx_rate = WSM_TRANSMIT_RATE_1; | 212 | scan.max_tx_rate = WSM_TRANSMIT_RATE_1; |
212 | scan.num_probes = | 213 | scan.num_probes = |
213 | (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2; | 214 | (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2; |
214 | scan.num_ssids = priv->scan.n_ssids; | 215 | scan.num_ssids = priv->scan.n_ssids; |
215 | scan.ssids = &priv->scan.ssids[0]; | 216 | scan.ssids = &priv->scan.ssids[0]; |
216 | scan.num_channels = it - priv->scan.curr; | 217 | scan.num_channels = it - priv->scan.curr; |
@@ -233,7 +234,7 @@ void cw1200_scan_work(struct work_struct *work) | |||
233 | } | 234 | } |
234 | for (i = 0; i < scan.num_channels; ++i) { | 235 | for (i = 0; i < scan.num_channels; ++i) { |
235 | scan.ch[i].number = priv->scan.curr[i]->hw_value; | 236 | scan.ch[i].number = priv->scan.curr[i]->hw_value; |
236 | if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) { | 237 | if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) { |
237 | scan.ch[i].min_chan_time = 50; | 238 | scan.ch[i].min_chan_time = 50; |
238 | scan.ch[i].max_chan_time = 100; | 239 | scan.ch[i].max_chan_time = 100; |
239 | } else { | 240 | } else { |
@@ -241,7 +242,7 @@ void cw1200_scan_work(struct work_struct *work) | |||
241 | scan.ch[i].max_chan_time = 25; | 242 | scan.ch[i].max_chan_time = 25; |
242 | } | 243 | } |
243 | } | 244 | } |
244 | if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 245 | if (!(first->flags & IEEE80211_CHAN_NO_IR) && |
245 | priv->scan.output_power != first->max_power) { | 246 | priv->scan.output_power != first->max_power) { |
246 | priv->scan.output_power = first->max_power; | 247 | priv->scan.output_power = first->max_power; |
247 | wsm_set_output_power(priv, | 248 | wsm_set_output_power(priv, |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index f8ab193009cd..3aba49259ef1 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -1930,10 +1930,10 @@ static int ipw2100_wdev_init(struct net_device *dev) | |||
1930 | bg_band->channels[i].max_power = geo->bg[i].max_power; | 1930 | bg_band->channels[i].max_power = geo->bg[i].max_power; |
1931 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) | 1931 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) |
1932 | bg_band->channels[i].flags |= | 1932 | bg_band->channels[i].flags |= |
1933 | IEEE80211_CHAN_PASSIVE_SCAN; | 1933 | IEEE80211_CHAN_NO_IR; |
1934 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) | 1934 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) |
1935 | bg_band->channels[i].flags |= | 1935 | bg_band->channels[i].flags |= |
1936 | IEEE80211_CHAN_NO_IBSS; | 1936 | IEEE80211_CHAN_NO_IR; |
1937 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) | 1937 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) |
1938 | bg_band->channels[i].flags |= | 1938 | bg_band->channels[i].flags |= |
1939 | IEEE80211_CHAN_RADAR; | 1939 | IEEE80211_CHAN_RADAR; |
@@ -6362,7 +6362,6 @@ out: | |||
6362 | &ipw2100_attribute_group); | 6362 | &ipw2100_attribute_group); |
6363 | 6363 | ||
6364 | free_libipw(dev, 0); | 6364 | free_libipw(dev, 0); |
6365 | pci_set_drvdata(pci_dev, NULL); | ||
6366 | } | 6365 | } |
6367 | 6366 | ||
6368 | pci_iounmap(pci_dev, ioaddr); | 6367 | pci_iounmap(pci_dev, ioaddr); |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 81903e33d5b1..9244b3661d34 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -11472,10 +11472,10 @@ static int ipw_wdev_init(struct net_device *dev) | |||
11472 | bg_band->channels[i].max_power = geo->bg[i].max_power; | 11472 | bg_band->channels[i].max_power = geo->bg[i].max_power; |
11473 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) | 11473 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) |
11474 | bg_band->channels[i].flags |= | 11474 | bg_band->channels[i].flags |= |
11475 | IEEE80211_CHAN_PASSIVE_SCAN; | 11475 | IEEE80211_CHAN_NO_IR; |
11476 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) | 11476 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) |
11477 | bg_band->channels[i].flags |= | 11477 | bg_band->channels[i].flags |= |
11478 | IEEE80211_CHAN_NO_IBSS; | 11478 | IEEE80211_CHAN_NO_IR; |
11479 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) | 11479 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) |
11480 | bg_band->channels[i].flags |= | 11480 | bg_band->channels[i].flags |= |
11481 | IEEE80211_CHAN_RADAR; | 11481 | IEEE80211_CHAN_RADAR; |
@@ -11511,10 +11511,10 @@ static int ipw_wdev_init(struct net_device *dev) | |||
11511 | a_band->channels[i].max_power = geo->a[i].max_power; | 11511 | a_band->channels[i].max_power = geo->a[i].max_power; |
11512 | if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) | 11512 | if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) |
11513 | a_band->channels[i].flags |= | 11513 | a_band->channels[i].flags |= |
11514 | IEEE80211_CHAN_PASSIVE_SCAN; | 11514 | IEEE80211_CHAN_NO_IR; |
11515 | if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) | 11515 | if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) |
11516 | a_band->channels[i].flags |= | 11516 | a_band->channels[i].flags |= |
11517 | IEEE80211_CHAN_NO_IBSS; | 11517 | IEEE80211_CHAN_NO_IR; |
11518 | if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) | 11518 | if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) |
11519 | a_band->channels[i].flags |= | 11519 | a_band->channels[i].flags |= |
11520 | IEEE80211_CHAN_RADAR; | 11520 | IEEE80211_CHAN_RADAR; |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index dea3b50d68b9..0487461ae4da 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -1595,7 +1595,7 @@ il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band, | |||
1595 | * and use long active_dwell time. | 1595 | * and use long active_dwell time. |
1596 | */ | 1596 | */ |
1597 | if (!is_active || il_is_channel_passive(ch_info) || | 1597 | if (!is_active || il_is_channel_passive(ch_info) || |
1598 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) { | 1598 | (chan->flags & IEEE80211_CHAN_NO_IR)) { |
1599 | scan_ch->type = 0; /* passive */ | 1599 | scan_ch->type = 0; /* passive */ |
1600 | if (IL_UCODE_API(il->ucode_ver) == 1) | 1600 | if (IL_UCODE_API(il->ucode_ver) == 1) |
1601 | scan_ch->active_dwell = | 1601 | scan_ch->active_dwell = |
@@ -2396,8 +2396,7 @@ __il3945_up(struct il_priv *il) | |||
2396 | clear_bit(S_RFKILL, &il->status); | 2396 | clear_bit(S_RFKILL, &il->status); |
2397 | else { | 2397 | else { |
2398 | set_bit(S_RFKILL, &il->status); | 2398 | set_bit(S_RFKILL, &il->status); |
2399 | IL_WARN("Radio disabled by HW RF Kill switch\n"); | 2399 | return -ERFKILL; |
2400 | return -ENODEV; | ||
2401 | } | 2400 | } |
2402 | 2401 | ||
2403 | _il_wr(il, CSR_INT, 0xFFFFFFFF); | 2402 | _il_wr(il, CSR_INT, 0xFFFFFFFF); |
@@ -3575,9 +3574,9 @@ il3945_setup_mac(struct il_priv *il) | |||
3575 | hw->wiphy->interface_modes = | 3574 | hw->wiphy->interface_modes = |
3576 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | 3575 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); |
3577 | 3576 | ||
3578 | hw->wiphy->flags |= | 3577 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
3579 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 3578 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
3580 | WIPHY_FLAG_IBSS_RSN; | 3579 | REGULATORY_DISABLE_BEACON_HINTS; |
3581 | 3580 | ||
3582 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 3581 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
3583 | 3582 | ||
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 3982ab76f375..43f488a8cda2 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -805,7 +805,7 @@ il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif, | |||
805 | } | 805 | } |
806 | 806 | ||
807 | if (!is_active || il_is_channel_passive(ch_info) || | 807 | if (!is_active || il_is_channel_passive(ch_info) || |
808 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | 808 | (chan->flags & IEEE80211_CHAN_NO_IR)) |
809 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 809 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
810 | else | 810 | else |
811 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 811 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
@@ -5778,9 +5778,9 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
5778 | hw->wiphy->interface_modes = | 5778 | hw->wiphy->interface_modes = |
5779 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | 5779 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); |
5780 | 5780 | ||
5781 | hw->wiphy->flags |= | 5781 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
5782 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 5782 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
5783 | WIPHY_FLAG_IBSS_RSN; | 5783 | REGULATORY_DISABLE_BEACON_HINTS; |
5784 | 5784 | ||
5785 | /* | 5785 | /* |
5786 | * For now, disable PS by default because it affects | 5786 | * For now, disable PS by default because it affects |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index b03e22ef5462..a27b14cfeaec 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -3445,10 +3445,10 @@ il_init_geos(struct il_priv *il) | |||
3445 | 3445 | ||
3446 | if (il_is_channel_valid(ch)) { | 3446 | if (il_is_channel_valid(ch)) { |
3447 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | 3447 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) |
3448 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | 3448 | geo_ch->flags |= IEEE80211_CHAN_NO_IR; |
3449 | 3449 | ||
3450 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | 3450 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) |
3451 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 3451 | geo_ch->flags |= IEEE80211_CHAN_NO_IR; |
3452 | 3452 | ||
3453 | if (ch->flags & EEPROM_CHANNEL_RADAR) | 3453 | if (ch->flags & EEPROM_CHANNEL_RADAR) |
3454 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | 3454 | geo_ch->flags |= IEEE80211_CHAN_RADAR; |
diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index eff26501d60a..3a487a3bb5de 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c | |||
@@ -567,12 +567,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, | |||
567 | flags & IEEE80211_CHAN_RADAR ? | 567 | flags & IEEE80211_CHAN_RADAR ? |
568 | " (IEEE 802.11h required)" : "", | 568 | " (IEEE 802.11h required)" : "", |
569 | ((channels[i]. | 569 | ((channels[i]. |
570 | flags & IEEE80211_CHAN_NO_IBSS) || | 570 | flags & IEEE80211_CHAN_NO_IR) || |
571 | (channels[i]. | 571 | (channels[i]. |
572 | flags & IEEE80211_CHAN_RADAR)) ? "" : | 572 | flags & IEEE80211_CHAN_RADAR)) ? "" : |
573 | ", IBSS", | 573 | ", IBSS", |
574 | channels[i]. | 574 | channels[i]. |
575 | flags & IEEE80211_CHAN_PASSIVE_SCAN ? | 575 | flags & IEEE80211_CHAN_NO_IR ? |
576 | "passive only" : "active/passive"); | 576 | "passive only" : "active/passive"); |
577 | } | 577 | } |
578 | supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); | 578 | supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); |
@@ -594,12 +594,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, | |||
594 | flags & IEEE80211_CHAN_RADAR ? | 594 | flags & IEEE80211_CHAN_RADAR ? |
595 | " (IEEE 802.11h required)" : "", | 595 | " (IEEE 802.11h required)" : "", |
596 | ((channels[i]. | 596 | ((channels[i]. |
597 | flags & IEEE80211_CHAN_NO_IBSS) || | 597 | flags & IEEE80211_CHAN_NO_IR) || |
598 | (channels[i]. | 598 | (channels[i]. |
599 | flags & IEEE80211_CHAN_RADAR)) ? "" : | 599 | flags & IEEE80211_CHAN_RADAR)) ? "" : |
600 | ", IBSS", | 600 | ", IBSS", |
601 | channels[i]. | 601 | channels[i]. |
602 | flags & IEEE80211_CHAN_PASSIVE_SCAN ? | 602 | flags & IEEE80211_CHAN_NO_IR ? |
603 | "passive only" : "active/passive"); | 603 | "passive only" : "active/passive"); |
604 | } | 604 | } |
605 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 605 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index d94f8ab15004..f69301e505ee 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -352,12 +352,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
352 | channels[i].max_power, | 352 | channels[i].max_power, |
353 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 353 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
354 | " (IEEE 802.11h required)" : "", | 354 | " (IEEE 802.11h required)" : "", |
355 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | 355 | ((channels[i].flags & IEEE80211_CHAN_NO_IR) |
356 | || (channels[i].flags & | 356 | || (channels[i].flags & |
357 | IEEE80211_CHAN_RADAR)) ? "" : | 357 | IEEE80211_CHAN_RADAR)) ? "" : |
358 | ", IBSS", | 358 | ", IBSS", |
359 | channels[i].flags & | 359 | channels[i].flags & |
360 | IEEE80211_CHAN_PASSIVE_SCAN ? | 360 | IEEE80211_CHAN_NO_IR ? |
361 | "passive only" : "active/passive"); | 361 | "passive only" : "active/passive"); |
362 | } | 362 | } |
363 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); | 363 | supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); |
@@ -375,12 +375,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
375 | channels[i].max_power, | 375 | channels[i].max_power, |
376 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 376 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
377 | " (IEEE 802.11h required)" : "", | 377 | " (IEEE 802.11h required)" : "", |
378 | ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) | 378 | ((channels[i].flags & IEEE80211_CHAN_NO_IR) |
379 | || (channels[i].flags & | 379 | || (channels[i].flags & |
380 | IEEE80211_CHAN_RADAR)) ? "" : | 380 | IEEE80211_CHAN_RADAR)) ? "" : |
381 | ", IBSS", | 381 | ", IBSS", |
382 | channels[i].flags & | 382 | channels[i].flags & |
383 | IEEE80211_CHAN_PASSIVE_SCAN ? | 383 | IEEE80211_CHAN_NO_IR ? |
384 | "passive only" : "active/passive"); | 384 | "passive only" : "active/passive"); |
385 | } | 385 | } |
386 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 386 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cae4d3182e33..217f1ca321a0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -155,9 +155,9 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
155 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); | 155 | ARRAY_SIZE(iwlagn_iface_combinations_dualmode); |
156 | } | 156 | } |
157 | 157 | ||
158 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 158 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
159 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 159 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
160 | WIPHY_FLAG_IBSS_RSN; | 160 | REGULATORY_DISABLE_BEACON_HINTS; |
161 | 161 | ||
162 | #ifdef CONFIG_PM_SLEEP | 162 | #ifdef CONFIG_PM_SLEEP |
163 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | 163 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 35e0ee8b4e5b..928f8640a0a7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -544,7 +544,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
544 | channel = chan->hw_value; | 544 | channel = chan->hw_value; |
545 | scan_ch->channel = cpu_to_le16(channel); | 545 | scan_ch->channel = cpu_to_le16(channel); |
546 | 546 | ||
547 | if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | 547 | if (!is_active || (chan->flags & IEEE80211_CHAN_NO_IR)) |
548 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 548 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
549 | else | 549 | else |
550 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 550 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 4c887f365908..f4a6d317a023 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -614,10 +614,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
614 | channel->flags = IEEE80211_CHAN_NO_HT40; | 614 | channel->flags = IEEE80211_CHAN_NO_HT40; |
615 | 615 | ||
616 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) | 616 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) |
617 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | 617 | channel->flags |= IEEE80211_CHAN_NO_IR; |
618 | 618 | ||
619 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) | 619 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) |
620 | channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 620 | channel->flags |= IEEE80211_CHAN_NO_IR; |
621 | 621 | ||
622 | if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) | 622 | if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) |
623 | channel->flags |= IEEE80211_CHAN_RADAR; | 623 | channel->flags |= IEEE80211_CHAN_RADAR; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index b76a9a8fc0b3..2fab203d3027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -223,10 +223,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
223 | channel->flags |= IEEE80211_CHAN_NO_160MHZ; | 223 | channel->flags |= IEEE80211_CHAN_NO_160MHZ; |
224 | 224 | ||
225 | if (!(ch_flags & NVM_CHANNEL_IBSS)) | 225 | if (!(ch_flags & NVM_CHANNEL_IBSS)) |
226 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | 226 | channel->flags |= IEEE80211_CHAN_NO_IR; |
227 | 227 | ||
228 | if (!(ch_flags & NVM_CHANNEL_ACTIVE)) | 228 | if (!(ch_flags & NVM_CHANNEL_ACTIVE)) |
229 | channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 229 | channel->flags |= IEEE80211_CHAN_NO_IR; |
230 | 230 | ||
231 | if (ch_flags & NVM_CHANNEL_RADAR) | 231 | if (ch_flags & NVM_CHANNEL_RADAR) |
232 | channel->flags |= IEEE80211_CHAN_RADAR; | 232 | channel->flags |= IEEE80211_CHAN_RADAR; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 74bc2c8af06d..b56c989ad784 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -199,9 +199,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
199 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | 199 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) |
200 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | 200 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); |
201 | 201 | ||
202 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 202 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
203 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 203 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
204 | WIPHY_FLAG_IBSS_RSN; | 204 | REGULATORY_DISABLE_BEACON_HINTS; |
205 | 205 | ||
206 | hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; | 206 | hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; |
207 | hw->wiphy->n_iface_combinations = | 207 | hw->wiphy->n_iface_combinations = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index dff7592e1ff8..e0cd100b40cd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -192,7 +192,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | |||
192 | for (i = 0; i < cmd->channel_count; i++) { | 192 | for (i = 0; i < cmd->channel_count; i++) { |
193 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); | 193 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); |
194 | chan->type = cpu_to_le32(type); | 194 | chan->type = cpu_to_le32(type); |
195 | if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 195 | if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) |
196 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); | 196 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); |
197 | chan->active_dwell = cpu_to_le16(active_dwell); | 197 | chan->active_dwell = cpu_to_le16(active_dwell); |
198 | chan->passive_dwell = cpu_to_le16(passive_dwell); | 198 | chan->passive_dwell = cpu_to_le16(passive_dwell); |
@@ -642,7 +642,7 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | |||
642 | channels->iter_count[index] = cpu_to_le16(1); | 642 | channels->iter_count[index] = cpu_to_le16(1); |
643 | channels->iter_interval[index] = 0; | 643 | channels->iter_interval[index] = 0; |
644 | 644 | ||
645 | if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) | 645 | if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR)) |
646 | channels->type[index] |= | 646 | channels->type[index] |= |
647 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); | 647 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); |
648 | 648 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 991238afd1b6..58c6ee5de98f 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -849,7 +849,7 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
849 | card->started = true; | 849 | card->started = true; |
850 | /* Tell PM core that we don't need the card to be | 850 | /* Tell PM core that we don't need the card to be |
851 | * powered now */ | 851 | * powered now */ |
852 | pm_runtime_put_noidle(&func->dev); | 852 | pm_runtime_put(&func->dev); |
853 | } | 853 | } |
854 | } | 854 | } |
855 | 855 | ||
@@ -907,8 +907,8 @@ static int if_sdio_power_on(struct if_sdio_card *card) | |||
907 | sdio_release_host(func); | 907 | sdio_release_host(func); |
908 | ret = if_sdio_prog_firmware(card); | 908 | ret = if_sdio_prog_firmware(card); |
909 | if (ret) { | 909 | if (ret) { |
910 | sdio_disable_func(func); | 910 | sdio_claim_host(func); |
911 | return ret; | 911 | goto disable; |
912 | } | 912 | } |
913 | 913 | ||
914 | return 0; | 914 | return 0; |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 83669151bb82..f11728a866ff 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -93,7 +93,6 @@ static void free_if_spi_card(struct if_spi_card *card) | |||
93 | list_del(&packet->list); | 93 | list_del(&packet->list); |
94 | kfree(packet); | 94 | kfree(packet); |
95 | } | 95 | } |
96 | spi_set_drvdata(card->spi, NULL); | ||
97 | kfree(card); | 96 | kfree(card); |
98 | } | 97 | } |
99 | 98 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c72438bb2faf..9c0cc8ded021 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -159,7 +159,7 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { | |||
159 | .reg_rules = { | 159 | .reg_rules = { |
160 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), | 160 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), |
161 | REG_RULE(5725-10, 5850+10, 40, 0, 30, | 161 | REG_RULE(5725-10, 5850+10, 40, 0, 30, |
162 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), | 162 | NL80211_RRF_NO_IR), |
163 | } | 163 | } |
164 | }; | 164 | }; |
165 | 165 | ||
@@ -353,7 +353,6 @@ struct mac80211_hwsim_data { | |||
353 | } ps; | 353 | } ps; |
354 | bool ps_poll_pending; | 354 | bool ps_poll_pending; |
355 | struct dentry *debugfs; | 355 | struct dentry *debugfs; |
356 | struct dentry *debugfs_ps; | ||
357 | 356 | ||
358 | struct sk_buff_head pending; /* packets pending */ | 357 | struct sk_buff_head pending; /* packets pending */ |
359 | /* | 358 | /* |
@@ -362,7 +361,6 @@ struct mac80211_hwsim_data { | |||
362 | * radio can be in more then one group. | 361 | * radio can be in more then one group. |
363 | */ | 362 | */ |
364 | u64 group; | 363 | u64 group; |
365 | struct dentry *debugfs_group; | ||
366 | 364 | ||
367 | int power_level; | 365 | int power_level; |
368 | 366 | ||
@@ -1493,7 +1491,7 @@ static void hw_scan_work(struct work_struct *work) | |||
1493 | req->channels[hwsim->scan_chan_idx]->center_freq); | 1491 | req->channels[hwsim->scan_chan_idx]->center_freq); |
1494 | 1492 | ||
1495 | hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; | 1493 | hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; |
1496 | if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | 1494 | if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR || |
1497 | !req->n_ssids) { | 1495 | !req->n_ssids) { |
1498 | dwell = 120; | 1496 | dwell = 120; |
1499 | } else { | 1497 | } else { |
@@ -1742,9 +1740,7 @@ static void mac80211_hwsim_free(void) | |||
1742 | spin_unlock_bh(&hwsim_radio_lock); | 1740 | spin_unlock_bh(&hwsim_radio_lock); |
1743 | 1741 | ||
1744 | list_for_each_entry_safe(data, tmpdata, &tmplist, list) { | 1742 | list_for_each_entry_safe(data, tmpdata, &tmplist, list) { |
1745 | debugfs_remove(data->debugfs_group); | 1743 | debugfs_remove_recursive(data->debugfs); |
1746 | debugfs_remove(data->debugfs_ps); | ||
1747 | debugfs_remove(data->debugfs); | ||
1748 | ieee80211_unregister_hw(data->hw); | 1744 | ieee80211_unregister_hw(data->hw); |
1749 | device_release_driver(data->dev); | 1745 | device_release_driver(data->dev); |
1750 | device_unregister(data->dev); | 1746 | device_unregister(data->dev); |
@@ -1901,6 +1897,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val) | |||
1901 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, | 1897 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, |
1902 | "%llu\n"); | 1898 | "%llu\n"); |
1903 | 1899 | ||
1900 | static int hwsim_write_simulate_radar(void *dat, u64 val) | ||
1901 | { | ||
1902 | struct mac80211_hwsim_data *data = dat; | ||
1903 | |||
1904 | ieee80211_radar_detected(data->hw); | ||
1905 | |||
1906 | return 0; | ||
1907 | } | ||
1908 | |||
1909 | DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL, | ||
1910 | hwsim_write_simulate_radar, "%llu\n"); | ||
1904 | 1911 | ||
1905 | static int hwsim_fops_group_read(void *dat, u64 *val) | 1912 | static int hwsim_fops_group_read(void *dat, u64 *val) |
1906 | { | 1913 | { |
@@ -2201,11 +2208,28 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { | |||
2201 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | 2208 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, |
2202 | }; | 2209 | }; |
2203 | 2210 | ||
2204 | static struct ieee80211_iface_combination hwsim_if_comb = { | 2211 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { |
2205 | .limits = hwsim_if_limits, | 2212 | { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, |
2206 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | 2213 | }; |
2207 | .max_interfaces = 2048, | 2214 | |
2208 | .num_different_channels = 1, | 2215 | static struct ieee80211_iface_combination hwsim_if_comb[] = { |
2216 | { | ||
2217 | .limits = hwsim_if_limits, | ||
2218 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | ||
2219 | .max_interfaces = 2048, | ||
2220 | .num_different_channels = 1, | ||
2221 | }, | ||
2222 | { | ||
2223 | .limits = hwsim_if_dfs_limits, | ||
2224 | .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits), | ||
2225 | .max_interfaces = 8, | ||
2226 | .num_different_channels = 1, | ||
2227 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
2228 | BIT(NL80211_CHAN_WIDTH_20) | | ||
2229 | BIT(NL80211_CHAN_WIDTH_40) | | ||
2230 | BIT(NL80211_CHAN_WIDTH_80) | | ||
2231 | BIT(NL80211_CHAN_WIDTH_160), | ||
2232 | } | ||
2209 | }; | 2233 | }; |
2210 | 2234 | ||
2211 | static int __init init_mac80211_hwsim(void) | 2235 | static int __init init_mac80211_hwsim(void) |
@@ -2223,7 +2247,7 @@ static int __init init_mac80211_hwsim(void) | |||
2223 | return -EINVAL; | 2247 | return -EINVAL; |
2224 | 2248 | ||
2225 | if (channels > 1) { | 2249 | if (channels > 1) { |
2226 | hwsim_if_comb.num_different_channels = channels; | 2250 | hwsim_if_comb[0].num_different_channels = channels; |
2227 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | 2251 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; |
2228 | mac80211_hwsim_ops.cancel_hw_scan = | 2252 | mac80211_hwsim_ops.cancel_hw_scan = |
2229 | mac80211_hwsim_cancel_hw_scan; | 2253 | mac80211_hwsim_cancel_hw_scan; |
@@ -2303,13 +2327,15 @@ static int __init init_mac80211_hwsim(void) | |||
2303 | hw->wiphy->n_addresses = 2; | 2327 | hw->wiphy->n_addresses = 2; |
2304 | hw->wiphy->addresses = data->addresses; | 2328 | hw->wiphy->addresses = data->addresses; |
2305 | 2329 | ||
2306 | hw->wiphy->iface_combinations = &hwsim_if_comb; | 2330 | hw->wiphy->iface_combinations = hwsim_if_comb; |
2307 | hw->wiphy->n_iface_combinations = 1; | 2331 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); |
2308 | 2332 | ||
2309 | if (channels > 1) { | 2333 | if (channels > 1) { |
2310 | hw->wiphy->max_scan_ssids = 255; | 2334 | hw->wiphy->max_scan_ssids = 255; |
2311 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | 2335 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; |
2312 | hw->wiphy->max_remain_on_channel_duration = 1000; | 2336 | hw->wiphy->max_remain_on_channel_duration = 1000; |
2337 | /* For channels > 1 DFS is not allowed */ | ||
2338 | hw->wiphy->n_iface_combinations = 1; | ||
2313 | } | 2339 | } |
2314 | 2340 | ||
2315 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); | 2341 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); |
@@ -2333,7 +2359,8 @@ static int __init init_mac80211_hwsim(void) | |||
2333 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 2359 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
2334 | IEEE80211_HW_AMPDU_AGGREGATION | | 2360 | IEEE80211_HW_AMPDU_AGGREGATION | |
2335 | IEEE80211_HW_WANT_MONITOR_VIF | | 2361 | IEEE80211_HW_WANT_MONITOR_VIF | |
2336 | IEEE80211_HW_QUEUE_CONTROL; | 2362 | IEEE80211_HW_QUEUE_CONTROL | |
2363 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | ||
2337 | if (rctbl) | 2364 | if (rctbl) |
2338 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | 2365 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; |
2339 | 2366 | ||
@@ -2393,6 +2420,7 @@ static int __init init_mac80211_hwsim(void) | |||
2393 | sband->vht_cap.cap = | 2420 | sband->vht_cap.cap = |
2394 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | 2421 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | |
2395 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | 2422 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | |
2423 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | ||
2396 | IEEE80211_VHT_CAP_RXLDPC | | 2424 | IEEE80211_VHT_CAP_RXLDPC | |
2397 | IEEE80211_VHT_CAP_SHORT_GI_80 | | 2425 | IEEE80211_VHT_CAP_SHORT_GI_80 | |
2398 | IEEE80211_VHT_CAP_SHORT_GI_160 | | 2426 | IEEE80211_VHT_CAP_SHORT_GI_160 | |
@@ -2435,46 +2463,53 @@ static int __init init_mac80211_hwsim(void) | |||
2435 | break; | 2463 | break; |
2436 | case HWSIM_REGTEST_WORLD_ROAM: | 2464 | case HWSIM_REGTEST_WORLD_ROAM: |
2437 | if (i == 0) { | 2465 | if (i == 0) { |
2438 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2466 | hw->wiphy->regulatory_flags |= |
2467 | REGULATORY_CUSTOM_REG; | ||
2439 | wiphy_apply_custom_regulatory(hw->wiphy, | 2468 | wiphy_apply_custom_regulatory(hw->wiphy, |
2440 | &hwsim_world_regdom_custom_01); | 2469 | &hwsim_world_regdom_custom_01); |
2441 | } | 2470 | } |
2442 | break; | 2471 | break; |
2443 | case HWSIM_REGTEST_CUSTOM_WORLD: | 2472 | case HWSIM_REGTEST_CUSTOM_WORLD: |
2444 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2473 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
2445 | wiphy_apply_custom_regulatory(hw->wiphy, | 2474 | wiphy_apply_custom_regulatory(hw->wiphy, |
2446 | &hwsim_world_regdom_custom_01); | 2475 | &hwsim_world_regdom_custom_01); |
2447 | break; | 2476 | break; |
2448 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | 2477 | case HWSIM_REGTEST_CUSTOM_WORLD_2: |
2449 | if (i == 0) { | 2478 | if (i == 0) { |
2450 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2479 | hw->wiphy->regulatory_flags |= |
2480 | REGULATORY_CUSTOM_REG; | ||
2451 | wiphy_apply_custom_regulatory(hw->wiphy, | 2481 | wiphy_apply_custom_regulatory(hw->wiphy, |
2452 | &hwsim_world_regdom_custom_01); | 2482 | &hwsim_world_regdom_custom_01); |
2453 | } else if (i == 1) { | 2483 | } else if (i == 1) { |
2454 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2484 | hw->wiphy->regulatory_flags |= |
2485 | REGULATORY_CUSTOM_REG; | ||
2455 | wiphy_apply_custom_regulatory(hw->wiphy, | 2486 | wiphy_apply_custom_regulatory(hw->wiphy, |
2456 | &hwsim_world_regdom_custom_02); | 2487 | &hwsim_world_regdom_custom_02); |
2457 | } | 2488 | } |
2458 | break; | 2489 | break; |
2459 | case HWSIM_REGTEST_STRICT_ALL: | 2490 | case HWSIM_REGTEST_STRICT_ALL: |
2460 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; | 2491 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; |
2461 | break; | 2492 | break; |
2462 | case HWSIM_REGTEST_STRICT_FOLLOW: | 2493 | case HWSIM_REGTEST_STRICT_FOLLOW: |
2463 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | 2494 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: |
2464 | if (i == 0) | 2495 | if (i == 0) |
2465 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; | 2496 | hw->wiphy->regulatory_flags |= |
2497 | REGULATORY_STRICT_REG; | ||
2466 | break; | 2498 | break; |
2467 | case HWSIM_REGTEST_ALL: | 2499 | case HWSIM_REGTEST_ALL: |
2468 | if (i == 0) { | 2500 | if (i == 0) { |
2469 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2501 | hw->wiphy->regulatory_flags |= |
2502 | REGULATORY_CUSTOM_REG; | ||
2470 | wiphy_apply_custom_regulatory(hw->wiphy, | 2503 | wiphy_apply_custom_regulatory(hw->wiphy, |
2471 | &hwsim_world_regdom_custom_01); | 2504 | &hwsim_world_regdom_custom_01); |
2472 | } else if (i == 1) { | 2505 | } else if (i == 1) { |
2473 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 2506 | hw->wiphy->regulatory_flags |= |
2507 | REGULATORY_CUSTOM_REG; | ||
2474 | wiphy_apply_custom_regulatory(hw->wiphy, | 2508 | wiphy_apply_custom_regulatory(hw->wiphy, |
2475 | &hwsim_world_regdom_custom_02); | 2509 | &hwsim_world_regdom_custom_02); |
2476 | } else if (i == 4) | 2510 | } else if (i == 4) |
2477 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; | 2511 | hw->wiphy->regulatory_flags |= |
2512 | REGULATORY_STRICT_REG; | ||
2478 | break; | 2513 | break; |
2479 | default: | 2514 | default: |
2480 | break; | 2515 | break; |
@@ -2541,16 +2576,18 @@ static int __init init_mac80211_hwsim(void) | |||
2541 | 2576 | ||
2542 | data->debugfs = debugfs_create_dir("hwsim", | 2577 | data->debugfs = debugfs_create_dir("hwsim", |
2543 | hw->wiphy->debugfsdir); | 2578 | hw->wiphy->debugfsdir); |
2544 | data->debugfs_ps = debugfs_create_file("ps", 0666, | 2579 | debugfs_create_file("ps", 0666, data->debugfs, data, |
2545 | data->debugfs, data, | 2580 | &hwsim_fops_ps); |
2546 | &hwsim_fops_ps); | 2581 | debugfs_create_file("group", 0666, data->debugfs, data, |
2547 | data->debugfs_group = debugfs_create_file("group", 0666, | 2582 | &hwsim_fops_group); |
2548 | data->debugfs, data, | 2583 | if (channels == 1) |
2549 | &hwsim_fops_group); | 2584 | debugfs_create_file("dfs_simulate_radar", 0222, |
2585 | data->debugfs, | ||
2586 | data, &hwsim_simulate_radar); | ||
2550 | 2587 | ||
2551 | tasklet_hrtimer_init(&data->beacon_timer, | 2588 | tasklet_hrtimer_init(&data->beacon_timer, |
2552 | mac80211_hwsim_beacon, | 2589 | mac80211_hwsim_beacon, |
2553 | CLOCK_REALTIME, HRTIMER_MODE_ABS); | 2590 | CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); |
2554 | 2591 | ||
2555 | list_add_tail(&data->list, &hwsim_radios); | 2592 | list_add_tail(&data->list, &hwsim_radios); |
2556 | } | 2593 | } |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index aeaea0e3b4c4..d9b7330c902f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -50,24 +50,24 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { | |||
50 | REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), | 50 | REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), |
51 | /* Channel 12 - 13 */ | 51 | /* Channel 12 - 13 */ |
52 | REG_RULE(2467-10, 2472+10, 20, 3, 20, | 52 | REG_RULE(2467-10, 2472+10, 20, 3, 20, |
53 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), | 53 | NL80211_RRF_NO_IR), |
54 | /* Channel 14 */ | 54 | /* Channel 14 */ |
55 | REG_RULE(2484-10, 2484+10, 20, 3, 20, | 55 | REG_RULE(2484-10, 2484+10, 20, 3, 20, |
56 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | | 56 | NL80211_RRF_NO_IR | |
57 | NL80211_RRF_NO_OFDM), | 57 | NL80211_RRF_NO_OFDM), |
58 | /* Channel 36 - 48 */ | 58 | /* Channel 36 - 48 */ |
59 | REG_RULE(5180-10, 5240+10, 40, 3, 20, | 59 | REG_RULE(5180-10, 5240+10, 40, 3, 20, |
60 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), | 60 | NL80211_RRF_NO_IR), |
61 | /* Channel 149 - 165 */ | 61 | /* Channel 149 - 165 */ |
62 | REG_RULE(5745-10, 5825+10, 40, 3, 20, | 62 | REG_RULE(5745-10, 5825+10, 40, 3, 20, |
63 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), | 63 | NL80211_RRF_NO_IR), |
64 | /* Channel 52 - 64 */ | 64 | /* Channel 52 - 64 */ |
65 | REG_RULE(5260-10, 5320+10, 40, 3, 30, | 65 | REG_RULE(5260-10, 5320+10, 40, 3, 30, |
66 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | | 66 | NL80211_RRF_NO_IR | |
67 | NL80211_RRF_DFS), | 67 | NL80211_RRF_DFS), |
68 | /* Channel 100 - 140 */ | 68 | /* Channel 100 - 140 */ |
69 | REG_RULE(5500-10, 5700+10, 40, 3, 30, | 69 | REG_RULE(5500-10, 5700+10, 40, 3, 30, |
70 | NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | | 70 | NL80211_RRF_NO_IR | |
71 | NL80211_RRF_DFS), | 71 | NL80211_RRF_DFS), |
72 | } | 72 | } |
73 | }; | 73 | }; |
@@ -184,10 +184,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) | |||
184 | */ | 184 | */ |
185 | static int | 185 | static int |
186 | mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 186 | mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
187 | struct ieee80211_channel *chan, bool offchan, | 187 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) |
188 | unsigned int wait, const u8 *buf, size_t len, | ||
189 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
190 | { | 188 | { |
189 | const u8 *buf = params->buf; | ||
190 | size_t len = params->len; | ||
191 | struct sk_buff *skb; | 191 | struct sk_buff *skb; |
192 | u16 pkt_len; | 192 | u16 pkt_len; |
193 | const struct ieee80211_mgmt *mgmt; | 193 | const struct ieee80211_mgmt *mgmt; |
@@ -1968,7 +1968,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1968 | user_scan_cfg->chan_list[i].chan_number = chan->hw_value; | 1968 | user_scan_cfg->chan_list[i].chan_number = chan->hw_value; |
1969 | user_scan_cfg->chan_list[i].radio_type = chan->band; | 1969 | user_scan_cfg->chan_list[i].radio_type = chan->band; |
1970 | 1970 | ||
1971 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 1971 | if (chan->flags & IEEE80211_CHAN_NO_IR) |
1972 | user_scan_cfg->chan_list[i].scan_type = | 1972 | user_scan_cfg->chan_list[i].scan_type = |
1973 | MWIFIEX_SCAN_TYPE_PASSIVE; | 1973 | MWIFIEX_SCAN_TYPE_PASSIVE; |
1974 | else | 1974 | else |
@@ -2702,9 +2702,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2702 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 2702 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
2703 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 2703 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
2704 | WIPHY_FLAG_AP_UAPSD | | 2704 | WIPHY_FLAG_AP_UAPSD | |
2705 | WIPHY_FLAG_CUSTOM_REGULATORY | | ||
2706 | WIPHY_FLAG_STRICT_REGULATORY | | ||
2707 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2705 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
2706 | wiphy->regulatory_flags |= | ||
2707 | REGULATORY_CUSTOM_REG | | ||
2708 | REGULATORY_STRICT_REG; | ||
2708 | 2709 | ||
2709 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); | 2710 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); |
2710 | 2711 | ||
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 8cf7d50a7603..0ed06646f19a 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -515,14 +515,14 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
515 | scan_chan_list[chan_idx].max_scan_time = | 515 | scan_chan_list[chan_idx].max_scan_time = |
516 | cpu_to_le16((u16) user_scan_in-> | 516 | cpu_to_le16((u16) user_scan_in-> |
517 | chan_list[0].scan_time); | 517 | chan_list[0].scan_time); |
518 | else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 518 | else if (ch->flags & IEEE80211_CHAN_NO_IR) |
519 | scan_chan_list[chan_idx].max_scan_time = | 519 | scan_chan_list[chan_idx].max_scan_time = |
520 | cpu_to_le16(adapter->passive_scan_time); | 520 | cpu_to_le16(adapter->passive_scan_time); |
521 | else | 521 | else |
522 | scan_chan_list[chan_idx].max_scan_time = | 522 | scan_chan_list[chan_idx].max_scan_time = |
523 | cpu_to_le16(adapter->active_scan_time); | 523 | cpu_to_le16(adapter->active_scan_time); |
524 | 524 | ||
525 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 525 | if (ch->flags & IEEE80211_CHAN_NO_IR) |
526 | scan_chan_list[chan_idx].chan_scan_mode_bitmap | 526 | scan_chan_list[chan_idx].chan_scan_mode_bitmap |
527 | |= MWIFIEX_PASSIVE_SCAN; | 527 | |= MWIFIEX_PASSIVE_SCAN; |
528 | else | 528 | else |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 2675ca7f8d14..551194605aa7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -338,8 +338,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) | |||
338 | if (!data_buf) | 338 | if (!data_buf) |
339 | return -1; | 339 | return -1; |
340 | 340 | ||
341 | pg_tlv_hdr = (struct mwifiex_types_power_group *) | 341 | pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf); |
342 | ((u8 *) data_buf + sizeof(struct host_cmd_ds_txpwr_cfg)); | ||
343 | pg = (struct mwifiex_power_group *) | 342 | pg = (struct mwifiex_power_group *) |
344 | ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group)); | 343 | ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group)); |
345 | length = le16_to_cpu(pg_tlv_hdr->length); | 344 | length = le16_to_cpu(pg_tlv_hdr->length); |
@@ -383,19 +382,25 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, | |||
383 | struct mwifiex_types_power_group *pg_tlv_hdr; | 382 | struct mwifiex_types_power_group *pg_tlv_hdr; |
384 | struct mwifiex_power_group *pg; | 383 | struct mwifiex_power_group *pg; |
385 | u16 action = le16_to_cpu(txp_cfg->action); | 384 | u16 action = le16_to_cpu(txp_cfg->action); |
385 | u16 tlv_buf_left; | ||
386 | 386 | ||
387 | switch (action) { | 387 | pg_tlv_hdr = (struct mwifiex_types_power_group *) |
388 | case HostCmd_ACT_GEN_GET: | 388 | ((u8 *)txp_cfg + |
389 | pg_tlv_hdr = (struct mwifiex_types_power_group *) | 389 | sizeof(struct host_cmd_ds_txpwr_cfg)); |
390 | ((u8 *) txp_cfg + | ||
391 | sizeof(struct host_cmd_ds_txpwr_cfg)); | ||
392 | 390 | ||
393 | pg = (struct mwifiex_power_group *) | 391 | pg = (struct mwifiex_power_group *) |
394 | ((u8 *) pg_tlv_hdr + | 392 | ((u8 *)pg_tlv_hdr + |
395 | sizeof(struct mwifiex_types_power_group)); | 393 | sizeof(struct mwifiex_types_power_group)); |
396 | 394 | ||
395 | tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); | ||
396 | if (tlv_buf_left < | ||
397 | le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) | ||
398 | return 0; | ||
399 | |||
400 | switch (action) { | ||
401 | case HostCmd_ACT_GEN_GET: | ||
397 | if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) | 402 | if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) |
398 | mwifiex_get_power_level(priv, txp_cfg); | 403 | mwifiex_get_power_level(priv, pg_tlv_hdr); |
399 | 404 | ||
400 | priv->tx_power_level = (u16) pg->power_min; | 405 | priv->tx_power_level = (u16) pg->power_min; |
401 | break; | 406 | break; |
@@ -404,14 +409,6 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, | |||
404 | if (!le32_to_cpu(txp_cfg->mode)) | 409 | if (!le32_to_cpu(txp_cfg->mode)) |
405 | break; | 410 | break; |
406 | 411 | ||
407 | pg_tlv_hdr = (struct mwifiex_types_power_group *) | ||
408 | ((u8 *) txp_cfg + | ||
409 | sizeof(struct host_cmd_ds_txpwr_cfg)); | ||
410 | |||
411 | pg = (struct mwifiex_power_group *) | ||
412 | ((u8 *) pg_tlv_hdr + | ||
413 | sizeof(struct mwifiex_types_power_group)); | ||
414 | |||
415 | if (pg->power_max == pg->power_min) | 412 | if (pg->power_max == pg->power_min) |
416 | priv->tx_power_level = (u16) pg->power_min; | 413 | priv->tx_power_level = (u16) pg->power_min; |
417 | break; | 414 | break; |
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index e05d9b4c8317..7fa2898d0619 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -914,7 +914,6 @@ islpci_setup(struct pci_dev *pdev) | |||
914 | do_islpci_free_memory: | 914 | do_islpci_free_memory: |
915 | islpci_free_memory(priv); | 915 | islpci_free_memory(priv); |
916 | do_free_netdev: | 916 | do_free_netdev: |
917 | pci_set_drvdata(pdev, NULL); | ||
918 | free_netdev(ndev); | 917 | free_netdev(ndev); |
919 | priv = NULL; | 918 | priv = NULL; |
920 | return NULL; | 919 | return NULL; |
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 9e68e0cb718e..d7b9e6376424 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c | |||
@@ -199,7 +199,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
199 | do_unregister_netdev: | 199 | do_unregister_netdev: |
200 | unregister_netdev(ndev); | 200 | unregister_netdev(ndev); |
201 | islpci_free_memory(priv); | 201 | islpci_free_memory(priv); |
202 | pci_set_drvdata(pdev, NULL); | ||
203 | free_netdev(ndev); | 202 | free_netdev(ndev); |
204 | priv = NULL; | 203 | priv = NULL; |
205 | do_pci_clear_mwi: | 204 | do_pci_clear_mwi: |
@@ -247,7 +246,6 @@ prism54_remove(struct pci_dev *pdev) | |||
247 | /* free the PCI memory and unmap the remapped page */ | 246 | /* free the PCI memory and unmap the remapped page */ |
248 | islpci_free_memory(priv); | 247 | islpci_free_memory(priv); |
249 | 248 | ||
250 | pci_set_drvdata(pdev, NULL); | ||
251 | free_netdev(ndev); | 249 | free_netdev(ndev); |
252 | priv = NULL; | 250 | priv = NULL; |
253 | 251 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 776aff3678ff..5ee5b296ad28 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -5462,15 +5462,14 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) | |||
5462 | 5462 | ||
5463 | rt2800_bbp_write(rt2x00dev, 68, 0x0b); | 5463 | rt2800_bbp_write(rt2x00dev, 68, 0x0b); |
5464 | 5464 | ||
5465 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | 5465 | rt2800_bbp_write(rt2x00dev, 69, 0x0d); |
5466 | rt2800_bbp_write(rt2x00dev, 70, 0x06); | ||
5466 | rt2800_bbp_write(rt2x00dev, 73, 0x13); | 5467 | rt2800_bbp_write(rt2x00dev, 73, 0x13); |
5467 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 5468 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
5468 | rt2800_bbp_write(rt2x00dev, 76, 0x28); | 5469 | rt2800_bbp_write(rt2x00dev, 76, 0x28); |
5469 | 5470 | ||
5470 | rt2800_bbp_write(rt2x00dev, 77, 0x59); | 5471 | rt2800_bbp_write(rt2x00dev, 77, 0x59); |
5471 | 5472 | ||
5472 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
5473 | |||
5474 | rt2800_bbp_write(rt2x00dev, 79, 0x13); | 5473 | rt2800_bbp_write(rt2x00dev, 79, 0x13); |
5475 | rt2800_bbp_write(rt2x00dev, 80, 0x05); | 5474 | rt2800_bbp_write(rt2x00dev, 80, 0x05); |
5476 | rt2800_bbp_write(rt2x00dev, 81, 0x33); | 5475 | rt2800_bbp_write(rt2x00dev, 81, 0x33); |
@@ -5513,6 +5512,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) | |||
5513 | if (rt2x00_rt(rt2x00dev, RT5392)) { | 5512 | if (rt2x00_rt(rt2x00dev, RT5392)) { |
5514 | rt2800_bbp_write(rt2x00dev, 134, 0xd0); | 5513 | rt2800_bbp_write(rt2x00dev, 134, 0xd0); |
5515 | rt2800_bbp_write(rt2x00dev, 135, 0xf6); | 5514 | rt2800_bbp_write(rt2x00dev, 135, 0xf6); |
5515 | rt2800_bbp_write(rt2x00dev, 148, 0x84); | ||
5516 | } | 5516 | } |
5517 | 5517 | ||
5518 | rt2800_disable_unused_dac_adc(rt2x00dev); | 5518 | rt2800_disable_unused_dac_adc(rt2x00dev); |
@@ -6453,7 +6453,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6453 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | 6453 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); |
6454 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | 6454 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); |
6455 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | 6455 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); |
6456 | rt2800_rfcsr_write(rt2x00dev, 12, 0xc6); | 6456 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); |
6457 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | 6457 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); |
6458 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | 6458 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); |
6459 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | 6459 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); |
@@ -6466,7 +6466,8 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6466 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | 6466 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); |
6467 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); | 6467 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); |
6468 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); | 6468 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); |
6469 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | 6469 | if (rt2x00_is_usb(rt2x00dev) && |
6470 | rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
6470 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | 6471 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); |
6471 | else | 6472 | else |
6472 | rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); | 6473 | rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); |
@@ -6486,10 +6487,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6486 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | 6487 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); |
6487 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | 6488 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); |
6488 | 6489 | ||
6489 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | 6490 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); |
6490 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
6491 | else | ||
6492 | rt2800_rfcsr_write(rt2x00dev, 40, 0x4b); | ||
6493 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | 6491 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); |
6494 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); | 6492 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); |
6495 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); | 6493 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); |
@@ -6510,16 +6508,26 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6510 | rt2800_rfcsr_write(rt2x00dev, 53, 0x84); | 6508 | rt2800_rfcsr_write(rt2x00dev, 53, 0x84); |
6511 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | 6509 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); |
6512 | rt2800_rfcsr_write(rt2x00dev, 55, 0x44); | 6510 | rt2800_rfcsr_write(rt2x00dev, 55, 0x44); |
6513 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | 6511 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) |
6512 | rt2800_rfcsr_write(rt2x00dev, 56, 0x42); | ||
6513 | else | ||
6514 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | ||
6514 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | 6515 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); |
6515 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | 6516 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); |
6516 | rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); | 6517 | rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); |
6517 | 6518 | ||
6518 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | 6519 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); |
6519 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | 6520 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { |
6520 | rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); | 6521 | if (rt2x00_is_usb(rt2x00dev)) |
6521 | else | 6522 | rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); |
6522 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); | 6523 | else |
6524 | rt2800_rfcsr_write(rt2x00dev, 61, 0xd5); | ||
6525 | } else { | ||
6526 | if (rt2x00_is_usb(rt2x00dev)) | ||
6527 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); | ||
6528 | else | ||
6529 | rt2800_rfcsr_write(rt2x00dev, 61, 0xb5); | ||
6530 | } | ||
6523 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | 6531 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); |
6524 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | 6532 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); |
6525 | 6533 | ||
@@ -6602,7 +6610,6 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) | |||
6602 | 6610 | ||
6603 | rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); | 6611 | rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); |
6604 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | 6612 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); |
6605 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
6606 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | 6613 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); |
6607 | rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); | 6614 | rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); |
6608 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | 6615 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 25da20e7e1f3..af721831dcbc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -156,8 +156,6 @@ exit_release_regions: | |||
156 | exit_disable_device: | 156 | exit_disable_device: |
157 | pci_disable_device(pci_dev); | 157 | pci_disable_device(pci_dev); |
158 | 158 | ||
159 | pci_set_drvdata(pci_dev, NULL); | ||
160 | |||
161 | return retval; | 159 | return retval; |
162 | } | 160 | } |
163 | EXPORT_SYMBOL_GPL(rt2x00pci_probe); | 161 | EXPORT_SYMBOL_GPL(rt2x00pci_probe); |
@@ -177,7 +175,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) | |||
177 | /* | 175 | /* |
178 | * Free the PCI device data. | 176 | * Free the PCI device data. |
179 | */ | 177 | */ |
180 | pci_set_drvdata(pci_dev, NULL); | ||
181 | pci_disable_device(pci_dev); | 178 | pci_disable_device(pci_dev); |
182 | pci_release_regions(pci_dev); | 179 | pci_release_regions(pci_dev); |
183 | } | 180 | } |
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 9a6edb0c014e..ec9aa5b67381 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
@@ -416,7 +416,7 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) | |||
416 | struct rtl8187_rx_info *info; | 416 | struct rtl8187_rx_info *info; |
417 | int ret = 0; | 417 | int ret = 0; |
418 | 418 | ||
419 | while (skb_queue_len(&priv->rx_queue) < 16) { | 419 | while (skb_queue_len(&priv->rx_queue) < 32) { |
420 | skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); | 420 | skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); |
421 | if (!skb) { | 421 | if (!skb) { |
422 | ret = -ENOMEM; | 422 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index ff784072fb42..fcf9b621918c 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -1437,7 +1437,8 @@ void rtl_watchdog_wq_callback(void *data) | |||
1437 | /* if we can't recv beacon for 6s, we should | 1437 | /* if we can't recv beacon for 6s, we should |
1438 | * reconnect this AP | 1438 | * reconnect this AP |
1439 | */ | 1439 | */ |
1440 | if (rtlpriv->link_info.roam_times >= 3) { | 1440 | if ((rtlpriv->link_info.roam_times >= 3) && |
1441 | !is_zero_ether_addr(rtlpriv->mac80211.bssid)) { | ||
1441 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
1442 | "AP off, try to reconnect now\n"); | 1443 | "AP off, try to reconnect now\n"); |
1443 | rtlpriv->link_info.roam_times = 0; | 1444 | rtlpriv->link_info.roam_times = 0; |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 210ce7cd94d8..2d337a0c3df0 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -46,10 +46,20 @@ void rtl_fw_cb(const struct firmware *firmware, void *context) | |||
46 | "Firmware callback routine entered!\n"); | 46 | "Firmware callback routine entered!\n"); |
47 | complete(&rtlpriv->firmware_loading_complete); | 47 | complete(&rtlpriv->firmware_loading_complete); |
48 | if (!firmware) { | 48 | if (!firmware) { |
49 | if (rtlpriv->cfg->alt_fw_name) { | ||
50 | err = request_firmware(&firmware, | ||
51 | rtlpriv->cfg->alt_fw_name, | ||
52 | rtlpriv->io.dev); | ||
53 | pr_info("Loading alternative firmware %s\n", | ||
54 | rtlpriv->cfg->alt_fw_name); | ||
55 | if (!err) | ||
56 | goto found_alt; | ||
57 | } | ||
49 | pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); | 58 | pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); |
50 | rtlpriv->max_fw_size = 0; | 59 | rtlpriv->max_fw_size = 0; |
51 | return; | 60 | return; |
52 | } | 61 | } |
62 | found_alt: | ||
53 | if (firmware->size > rtlpriv->max_fw_size) { | 63 | if (firmware->size > rtlpriv->max_fw_size) { |
54 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 64 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
55 | "Firmware is too big!\n"); | 65 | "Firmware is too big!\n"); |
@@ -184,6 +194,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
184 | rtlpriv->cfg->maps | 194 | rtlpriv->cfg->maps |
185 | [RTL_IBSS_INT_MASKS]); | 195 | [RTL_IBSS_INT_MASKS]); |
186 | } | 196 | } |
197 | mac->link_state = MAC80211_LINKED; | ||
187 | break; | 198 | break; |
188 | case NL80211_IFTYPE_ADHOC: | 199 | case NL80211_IFTYPE_ADHOC: |
189 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 200 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 0f494444bcd1..8707d1a94995 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -688,8 +688,6 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
688 | rtlpriv->stats.rxbytesunicast += skb->len; | 688 | rtlpriv->stats.rxbytesunicast += skb->len; |
689 | } | 689 | } |
690 | 690 | ||
691 | rtl_is_special_data(hw, skb, false); | ||
692 | |||
693 | if (ieee80211_is_data(fc)) { | 691 | if (ieee80211_is_data(fc)) { |
694 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); | 692 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); |
695 | 693 | ||
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index d7d0d4948b01..a4eb9b271438 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c | |||
@@ -59,30 +59,26 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
59 | */ | 59 | */ |
60 | #define RTL819x_2GHZ_CH12_13 \ | 60 | #define RTL819x_2GHZ_CH12_13 \ |
61 | REG_RULE(2467-10, 2472+10, 40, 0, 20,\ | 61 | REG_RULE(2467-10, 2472+10, 40, 0, 20,\ |
62 | NL80211_RRF_PASSIVE_SCAN) | 62 | NL80211_RRF_NO_IR) |
63 | 63 | ||
64 | #define RTL819x_2GHZ_CH14 \ | 64 | #define RTL819x_2GHZ_CH14 \ |
65 | REG_RULE(2484-10, 2484+10, 40, 0, 20, \ | 65 | REG_RULE(2484-10, 2484+10, 40, 0, 20, \ |
66 | NL80211_RRF_PASSIVE_SCAN | \ | 66 | NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM) |
67 | NL80211_RRF_NO_OFDM) | ||
68 | 67 | ||
69 | /* 5G chan 36 - chan 64*/ | 68 | /* 5G chan 36 - chan 64*/ |
70 | #define RTL819x_5GHZ_5150_5350 \ | 69 | #define RTL819x_5GHZ_5150_5350 \ |
71 | REG_RULE(5150-10, 5350+10, 40, 0, 30, \ | 70 | REG_RULE(5150-10, 5350+10, 40, 0, 30, \ |
72 | NL80211_RRF_PASSIVE_SCAN | \ | 71 | NL80211_RRF_NO_IR) |
73 | NL80211_RRF_NO_IBSS) | ||
74 | 72 | ||
75 | /* 5G chan 100 - chan 165*/ | 73 | /* 5G chan 100 - chan 165*/ |
76 | #define RTL819x_5GHZ_5470_5850 \ | 74 | #define RTL819x_5GHZ_5470_5850 \ |
77 | REG_RULE(5470-10, 5850+10, 40, 0, 30, \ | 75 | REG_RULE(5470-10, 5850+10, 40, 0, 30, \ |
78 | NL80211_RRF_PASSIVE_SCAN | \ | 76 | NL80211_RRF_NO_IR) |
79 | NL80211_RRF_NO_IBSS) | ||
80 | 77 | ||
81 | /* 5G chan 149 - chan 165*/ | 78 | /* 5G chan 149 - chan 165*/ |
82 | #define RTL819x_5GHZ_5725_5850 \ | 79 | #define RTL819x_5GHZ_5725_5850 \ |
83 | REG_RULE(5725-10, 5850+10, 40, 0, 30, \ | 80 | REG_RULE(5725-10, 5850+10, 40, 0, 30, \ |
84 | NL80211_RRF_PASSIVE_SCAN | \ | 81 | NL80211_RRF_NO_IR) |
85 | NL80211_RRF_NO_IBSS) | ||
86 | 82 | ||
87 | #define RTL819x_5GHZ_ALL \ | 83 | #define RTL819x_5GHZ_ALL \ |
88 | (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) | 84 | (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) |
@@ -172,7 +168,8 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
172 | (ch->flags & IEEE80211_CHAN_RADAR)) | 168 | (ch->flags & IEEE80211_CHAN_RADAR)) |
173 | continue; | 169 | continue; |
174 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 170 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
175 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | 171 | reg_rule = freq_reg_info(wiphy, |
172 | MHZ_TO_KHZ(ch->center_freq)); | ||
176 | if (IS_ERR(reg_rule)) | 173 | if (IS_ERR(reg_rule)) |
177 | continue; | 174 | continue; |
178 | 175 | ||
@@ -185,16 +182,11 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
185 | *regulatory_hint(). | 182 | *regulatory_hint(). |
186 | */ | 183 | */ |
187 | 184 | ||
188 | if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) | 185 | if (!(reg_rule->flags & NL80211_RRF_NO_IR)) |
189 | ch->flags &= ~IEEE80211_CHAN_NO_IBSS; | 186 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
190 | if (!(reg_rule-> | ||
191 | flags & NL80211_RRF_PASSIVE_SCAN)) | ||
192 | ch->flags &= | ||
193 | ~IEEE80211_CHAN_PASSIVE_SCAN; | ||
194 | } else { | 187 | } else { |
195 | if (ch->beacon_found) | 188 | if (ch->beacon_found) |
196 | ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | | 189 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
197 | IEEE80211_CHAN_PASSIVE_SCAN); | ||
198 | } | 190 | } |
199 | } | 191 | } |
200 | } | 192 | } |
@@ -219,11 +211,11 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
219 | */ | 211 | */ |
220 | if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 212 | if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
221 | ch = &sband->channels[11]; /* CH 12 */ | 213 | ch = &sband->channels[11]; /* CH 12 */ |
222 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 214 | if (ch->flags & IEEE80211_CHAN_NO_IR) |
223 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 215 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
224 | ch = &sband->channels[12]; /* CH 13 */ | 216 | ch = &sband->channels[12]; /* CH 13 */ |
225 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 217 | if (ch->flags & IEEE80211_CHAN_NO_IR) |
226 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 218 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
227 | return; | 219 | return; |
228 | } | 220 | } |
229 | 221 | ||
@@ -235,19 +227,19 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
235 | */ | 227 | */ |
236 | 228 | ||
237 | ch = &sband->channels[11]; /* CH 12 */ | 229 | ch = &sband->channels[11]; /* CH 12 */ |
238 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | 230 | reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); |
239 | if (!IS_ERR(reg_rule)) { | 231 | if (!IS_ERR(reg_rule)) { |
240 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 232 | if (!(reg_rule->flags & NL80211_RRF_NO_IR)) |
241 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 233 | if (ch->flags & IEEE80211_CHAN_NO_IR) |
242 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 234 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
243 | } | 235 | } |
244 | 236 | ||
245 | ch = &sband->channels[12]; /* CH 13 */ | 237 | ch = &sband->channels[12]; /* CH 13 */ |
246 | reg_rule = freq_reg_info(wiphy, ch->center_freq); | 238 | reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq)); |
247 | if (!IS_ERR(reg_rule)) { | 239 | if (!IS_ERR(reg_rule)) { |
248 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 240 | if (!(reg_rule->flags & NL80211_RRF_NO_IR)) |
249 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 241 | if (ch->flags & IEEE80211_CHAN_NO_IR) |
250 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 242 | ch->flags &= ~IEEE80211_CHAN_NO_IR; |
251 | } | 243 | } |
252 | } | 244 | } |
253 | 245 | ||
@@ -284,8 +276,7 @@ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) | |||
284 | */ | 276 | */ |
285 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) | 277 | if (!(ch->flags & IEEE80211_CHAN_DISABLED)) |
286 | ch->flags |= IEEE80211_CHAN_RADAR | | 278 | ch->flags |= IEEE80211_CHAN_RADAR | |
287 | IEEE80211_CHAN_NO_IBSS | | 279 | IEEE80211_CHAN_NO_IR; |
288 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
289 | } | 280 | } |
290 | } | 281 | } |
291 | 282 | ||
@@ -354,9 +345,9 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, | |||
354 | 345 | ||
355 | wiphy->reg_notifier = reg_notifier; | 346 | wiphy->reg_notifier = reg_notifier; |
356 | 347 | ||
357 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 348 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
358 | wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; | 349 | wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; |
359 | wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; | 350 | wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; |
360 | 351 | ||
361 | regd = _rtl_regdomain_select(reg); | 352 | regd = _rtl_regdomain_select(reg); |
362 | wiphy_apply_custom_regulatory(wiphy, regd); | 353 | wiphy_apply_custom_regulatory(wiphy, regd); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c index 21a5cf060677..a6184b6e1d57 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | |||
@@ -1078,7 +1078,7 @@ static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw | |||
1078 | rtldm->swing_flag_ofdm = true; | 1078 | rtldm->swing_flag_ofdm = true; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) { | 1081 | if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) { |
1082 | rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; | 1082 | rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; |
1083 | rtldm->swing_flag_cck = true; | 1083 | rtldm->swing_flag_cck = true; |
1084 | } | 1084 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index e9caa5d4cff0..fd7e4a7c94de 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | |||
@@ -158,6 +158,42 @@ static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { | |||
158 | {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} | 158 | {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; | ||
162 | |||
163 | void dm_restorepowerindex(struct ieee80211_hw *hw) | ||
164 | { | ||
165 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
166 | u8 index; | ||
167 | |||
168 | for (index = 0; index < 6; index++) | ||
169 | rtl_write_byte(rtlpriv, power_index_reg[index], | ||
170 | rtlpriv->dm.powerindex_backup[index]); | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(dm_restorepowerindex); | ||
173 | |||
174 | void dm_writepowerindex(struct ieee80211_hw *hw, u8 value) | ||
175 | { | ||
176 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
177 | u8 index; | ||
178 | |||
179 | for (index = 0; index < 6; index++) | ||
180 | rtl_write_byte(rtlpriv, power_index_reg[index], value); | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(dm_writepowerindex); | ||
183 | |||
184 | void dm_savepowerindex(struct ieee80211_hw *hw) | ||
185 | { | ||
186 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
187 | u8 index; | ||
188 | u8 tmp; | ||
189 | |||
190 | for (index = 0; index < 6; index++) { | ||
191 | tmp = rtl_read_byte(rtlpriv, power_index_reg[index]); | ||
192 | rtlpriv->dm.powerindex_backup[index] = tmp; | ||
193 | } | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(dm_savepowerindex); | ||
196 | |||
161 | static void rtl92c_dm_diginit(struct ieee80211_hw *hw) | 197 | static void rtl92c_dm_diginit(struct ieee80211_hw *hw) |
162 | { | 198 | { |
163 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 199 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -180,7 +216,12 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw) | |||
180 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 216 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
181 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 217 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
182 | dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; | 218 | dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; |
183 | dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; | 219 | dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LowRssi; |
220 | |||
221 | dm_digtable->forbidden_igi = DM_DIG_MIN; | ||
222 | dm_digtable->large_fa_hit = 0; | ||
223 | dm_digtable->recover_cnt = 0; | ||
224 | dm_digtable->dig_dynamic_min = 0x25; | ||
184 | } | 225 | } |
185 | 226 | ||
186 | static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) | 227 | static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) |
@@ -206,7 +247,9 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) | |||
206 | rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; | 247 | rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; |
207 | } | 248 | } |
208 | 249 | ||
209 | return (u8) rssi_val_min; | 250 | if (rssi_val_min > 100) |
251 | rssi_val_min = 100; | ||
252 | return (u8)rssi_val_min; | ||
210 | } | 253 | } |
211 | 254 | ||
212 | static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) | 255 | static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) |
@@ -224,9 +267,17 @@ static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) | |||
224 | 267 | ||
225 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); | 268 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); |
226 | falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); | 269 | falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); |
270 | |||
271 | ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); | ||
272 | falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); | ||
273 | falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); | ||
274 | |||
227 | falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + | 275 | falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + |
228 | falsealm_cnt->cnt_rate_illegal + | 276 | falsealm_cnt->cnt_rate_illegal + |
229 | falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail; | 277 | falsealm_cnt->cnt_crc8_fail + |
278 | falsealm_cnt->cnt_mcs_fail + | ||
279 | falsealm_cnt->cnt_fast_fsync_fail + | ||
280 | falsealm_cnt->cnt_sb_search_fail; | ||
230 | 281 | ||
231 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); | 282 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); |
232 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); | 283 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); |
@@ -271,12 +322,14 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) | |||
271 | value_igi++; | 322 | value_igi++; |
272 | else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) | 323 | else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) |
273 | value_igi += 2; | 324 | value_igi += 2; |
325 | |||
274 | if (value_igi > DM_DIG_FA_UPPER) | 326 | if (value_igi > DM_DIG_FA_UPPER) |
275 | value_igi = DM_DIG_FA_UPPER; | 327 | value_igi = DM_DIG_FA_UPPER; |
276 | else if (value_igi < DM_DIG_FA_LOWER) | 328 | else if (value_igi < DM_DIG_FA_LOWER) |
277 | value_igi = DM_DIG_FA_LOWER; | 329 | value_igi = DM_DIG_FA_LOWER; |
330 | |||
278 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) | 331 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) |
279 | value_igi = 0x32; | 332 | value_igi = DM_DIG_FA_UPPER; |
280 | 333 | ||
281 | dm_digtable->cur_igvalue = value_igi; | 334 | dm_digtable->cur_igvalue = value_igi; |
282 | rtl92c_dm_write_dig(hw); | 335 | rtl92c_dm_write_dig(hw); |
@@ -286,32 +339,80 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) | |||
286 | { | 339 | { |
287 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 340 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
288 | struct dig_t *digtable = &rtlpriv->dm_digtable; | 341 | struct dig_t *digtable = &rtlpriv->dm_digtable; |
342 | u32 isbt; | ||
343 | |||
344 | /* modify DIG lower bound, deal with abnorally large false alarm */ | ||
345 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) { | ||
346 | digtable->large_fa_hit++; | ||
347 | if (digtable->forbidden_igi < digtable->cur_igvalue) { | ||
348 | digtable->forbidden_igi = digtable->cur_igvalue; | ||
349 | digtable->large_fa_hit = 1; | ||
350 | } | ||
289 | 351 | ||
290 | if (rtlpriv->falsealm_cnt.cnt_all > digtable->fa_highthresh) { | 352 | if (digtable->large_fa_hit >= 3) { |
291 | if ((digtable->back_val - 2) < digtable->back_range_min) | 353 | if ((digtable->forbidden_igi + 1) > |
292 | digtable->back_val = digtable->back_range_min; | 354 | digtable->rx_gain_max) |
293 | else | 355 | digtable->rx_gain_min = digtable->rx_gain_max; |
294 | digtable->back_val -= 2; | 356 | else |
295 | } else if (rtlpriv->falsealm_cnt.cnt_all < digtable->fa_lowthresh) { | 357 | digtable->rx_gain_min = (digtable->forbidden_igi + 1); |
296 | if ((digtable->back_val + 2) > digtable->back_range_max) | 358 | digtable->recover_cnt = 3600; /* 3600=2hr */ |
297 | digtable->back_val = digtable->back_range_max; | 359 | } |
298 | else | 360 | } else { |
299 | digtable->back_val += 2; | 361 | /* Recovery mechanism for IGI lower bound */ |
362 | if (digtable->recover_cnt != 0) { | ||
363 | digtable->recover_cnt--; | ||
364 | } else { | ||
365 | if (digtable->large_fa_hit == 0) { | ||
366 | if ((digtable->forbidden_igi-1) < DM_DIG_MIN) { | ||
367 | digtable->forbidden_igi = DM_DIG_MIN; | ||
368 | digtable->rx_gain_min = DM_DIG_MIN; | ||
369 | } else { | ||
370 | digtable->forbidden_igi--; | ||
371 | digtable->rx_gain_min = digtable->forbidden_igi + 1; | ||
372 | } | ||
373 | } else if (digtable->large_fa_hit == 3) { | ||
374 | digtable->large_fa_hit = 0; | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | if (rtlpriv->falsealm_cnt.cnt_all < 250) { | ||
379 | isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01; | ||
380 | |||
381 | if (!isbt) { | ||
382 | if (rtlpriv->falsealm_cnt.cnt_all > | ||
383 | digtable->fa_lowthresh) { | ||
384 | if ((digtable->back_val - 2) < | ||
385 | digtable->back_range_min) | ||
386 | digtable->back_val = digtable->back_range_min; | ||
387 | else | ||
388 | digtable->back_val -= 2; | ||
389 | } else if (rtlpriv->falsealm_cnt.cnt_all < | ||
390 | digtable->fa_lowthresh) { | ||
391 | if ((digtable->back_val + 2) > | ||
392 | digtable->back_range_max) | ||
393 | digtable->back_val = digtable->back_range_max; | ||
394 | else | ||
395 | digtable->back_val += 2; | ||
396 | } | ||
397 | } else { | ||
398 | digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | ||
399 | } | ||
400 | } else { | ||
401 | /* Adjust initial gain by false alarm */ | ||
402 | if (rtlpriv->falsealm_cnt.cnt_all > 1000) | ||
403 | digtable->cur_igvalue = digtable->pre_igvalue + 2; | ||
404 | else if (rtlpriv->falsealm_cnt.cnt_all > 750) | ||
405 | digtable->cur_igvalue = digtable->pre_igvalue + 1; | ||
406 | else if (rtlpriv->falsealm_cnt.cnt_all < 500) | ||
407 | digtable->cur_igvalue = digtable->pre_igvalue - 1; | ||
300 | } | 408 | } |
301 | 409 | ||
302 | if ((digtable->rssi_val_min + 10 - digtable->back_val) > | 410 | /* Check initial gain by upper/lower bound */ |
303 | digtable->rx_gain_max) | 411 | if (digtable->cur_igvalue > digtable->rx_gain_max) |
304 | digtable->cur_igvalue = digtable->rx_gain_max; | 412 | digtable->cur_igvalue = digtable->rx_gain_max; |
305 | else if ((digtable->rssi_val_min + 10 - | ||
306 | digtable->back_val) < digtable->rx_gain_min) | ||
307 | digtable->cur_igvalue = digtable->rx_gain_min; | ||
308 | else | ||
309 | digtable->cur_igvalue = digtable->rssi_val_min + 10 - | ||
310 | digtable->back_val; | ||
311 | 413 | ||
312 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | 414 | if (digtable->cur_igvalue < digtable->rx_gain_min) |
313 | "rssi_val_min = %x back_val %x\n", | 415 | digtable->cur_igvalue = digtable->rx_gain_min; |
314 | digtable->rssi_val_min, digtable->back_val); | ||
315 | 416 | ||
316 | rtl92c_dm_write_dig(hw); | 417 | rtl92c_dm_write_dig(hw); |
317 | } | 418 | } |
@@ -329,7 +430,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) | |||
329 | multi_sta = true; | 430 | multi_sta = true; |
330 | 431 | ||
331 | if (!multi_sta || | 432 | if (!multi_sta || |
332 | dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { | 433 | dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) { |
333 | initialized = false; | 434 | initialized = false; |
334 | dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; | 435 | dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
335 | return; | 436 | return; |
@@ -375,7 +476,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) | |||
375 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | 476 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, |
376 | "presta_cstate = %x, cursta_cstate = %x\n", | 477 | "presta_cstate = %x, cursta_cstate = %x\n", |
377 | dm_digtable->presta_cstate, dm_digtable->cursta_cstate); | 478 | dm_digtable->presta_cstate, dm_digtable->cursta_cstate); |
378 | |||
379 | if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || | 479 | if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || |
380 | dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || | 480 | dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || |
381 | dm_digtable->cursta_cstate == DIG_STA_CONNECT) { | 481 | dm_digtable->cursta_cstate == DIG_STA_CONNECT) { |
@@ -383,6 +483,8 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) | |||
383 | if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { | 483 | if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { |
384 | dm_digtable->rssi_val_min = | 484 | dm_digtable->rssi_val_min = |
385 | rtl92c_dm_initial_gain_min_pwdb(hw); | 485 | rtl92c_dm_initial_gain_min_pwdb(hw); |
486 | if (dm_digtable->rssi_val_min > 100) | ||
487 | dm_digtable->rssi_val_min = 100; | ||
386 | rtl92c_dm_ctrl_initgain_by_rssi(hw); | 488 | rtl92c_dm_ctrl_initgain_by_rssi(hw); |
387 | } | 489 | } |
388 | } else { | 490 | } else { |
@@ -398,11 +500,12 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) | |||
398 | static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) | 500 | static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) |
399 | { | 501 | { |
400 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 502 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
401 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
402 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; | 503 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
403 | 504 | ||
404 | if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { | 505 | if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { |
405 | dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); | 506 | dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); |
507 | if (dm_digtable->rssi_val_min > 100) | ||
508 | dm_digtable->rssi_val_min = 100; | ||
406 | 509 | ||
407 | if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) { | 510 | if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) { |
408 | if (dm_digtable->rssi_val_min <= 25) | 511 | if (dm_digtable->rssi_val_min <= 25) |
@@ -424,48 +527,14 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) | |||
424 | } | 527 | } |
425 | 528 | ||
426 | if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { | 529 | if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { |
427 | if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) { | 530 | if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) || |
428 | if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800) | 531 | (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX)) |
429 | dm_digtable->cur_cck_fa_state = | 532 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); |
430 | CCK_FA_STAGE_High; | 533 | else |
431 | else | ||
432 | dm_digtable->cur_cck_fa_state = CCK_FA_STAGE_Low; | ||
433 | |||
434 | if (dm_digtable->pre_cck_fa_state != | ||
435 | dm_digtable->cur_cck_fa_state) { | ||
436 | if (dm_digtable->cur_cck_fa_state == | ||
437 | CCK_FA_STAGE_Low) | ||
438 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, | ||
439 | 0x83); | ||
440 | else | ||
441 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, | ||
442 | 0xcd); | ||
443 | |||
444 | dm_digtable->pre_cck_fa_state = | ||
445 | dm_digtable->cur_cck_fa_state; | ||
446 | } | ||
447 | |||
448 | rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40); | ||
449 | |||
450 | if (IS_92C_SERIAL(rtlhal->version)) | ||
451 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, | ||
452 | MASKBYTE2, 0xd7); | ||
453 | } else { | ||
454 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); | 534 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); |
455 | rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); | ||
456 | 535 | ||
457 | if (IS_92C_SERIAL(rtlhal->version)) | ||
458 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, | ||
459 | MASKBYTE2, 0xd3); | ||
460 | } | ||
461 | dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; | 536 | dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; |
462 | } | 537 | } |
463 | |||
464 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "CCKPDStage=%x\n", | ||
465 | dm_digtable->cur_cck_pd_state); | ||
466 | |||
467 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "is92C=%x\n", | ||
468 | IS_92C_SERIAL(rtlhal->version)); | ||
469 | } | 538 | } |
470 | 539 | ||
471 | static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) | 540 | static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) |
@@ -482,6 +551,8 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) | |||
482 | else | 551 | else |
483 | dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; | 552 | dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; |
484 | 553 | ||
554 | dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; | ||
555 | |||
485 | rtl92c_dm_initial_gain_sta(hw); | 556 | rtl92c_dm_initial_gain_sta(hw); |
486 | rtl92c_dm_initial_gain_multi_sta(hw); | 557 | rtl92c_dm_initial_gain_multi_sta(hw); |
487 | rtl92c_dm_cck_packet_detection_thresh(hw); | 558 | rtl92c_dm_cck_packet_detection_thresh(hw); |
@@ -493,23 +564,26 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) | |||
493 | static void rtl92c_dm_dig(struct ieee80211_hw *hw) | 564 | static void rtl92c_dm_dig(struct ieee80211_hw *hw) |
494 | { | 565 | { |
495 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 566 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
496 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; | ||
497 | 567 | ||
498 | if (rtlpriv->dm.dm_initialgain_enable == false) | 568 | if (rtlpriv->dm.dm_initialgain_enable == false) |
499 | return; | 569 | return; |
500 | if (dm_digtable->dig_enable_flag == false) | 570 | if (!rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG) |
501 | return; | 571 | return; |
502 | 572 | ||
503 | rtl92c_dm_ctrl_initgain_by_twoport(hw); | 573 | rtl92c_dm_ctrl_initgain_by_twoport(hw); |
504 | |||
505 | } | 574 | } |
506 | 575 | ||
507 | static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) | 576 | static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) |
508 | { | 577 | { |
509 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 578 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
510 | 579 | ||
511 | rtlpriv->dm.dynamic_txpower_enable = false; | 580 | if (rtlpriv->rtlhal.interface == INTF_USB && |
512 | 581 | rtlpriv->rtlhal.board_type & 0x1) { | |
582 | dm_savepowerindex(hw); | ||
583 | rtlpriv->dm.dynamic_txpower_enable = true; | ||
584 | } else { | ||
585 | rtlpriv->dm.dynamic_txpower_enable = false; | ||
586 | } | ||
513 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; | 587 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; |
514 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | 588 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; |
515 | } | 589 | } |
@@ -524,9 +598,14 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) | |||
524 | dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, | 598 | dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, |
525 | dm_digtable->back_val); | 599 | dm_digtable->back_val); |
526 | 600 | ||
527 | dm_digtable->cur_igvalue += 2; | 601 | if (rtlpriv->rtlhal.interface == INTF_USB && |
528 | if (dm_digtable->cur_igvalue > 0x3f) | 602 | !dm_digtable->dig_enable_flag) { |
529 | dm_digtable->cur_igvalue = 0x3f; | 603 | dm_digtable->pre_igvalue = 0x17; |
604 | return; | ||
605 | } | ||
606 | dm_digtable->cur_igvalue -= 1; | ||
607 | if (dm_digtable->cur_igvalue < DM_DIG_MIN) | ||
608 | dm_digtable->cur_igvalue = DM_DIG_MIN; | ||
530 | 609 | ||
531 | if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { | 610 | if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { |
532 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, | 611 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, |
@@ -536,11 +615,47 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) | |||
536 | 615 | ||
537 | dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; | 616 | dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; |
538 | } | 617 | } |
618 | RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING, | ||
619 | "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | ||
620 | dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, | ||
621 | dm_digtable->rssi_val_min, dm_digtable->back_val, | ||
622 | dm_digtable->rx_gain_max, dm_digtable->rx_gain_min, | ||
623 | dm_digtable->large_fa_hit, dm_digtable->forbidden_igi); | ||
539 | } | 624 | } |
540 | EXPORT_SYMBOL(rtl92c_dm_write_dig); | 625 | EXPORT_SYMBOL(rtl92c_dm_write_dig); |
541 | 626 | ||
542 | static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) | 627 | static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) |
543 | { | 628 | { |
629 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
630 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
631 | long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; | ||
632 | |||
633 | if (mac->link_state != MAC80211_LINKED) | ||
634 | return; | ||
635 | |||
636 | if (mac->opmode == NL80211_IFTYPE_ADHOC || | ||
637 | mac->opmode == NL80211_IFTYPE_AP) { | ||
638 | /* TODO: Handle ADHOC and AP Mode */ | ||
639 | } | ||
640 | |||
641 | if (tmpentry_max_pwdb != 0) | ||
642 | rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; | ||
643 | else | ||
644 | rtlpriv->dm.entry_max_undec_sm_pwdb = 0; | ||
645 | |||
646 | if (tmpentry_min_pwdb != 0xff) | ||
647 | rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; | ||
648 | else | ||
649 | rtlpriv->dm.entry_min_undec_sm_pwdb = 0; | ||
650 | |||
651 | /* TODO: | ||
652 | * if (mac->opmode == NL80211_IFTYPE_STATION) { | ||
653 | * if (rtlpriv->rtlhal.fw_ready) { | ||
654 | * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16); | ||
655 | * rtl8192c_set_rssi_cmd(hw, param); | ||
656 | * } | ||
657 | * } | ||
658 | */ | ||
544 | } | 659 | } |
545 | 660 | ||
546 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) | 661 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) |
@@ -750,6 +865,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw | |||
750 | rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; | 865 | rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; |
751 | rtlpriv->dm.cck_index = cck_index_old; | 866 | rtlpriv->dm.cck_index = cck_index_old; |
752 | } | 867 | } |
868 | /* Handle USB High PA boards */ | ||
753 | 869 | ||
754 | delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? | 870 | delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? |
755 | (thermalvalue - rtlpriv->dm.thermalvalue) : | 871 | (thermalvalue - rtlpriv->dm.thermalvalue) : |
@@ -1140,22 +1256,22 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) | |||
1140 | { | 1256 | { |
1141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1257 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1142 | struct ps_t *dm_pstable = &rtlpriv->dm_pstable; | 1258 | struct ps_t *dm_pstable = &rtlpriv->dm_pstable; |
1143 | static u8 initialize; | ||
1144 | static u32 reg_874, reg_c70, reg_85c, reg_a74; | ||
1145 | 1259 | ||
1146 | if (initialize == 0) { | 1260 | if (!rtlpriv->reg_init) { |
1147 | reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, | 1261 | rtlpriv->reg_874 = (rtl_get_bbreg(hw, |
1148 | MASKDWORD) & 0x1CC000) >> 14; | 1262 | RFPGA0_XCD_RFINTERFACESW, |
1263 | MASKDWORD) & 0x1CC000) >> 14; | ||
1149 | 1264 | ||
1150 | reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, | 1265 | rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, |
1151 | MASKDWORD) & BIT(3)) >> 3; | 1266 | MASKDWORD) & BIT(3)) >> 3; |
1152 | 1267 | ||
1153 | reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, | 1268 | rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, |
1154 | MASKDWORD) & 0xFF000000) >> 24; | 1269 | MASKDWORD) & 0xFF000000) >> 24; |
1155 | 1270 | ||
1156 | reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12; | 1271 | rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & |
1272 | 0xF000) >> 12; | ||
1157 | 1273 | ||
1158 | initialize = 1; | 1274 | rtlpriv->reg_init = true; |
1159 | } | 1275 | } |
1160 | 1276 | ||
1161 | if (!bforce_in_normal) { | 1277 | if (!bforce_in_normal) { |
@@ -1192,12 +1308,12 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) | |||
1192 | rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); | 1308 | rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); |
1193 | } else { | 1309 | } else { |
1194 | rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, | 1310 | rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, |
1195 | 0x1CC000, reg_874); | 1311 | 0x1CC000, rtlpriv->reg_874); |
1196 | rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), | 1312 | rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), |
1197 | reg_c70); | 1313 | rtlpriv->reg_c70); |
1198 | rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, | 1314 | rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, |
1199 | reg_85c); | 1315 | rtlpriv->reg_85c); |
1200 | rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74); | 1316 | rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74); |
1201 | rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); | 1317 | rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); |
1202 | } | 1318 | } |
1203 | 1319 | ||
@@ -1213,6 +1329,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) | |||
1213 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1329 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1214 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1330 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1215 | 1331 | ||
1332 | /* Determine the minimum RSSI */ | ||
1216 | if (((mac->link_state == MAC80211_NOLINK)) && | 1333 | if (((mac->link_state == MAC80211_NOLINK)) && |
1217 | (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | 1334 | (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { |
1218 | dm_pstable->rssi_val_min = 0; | 1335 | dm_pstable->rssi_val_min = 0; |
@@ -1241,6 +1358,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) | |||
1241 | dm_pstable->rssi_val_min); | 1358 | dm_pstable->rssi_val_min); |
1242 | } | 1359 | } |
1243 | 1360 | ||
1361 | /* Power Saving for 92C */ | ||
1244 | if (IS_92C_SERIAL(rtlhal->version)) | 1362 | if (IS_92C_SERIAL(rtlhal->version)) |
1245 | ;/* rtl92c_dm_1r_cca(hw); */ | 1363 | ;/* rtl92c_dm_1r_cca(hw); */ |
1246 | else | 1364 | else |
@@ -1252,12 +1370,23 @@ void rtl92c_dm_init(struct ieee80211_hw *hw) | |||
1252 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1370 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1253 | 1371 | ||
1254 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; | 1372 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; |
1373 | rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG; | ||
1374 | rtlpriv->dm.undec_sm_pwdb = -1; | ||
1375 | rtlpriv->dm.undec_sm_cck = -1; | ||
1376 | rtlpriv->dm.dm_initialgain_enable = true; | ||
1255 | rtl92c_dm_diginit(hw); | 1377 | rtl92c_dm_diginit(hw); |
1378 | |||
1379 | rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE; | ||
1256 | rtl92c_dm_init_dynamic_txpower(hw); | 1380 | rtl92c_dm_init_dynamic_txpower(hw); |
1381 | |||
1257 | rtl92c_dm_init_edca_turbo(hw); | 1382 | rtl92c_dm_init_edca_turbo(hw); |
1258 | rtl92c_dm_init_rate_adaptive_mask(hw); | 1383 | rtl92c_dm_init_rate_adaptive_mask(hw); |
1384 | rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS; | ||
1259 | rtl92c_dm_initialize_txpower_tracking(hw); | 1385 | rtl92c_dm_initialize_txpower_tracking(hw); |
1260 | rtl92c_dm_init_dynamic_bb_powersaving(hw); | 1386 | rtl92c_dm_init_dynamic_bb_powersaving(hw); |
1387 | |||
1388 | rtlpriv->dm.ofdm_pkt_cnt = 0; | ||
1389 | rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT; | ||
1261 | } | 1390 | } |
1262 | EXPORT_SYMBOL(rtl92c_dm_init); | 1391 | EXPORT_SYMBOL(rtl92c_dm_init); |
1263 | 1392 | ||
@@ -1308,7 +1437,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) | |||
1308 | } | 1437 | } |
1309 | 1438 | ||
1310 | if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | 1439 | if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { |
1311 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; | 1440 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2; |
1312 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | 1441 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
1313 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); | 1442 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); |
1314 | } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | 1443 | } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && |
@@ -1328,8 +1457,16 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) | |||
1328 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", | 1457 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", |
1329 | rtlphy->current_channel); | 1458 | rtlphy->current_channel); |
1330 | rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); | 1459 | rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); |
1460 | if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
1461 | TXHIGHPWRLEVEL_NORMAL) | ||
1462 | dm_restorepowerindex(hw); | ||
1463 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
1464 | TXHIGHPWRLEVEL_LEVEL1) | ||
1465 | dm_writepowerindex(hw, 0x14); | ||
1466 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
1467 | TXHIGHPWRLEVEL_LEVEL2) | ||
1468 | dm_writepowerindex(hw, 0x10); | ||
1331 | } | 1469 | } |
1332 | |||
1333 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; | 1470 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; |
1334 | } | 1471 | } |
1335 | 1472 | ||
@@ -1400,12 +1537,6 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) | |||
1400 | else | 1537 | else |
1401 | curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); | 1538 | curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); |
1402 | 1539 | ||
1403 | /* Set Tx Power according to BT status. */ | ||
1404 | if (undec_sm_pwdb >= 30) | ||
1405 | curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; | ||
1406 | else if (undec_sm_pwdb < 25) | ||
1407 | curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); | ||
1408 | |||
1409 | /* Check BT state related to BT_Idle in B/G mode. */ | 1540 | /* Check BT state related to BT_Idle in B/G mode. */ |
1410 | if (undec_sm_pwdb < 15) | 1541 | if (undec_sm_pwdb < 15) |
1411 | curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; | 1542 | curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h index 518e208c0180..4f232a063636 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h | |||
@@ -91,6 +91,17 @@ | |||
91 | #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 | 91 | #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 |
92 | #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 | 92 | #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 |
93 | 93 | ||
94 | #define DYNAMIC_FUNC_DISABLE 0x0 | ||
95 | #define DYNAMIC_FUNC_DIG BIT(0) | ||
96 | #define DYNAMIC_FUNC_HP BIT(1) | ||
97 | #define DYNAMIC_FUNC_SS BIT(2) /*Tx Power Tracking*/ | ||
98 | #define DYNAMIC_FUNC_BT BIT(3) | ||
99 | #define DYNAMIC_FUNC_ANT_DIV BIT(4) | ||
100 | |||
101 | #define RSSI_CCK 0 | ||
102 | #define RSSI_OFDM 1 | ||
103 | #define RSSI_DEFAULT 2 | ||
104 | |||
94 | struct swat_t { | 105 | struct swat_t { |
95 | u8 failure_cnt; | 106 | u8 failure_cnt; |
96 | u8 try_flag; | 107 | u8 try_flag; |
@@ -167,5 +178,8 @@ void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); | |||
167 | void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); | 178 | void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); |
168 | void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); | 179 | void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); |
169 | void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); | 180 | void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); |
181 | void dm_savepowerindex(struct ieee80211_hw *hw); | ||
182 | void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); | ||
183 | void dm_restorepowerindex(struct ieee80211_hw *hw); | ||
170 | 184 | ||
171 | #endif | 185 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 0c0e78263a66..9e32ac8a4425 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | |||
@@ -1147,6 +1147,12 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, | |||
1147 | 0x522, 0x550, 0x551, 0x040 | 1147 | 0x522, 0x550, 0x551, 0x040 |
1148 | }; | 1148 | }; |
1149 | 1149 | ||
1150 | u32 iqk_bb_reg_92C[9] = { | ||
1151 | 0xc04, 0xc08, 0x874, 0xb68, | ||
1152 | 0xb6c, 0x870, 0x860, 0x864, | ||
1153 | 0x800 | ||
1154 | }; | ||
1155 | |||
1150 | const u32 retrycount = 2; | 1156 | const u32 retrycount = 2; |
1151 | 1157 | ||
1152 | if (t == 0) { | 1158 | if (t == 0) { |
@@ -1157,6 +1163,8 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, | |||
1157 | rtlphy->adda_backup, 16); | 1163 | rtlphy->adda_backup, 16); |
1158 | _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, | 1164 | _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, |
1159 | rtlphy->iqk_mac_backup); | 1165 | rtlphy->iqk_mac_backup); |
1166 | _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg_92C, | ||
1167 | rtlphy->iqk_bb_backup, 9); | ||
1160 | } | 1168 | } |
1161 | _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); | 1169 | _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); |
1162 | if (t == 0) { | 1170 | if (t == 0) { |
@@ -1167,14 +1175,18 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, | |||
1167 | 1175 | ||
1168 | if (!rtlphy->rfpi_enable) | 1176 | if (!rtlphy->rfpi_enable) |
1169 | _rtl92c_phy_pi_mode_switch(hw, true); | 1177 | _rtl92c_phy_pi_mode_switch(hw, true); |
1170 | if (t == 0) { | 1178 | |
1171 | rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); | 1179 | rtl_set_bbreg(hw, 0x800, BIT(24), 0x0); |
1172 | rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); | 1180 | |
1173 | rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); | ||
1174 | } | ||
1175 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); | 1181 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); |
1176 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); | 1182 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); |
1177 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); | 1183 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); |
1184 | |||
1185 | rtl_set_bbreg(hw, 0x870, BIT(10), 0x1); | ||
1186 | rtl_set_bbreg(hw, 0x870, BIT(26), 0x1); | ||
1187 | rtl_set_bbreg(hw, 0x860, BIT(10), 0x0); | ||
1188 | rtl_set_bbreg(hw, 0x864, BIT(10), 0x0); | ||
1189 | |||
1178 | if (is2t) { | 1190 | if (is2t) { |
1179 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | 1191 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); |
1180 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); | 1192 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); |
@@ -1239,13 +1251,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, | |||
1239 | 0x3FF0000) >> 16; | 1251 | 0x3FF0000) >> 16; |
1240 | } | 1252 | } |
1241 | } | 1253 | } |
1242 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); | 1254 | |
1243 | rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); | ||
1244 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); | ||
1245 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); | 1255 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); |
1246 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); | 1256 | |
1247 | if (is2t) | ||
1248 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); | ||
1249 | if (t != 0) { | 1257 | if (t != 0) { |
1250 | if (!rtlphy->rfpi_enable) | 1258 | if (!rtlphy->rfpi_enable) |
1251 | _rtl92c_phy_pi_mode_switch(hw, false); | 1259 | _rtl92c_phy_pi_mode_switch(hw, false); |
@@ -1253,6 +1261,15 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, | |||
1253 | rtlphy->adda_backup, 16); | 1261 | rtlphy->adda_backup, 16); |
1254 | _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, | 1262 | _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, |
1255 | rtlphy->iqk_mac_backup); | 1263 | rtlphy->iqk_mac_backup); |
1264 | _rtl92c_phy_reload_adda_registers(hw, iqk_bb_reg_92C, | ||
1265 | rtlphy->iqk_bb_backup, 9); | ||
1266 | |||
1267 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); | ||
1268 | if (is2t) | ||
1269 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); | ||
1270 | |||
1271 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); | ||
1272 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); | ||
1256 | } | 1273 | } |
1257 | } | 1274 | } |
1258 | 1275 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c index 16a0b9e59acf..c16209a336ea 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c | |||
@@ -101,6 +101,15 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) | |||
101 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", | 101 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", |
102 | rtlphy->current_channel); | 102 | rtlphy->current_channel); |
103 | rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); | 103 | rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); |
104 | if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
105 | TXHIGHPWRLEVEL_NORMAL) | ||
106 | dm_restorepowerindex(hw); | ||
107 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
108 | TXHIGHPWRLEVEL_LEVEL1) | ||
109 | dm_writepowerindex(hw, 0x14); | ||
110 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
111 | TXHIGHPWRLEVEL_LEVEL2) | ||
112 | dm_writepowerindex(hw, 0x10); | ||
104 | } | 113 | } |
105 | 114 | ||
106 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; | 115 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h index d947e7d350bb..fafa6bac2a3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h | |||
@@ -30,3 +30,6 @@ | |||
30 | #include "../rtl8192ce/dm.h" | 30 | #include "../rtl8192ce/dm.h" |
31 | 31 | ||
32 | void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); | 32 | void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); |
33 | void dm_savepowerindex(struct ieee80211_hw *hw); | ||
34 | void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); | ||
35 | void dm_restorepowerindex(struct ieee80211_hw *hw); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 189ba124a8c6..468bf73cc883 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1022,7 +1022,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
1022 | if (ppsc->rfpwr_state == ERFON) { | 1022 | if (ppsc->rfpwr_state == ERFON) { |
1023 | rtl92c_phy_set_rfpath_switch(hw, 1); | 1023 | rtl92c_phy_set_rfpath_switch(hw, 1); |
1024 | if (iqk_initialized) { | 1024 | if (iqk_initialized) { |
1025 | rtl92c_phy_iq_calibrate(hw, false); | 1025 | rtl92c_phy_iq_calibrate(hw, true); |
1026 | } else { | 1026 | } else { |
1027 | rtl92c_phy_iq_calibrate(hw, false); | 1027 | rtl92c_phy_iq_calibrate(hw, false); |
1028 | iqk_initialized = true; | 1028 | iqk_initialized = true; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 34e56308301e..0c09240eadcc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | |||
@@ -120,6 +120,7 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) | |||
120 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 120 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
121 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 121 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
122 | u16 regval; | 122 | u16 regval; |
123 | u32 regval32; | ||
123 | u8 b_reg_hwparafile = 1; | 124 | u8 b_reg_hwparafile = 1; |
124 | 125 | ||
125 | _rtl92c_phy_init_bb_rf_register_definition(hw); | 126 | _rtl92c_phy_init_bb_rf_register_definition(hw); |
@@ -135,8 +136,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) | |||
135 | } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) { | 136 | } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) { |
136 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | | 137 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | |
137 | FEN_BB_GLB_RSTn | FEN_BBRSTB); | 138 | FEN_BB_GLB_RSTn | FEN_BBRSTB); |
138 | rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); | ||
139 | } | 139 | } |
140 | regval32 = rtl_read_dword(rtlpriv, 0x87c); | ||
141 | rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); | ||
142 | if (IS_HARDWARE_TYPE_8192CU(rtlhal)) | ||
143 | rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); | ||
140 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); | 144 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); |
141 | if (b_reg_hwparafile == 1) | 145 | if (b_reg_hwparafile == 1) |
142 | rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); | 146 | rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 2119313a737b..b878d56d2f4d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | |||
@@ -85,17 +85,15 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |||
85 | if (mac->act_scanning) { | 85 | if (mac->act_scanning) { |
86 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; | 86 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; |
87 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; | 87 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; |
88 | if (turbo_scanoff) { | 88 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { |
89 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | 89 | tx_agc[idx1] = ppowerlevel[idx1] | |
90 | tx_agc[idx1] = ppowerlevel[idx1] | | 90 | (ppowerlevel[idx1] << 8) | |
91 | (ppowerlevel[idx1] << 8) | | 91 | (ppowerlevel[idx1] << 16) | |
92 | (ppowerlevel[idx1] << 16) | | 92 | (ppowerlevel[idx1] << 24); |
93 | (ppowerlevel[idx1] << 24); | 93 | if (rtlhal->interface == INTF_USB) { |
94 | if (rtlhal->interface == INTF_USB) { | 94 | if (tx_agc[idx1] > 0x20 && |
95 | if (tx_agc[idx1] > 0x20 && | 95 | rtlefuse->external_pa) |
96 | rtlefuse->external_pa) | 96 | tx_agc[idx1] = 0x20; |
97 | tx_agc[idx1] = 0x20; | ||
98 | } | ||
99 | } | 97 | } |
100 | } | 98 | } |
101 | } else { | 99 | } else { |
@@ -107,7 +105,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | |||
107 | TXHIGHPWRLEVEL_LEVEL2) { | 105 | TXHIGHPWRLEVEL_LEVEL2) { |
108 | tx_agc[RF90_PATH_A] = 0x00000000; | 106 | tx_agc[RF90_PATH_A] = 0x00000000; |
109 | tx_agc[RF90_PATH_B] = 0x00000000; | 107 | tx_agc[RF90_PATH_B] = 0x00000000; |
110 | } else{ | 108 | } else { |
111 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | 109 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { |
112 | tx_agc[idx1] = ppowerlevel[idx1] | | 110 | tx_agc[idx1] = ppowerlevel[idx1] | |
113 | (ppowerlevel[idx1] << 8) | | 111 | (ppowerlevel[idx1] << 8) | |
@@ -373,7 +371,12 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, | |||
373 | regoffset == RTXAGC_B_MCS07_MCS04) | 371 | regoffset == RTXAGC_B_MCS07_MCS04) |
374 | regoffset = 0xc98; | 372 | regoffset = 0xc98; |
375 | for (i = 0; i < 3; i++) { | 373 | for (i = 0; i < 3; i++) { |
376 | writeVal = (writeVal > 6) ? (writeVal - 6) : 0; | 374 | if (i != 2) |
375 | writeVal = (writeVal > 8) ? | ||
376 | (writeVal - 8) : 0; | ||
377 | else | ||
378 | writeVal = (writeVal > 6) ? | ||
379 | (writeVal - 6) : 0; | ||
377 | rtl_write_byte(rtlpriv, (u32)(regoffset + i), | 380 | rtl_write_byte(rtlpriv, (u32)(regoffset + i), |
378 | (u8)writeVal); | 381 | (u8)writeVal); |
379 | } | 382 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9936de716ad5..8501954cfb44 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -50,6 +50,9 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); | |||
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); | 51 | MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); |
52 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); | 52 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); |
53 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); | ||
54 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); | ||
55 | MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); | ||
53 | 56 | ||
54 | static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) | 57 | static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) |
55 | { | 58 | { |
@@ -69,14 +72,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) | |||
69 | "Can't alloc buffer for fw\n"); | 72 | "Can't alloc buffer for fw\n"); |
70 | return 1; | 73 | return 1; |
71 | } | 74 | } |
72 | 75 | if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) && | |
76 | !IS_92C_SERIAL(rtlpriv->rtlhal.version)) { | ||
77 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin"; | ||
78 | } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) { | ||
79 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin"; | ||
80 | } else { | ||
81 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; | ||
82 | } | ||
83 | /* provide name of alternative file */ | ||
84 | rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin"; | ||
73 | pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); | 85 | pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); |
74 | rtlpriv->max_fw_size = 0x4000; | 86 | rtlpriv->max_fw_size = 0x4000; |
75 | err = request_firmware_nowait(THIS_MODULE, 1, | 87 | err = request_firmware_nowait(THIS_MODULE, 1, |
76 | rtlpriv->cfg->fw_name, rtlpriv->io.dev, | 88 | rtlpriv->cfg->fw_name, rtlpriv->io.dev, |
77 | GFP_KERNEL, hw, rtl_fw_cb); | 89 | GFP_KERNEL, hw, rtl_fw_cb); |
78 | |||
79 | |||
80 | return err; | 90 | return err; |
81 | } | 91 | } |
82 | 92 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c index 966be519edb8..7903c154de00 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c | |||
@@ -36,7 +36,7 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { | |||
36 | 0x804, 0x00000003, | 36 | 0x804, 0x00000003, |
37 | 0x808, 0x0000fc00, | 37 | 0x808, 0x0000fc00, |
38 | 0x80c, 0x0000000a, | 38 | 0x80c, 0x0000000a, |
39 | 0x810, 0x10005388, | 39 | 0x810, 0x10000330, |
40 | 0x814, 0x020c3d10, | 40 | 0x814, 0x020c3d10, |
41 | 0x818, 0x02200385, | 41 | 0x818, 0x02200385, |
42 | 0x81c, 0x00000000, | 42 | 0x81c, 0x00000000, |
@@ -110,22 +110,22 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { | |||
110 | 0xc44, 0x000100b7, | 110 | 0xc44, 0x000100b7, |
111 | 0xc48, 0xec020107, | 111 | 0xc48, 0xec020107, |
112 | 0xc4c, 0x007f037f, | 112 | 0xc4c, 0x007f037f, |
113 | 0xc50, 0x6954341e, | 113 | 0xc50, 0x69543420, |
114 | 0xc54, 0x43bc0094, | 114 | 0xc54, 0x43bc0094, |
115 | 0xc58, 0x6954341e, | 115 | 0xc58, 0x69543420, |
116 | 0xc5c, 0x433c0094, | 116 | 0xc5c, 0x433c0094, |
117 | 0xc60, 0x00000000, | 117 | 0xc60, 0x00000000, |
118 | 0xc64, 0x5116848b, | 118 | 0xc64, 0x5116848b, |
119 | 0xc68, 0x47c00bff, | 119 | 0xc68, 0x47c00bff, |
120 | 0xc6c, 0x00000036, | 120 | 0xc6c, 0x00000036, |
121 | 0xc70, 0x2c7f000d, | 121 | 0xc70, 0x2c7f000d, |
122 | 0xc74, 0x0186115b, | 122 | 0xc74, 0x2186115b, |
123 | 0xc78, 0x0000001f, | 123 | 0xc78, 0x0000001f, |
124 | 0xc7c, 0x00b99612, | 124 | 0xc7c, 0x00b99612, |
125 | 0xc80, 0x40000100, | 125 | 0xc80, 0x40000100, |
126 | 0xc84, 0x20f60000, | 126 | 0xc84, 0x20f60000, |
127 | 0xc88, 0x40000100, | 127 | 0xc88, 0x40000100, |
128 | 0xc8c, 0x20200000, | 128 | 0xc8c, 0xa0e40000, |
129 | 0xc90, 0x00121820, | 129 | 0xc90, 0x00121820, |
130 | 0xc94, 0x00000000, | 130 | 0xc94, 0x00000000, |
131 | 0xc98, 0x00121820, | 131 | 0xc98, 0x00121820, |
@@ -226,7 +226,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { | |||
226 | 0x804, 0x00000001, | 226 | 0x804, 0x00000001, |
227 | 0x808, 0x0000fc00, | 227 | 0x808, 0x0000fc00, |
228 | 0x80c, 0x0000000a, | 228 | 0x80c, 0x0000000a, |
229 | 0x810, 0x10005388, | 229 | 0x810, 0x10000330, |
230 | 0x814, 0x020c3d10, | 230 | 0x814, 0x020c3d10, |
231 | 0x818, 0x02200385, | 231 | 0x818, 0x02200385, |
232 | 0x81c, 0x00000000, | 232 | 0x81c, 0x00000000, |
@@ -300,9 +300,9 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { | |||
300 | 0xc44, 0x000100b7, | 300 | 0xc44, 0x000100b7, |
301 | 0xc48, 0xec020107, | 301 | 0xc48, 0xec020107, |
302 | 0xc4c, 0x007f037f, | 302 | 0xc4c, 0x007f037f, |
303 | 0xc50, 0x6954341e, | 303 | 0xc50, 0x69543420, |
304 | 0xc54, 0x43bc0094, | 304 | 0xc54, 0x43bc0094, |
305 | 0xc58, 0x6954341e, | 305 | 0xc58, 0x69543420, |
306 | 0xc5c, 0x433c0094, | 306 | 0xc5c, 0x433c0094, |
307 | 0xc60, 0x00000000, | 307 | 0xc60, 0x00000000, |
308 | 0xc64, 0x5116848b, | 308 | 0xc64, 0x5116848b, |
@@ -340,7 +340,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { | |||
340 | 0xce4, 0x00000000, | 340 | 0xce4, 0x00000000, |
341 | 0xce8, 0x37644302, | 341 | 0xce8, 0x37644302, |
342 | 0xcec, 0x2f97d40c, | 342 | 0xcec, 0x2f97d40c, |
343 | 0xd00, 0x00080740, | 343 | 0xd00, 0x00000740, |
344 | 0xd04, 0x00020401, | 344 | 0xd04, 0x00020401, |
345 | 0xd08, 0x0000907f, | 345 | 0xd08, 0x0000907f, |
346 | 0xd0c, 0x20010201, | 346 | 0xd0c, 0x20010201, |
@@ -633,17 +633,17 @@ u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = { | |||
633 | 0x012, 0x00071000, | 633 | 0x012, 0x00071000, |
634 | 0x012, 0x000b0000, | 634 | 0x012, 0x000b0000, |
635 | 0x012, 0x000fc000, | 635 | 0x012, 0x000fc000, |
636 | 0x013, 0x000287af, | 636 | 0x013, 0x000287b3, |
637 | 0x013, 0x000244b7, | 637 | 0x013, 0x000244b7, |
638 | 0x013, 0x000204ab, | 638 | 0x013, 0x000204ab, |
639 | 0x013, 0x0001c49f, | 639 | 0x013, 0x0001c49f, |
640 | 0x013, 0x00018493, | 640 | 0x013, 0x00018493, |
641 | 0x013, 0x00014297, | 641 | 0x013, 0x0001429b, |
642 | 0x013, 0x00010295, | 642 | 0x013, 0x00010299, |
643 | 0x013, 0x0000c298, | 643 | 0x013, 0x0000c29c, |
644 | 0x013, 0x0000819c, | 644 | 0x013, 0x000081a0, |
645 | 0x013, 0x000040a8, | 645 | 0x013, 0x000040ac, |
646 | 0x013, 0x0000001c, | 646 | 0x013, 0x00000020, |
647 | 0x014, 0x0001944c, | 647 | 0x014, 0x0001944c, |
648 | 0x014, 0x00059444, | 648 | 0x014, 0x00059444, |
649 | 0x014, 0x0009944c, | 649 | 0x014, 0x0009944c, |
@@ -932,10 +932,10 @@ u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = { | |||
932 | 0x608, 0x0000000e, | 932 | 0x608, 0x0000000e, |
933 | 0x609, 0x0000002a, | 933 | 0x609, 0x0000002a, |
934 | 0x652, 0x00000020, | 934 | 0x652, 0x00000020, |
935 | 0x63c, 0x0000000a, | 935 | 0x63c, 0x00000008, |
936 | 0x63d, 0x0000000e, | 936 | 0x63d, 0x00000008, |
937 | 0x63e, 0x0000000a, | 937 | 0x63e, 0x0000000c, |
938 | 0x63f, 0x0000000e, | 938 | 0x63f, 0x0000000c, |
939 | 0x66e, 0x00000005, | 939 | 0x66e, 0x00000005, |
940 | 0x700, 0x00000021, | 940 | 0x700, 0x00000021, |
941 | 0x701, 0x00000043, | 941 | 0x701, 0x00000043, |
diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c index 8ed31744a054..4f083fc1d360 100644 --- a/drivers/net/wireless/rtlwifi/stats.c +++ b/drivers/net/wireless/rtlwifi/stats.c | |||
@@ -176,6 +176,7 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) | |||
176 | struct rtl_sta_info *drv_priv = NULL; | 176 | struct rtl_sta_info *drv_priv = NULL; |
177 | struct ieee80211_sta *sta = NULL; | 177 | struct ieee80211_sta *sta = NULL; |
178 | long undec_sm_pwdb; | 178 | long undec_sm_pwdb; |
179 | long undec_sm_cck; | ||
179 | 180 | ||
180 | rcu_read_lock(); | 181 | rcu_read_lock(); |
181 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) | 182 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) |
@@ -185,12 +186,16 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) | |||
185 | if (sta) { | 186 | if (sta) { |
186 | drv_priv = (struct rtl_sta_info *) sta->drv_priv; | 187 | drv_priv = (struct rtl_sta_info *) sta->drv_priv; |
187 | undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; | 188 | undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; |
189 | undec_sm_cck = drv_priv->rssi_stat.undec_sm_cck; | ||
188 | } else { | 190 | } else { |
189 | undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | 191 | undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; |
192 | undec_sm_cck = rtlpriv->dm.undec_sm_cck; | ||
190 | } | 193 | } |
191 | 194 | ||
192 | if (undec_sm_pwdb < 0) | 195 | if (undec_sm_pwdb < 0) |
193 | undec_sm_pwdb = pstatus->rx_pwdb_all; | 196 | undec_sm_pwdb = pstatus->rx_pwdb_all; |
197 | if (undec_sm_cck < 0) | ||
198 | undec_sm_cck = pstatus->rx_pwdb_all; | ||
194 | if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { | 199 | if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { |
195 | undec_sm_pwdb = (((undec_sm_pwdb) * | 200 | undec_sm_pwdb = (((undec_sm_pwdb) * |
196 | (RX_SMOOTH_FACTOR - 1)) + | 201 | (RX_SMOOTH_FACTOR - 1)) + |
@@ -200,6 +205,15 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) | |||
200 | undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + | 205 | undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) + |
201 | (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | 206 | (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
202 | } | 207 | } |
208 | if (pstatus->rx_pwdb_all > (u32) undec_sm_cck) { | ||
209 | undec_sm_cck = (((undec_sm_pwdb) * | ||
210 | (RX_SMOOTH_FACTOR - 1)) + | ||
211 | (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
212 | undec_sm_cck = undec_sm_cck + 1; | ||
213 | } else { | ||
214 | undec_sm_pwdb = (((undec_sm_cck) * (RX_SMOOTH_FACTOR - 1)) + | ||
215 | (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
216 | } | ||
203 | 217 | ||
204 | if (sta) { | 218 | if (sta) { |
205 | drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; | 219 | drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 6e2b5c5c83c8..4933f02ce1d5 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -475,14 +475,14 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, | |||
475 | rtlpriv->stats.rxbytesunicast += skb->len; | 475 | rtlpriv->stats.rxbytesunicast += skb->len; |
476 | } | 476 | } |
477 | 477 | ||
478 | rtl_is_special_data(hw, skb, false); | ||
479 | |||
480 | if (ieee80211_is_data(fc)) { | 478 | if (ieee80211_is_data(fc)) { |
481 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); | 479 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); |
482 | 480 | ||
483 | if (unicast) | 481 | if (unicast) |
484 | rtlpriv->link_info.num_rx_inperiod++; | 482 | rtlpriv->link_info.num_rx_inperiod++; |
485 | } | 483 | } |
484 | /* static bcn for roaming */ | ||
485 | rtl_beacon_statistic(hw, skb); | ||
486 | } | 486 | } |
487 | } | 487 | } |
488 | 488 | ||
@@ -517,8 +517,6 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, | |||
517 | rtlpriv->stats.rxbytesunicast += skb->len; | 517 | rtlpriv->stats.rxbytesunicast += skb->len; |
518 | } | 518 | } |
519 | 519 | ||
520 | rtl_is_special_data(hw, skb, false); | ||
521 | |||
522 | if (ieee80211_is_data(fc)) { | 520 | if (ieee80211_is_data(fc)) { |
523 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); | 521 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); |
524 | 522 | ||
@@ -553,7 +551,7 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
553 | } | 551 | } |
554 | } | 552 | } |
555 | 553 | ||
556 | #define __RX_SKB_MAX_QUEUED 32 | 554 | #define __RX_SKB_MAX_QUEUED 64 |
557 | 555 | ||
558 | static void _rtl_rx_work(unsigned long param) | 556 | static void _rtl_rx_work(unsigned long param) |
559 | { | 557 | { |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 0c65386fa30d..8c647391bedf 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -1033,6 +1033,7 @@ struct rtl_ht_agg { | |||
1033 | 1033 | ||
1034 | struct rssi_sta { | 1034 | struct rssi_sta { |
1035 | long undec_sm_pwdb; | 1035 | long undec_sm_pwdb; |
1036 | long undec_sm_cck; | ||
1036 | }; | 1037 | }; |
1037 | 1038 | ||
1038 | struct rtl_tid_data { | 1039 | struct rtl_tid_data { |
@@ -1323,8 +1324,10 @@ struct fast_ant_training { | |||
1323 | struct rtl_dm { | 1324 | struct rtl_dm { |
1324 | /*PHY status for Dynamic Management */ | 1325 | /*PHY status for Dynamic Management */ |
1325 | long entry_min_undec_sm_pwdb; | 1326 | long entry_min_undec_sm_pwdb; |
1327 | long undec_sm_cck; | ||
1326 | long undec_sm_pwdb; /*out dm */ | 1328 | long undec_sm_pwdb; /*out dm */ |
1327 | long entry_max_undec_sm_pwdb; | 1329 | long entry_max_undec_sm_pwdb; |
1330 | s32 ofdm_pkt_cnt; | ||
1328 | bool dm_initialgain_enable; | 1331 | bool dm_initialgain_enable; |
1329 | bool dynamic_txpower_enable; | 1332 | bool dynamic_txpower_enable; |
1330 | bool current_turbo_edca; | 1333 | bool current_turbo_edca; |
@@ -1339,6 +1342,7 @@ struct rtl_dm { | |||
1339 | bool inform_fw_driverctrldm; | 1342 | bool inform_fw_driverctrldm; |
1340 | bool current_mrc_switch; | 1343 | bool current_mrc_switch; |
1341 | u8 txpowercount; | 1344 | u8 txpowercount; |
1345 | u8 powerindex_backup[6]; | ||
1342 | 1346 | ||
1343 | u8 thermalvalue_rxgain; | 1347 | u8 thermalvalue_rxgain; |
1344 | u8 thermalvalue_iqk; | 1348 | u8 thermalvalue_iqk; |
@@ -1350,7 +1354,9 @@ struct rtl_dm { | |||
1350 | bool done_txpower; | 1354 | bool done_txpower; |
1351 | u8 dynamic_txhighpower_lvl; /*Tx high power level */ | 1355 | u8 dynamic_txhighpower_lvl; /*Tx high power level */ |
1352 | u8 dm_flag; /*Indicate each dynamic mechanism's status. */ | 1356 | u8 dm_flag; /*Indicate each dynamic mechanism's status. */ |
1357 | u8 dm_flag_tmp; | ||
1353 | u8 dm_type; | 1358 | u8 dm_type; |
1359 | u8 dm_rssi_sel; | ||
1354 | u8 txpower_track_control; | 1360 | u8 txpower_track_control; |
1355 | bool interrupt_migration; | 1361 | bool interrupt_migration; |
1356 | bool disable_tx_int; | 1362 | bool disable_tx_int; |
@@ -1804,6 +1810,7 @@ struct rtl_hal_cfg { | |||
1804 | bool write_readback; | 1810 | bool write_readback; |
1805 | char *name; | 1811 | char *name; |
1806 | char *fw_name; | 1812 | char *fw_name; |
1813 | char *alt_fw_name; | ||
1807 | struct rtl_hal_ops *ops; | 1814 | struct rtl_hal_ops *ops; |
1808 | struct rtl_mod_params *mod_params; | 1815 | struct rtl_mod_params *mod_params; |
1809 | struct rtl_hal_usbint_cfg *usb_interface_cfg; | 1816 | struct rtl_hal_usbint_cfg *usb_interface_cfg; |
@@ -1948,6 +1955,7 @@ struct dig_t { | |||
1948 | u8 pre_ccastate; | 1955 | u8 pre_ccastate; |
1949 | u8 cur_ccasate; | 1956 | u8 cur_ccasate; |
1950 | u8 large_fa_hit; | 1957 | u8 large_fa_hit; |
1958 | u8 dig_dynamic_min; | ||
1951 | u8 forbidden_igi; | 1959 | u8 forbidden_igi; |
1952 | u8 dig_state; | 1960 | u8 dig_state; |
1953 | u8 dig_highpwrstate; | 1961 | u8 dig_highpwrstate; |
@@ -2028,22 +2036,15 @@ struct rtl_priv { | |||
2028 | struct dig_t dm_digtable; | 2036 | struct dig_t dm_digtable; |
2029 | struct ps_t dm_pstable; | 2037 | struct ps_t dm_pstable; |
2030 | 2038 | ||
2031 | /* section shared by individual drivers */ | 2039 | u32 reg_874; |
2032 | union { | 2040 | u32 reg_c70; |
2033 | struct { /* data buffer pointer for USB reads */ | 2041 | u32 reg_85c; |
2034 | __le32 *usb_data; | 2042 | u32 reg_a74; |
2035 | int usb_data_index; | 2043 | bool reg_init; /* true if regs saved */ |
2036 | bool initialized; | 2044 | bool bt_operation_on; |
2037 | }; | 2045 | __le32 *usb_data; |
2038 | struct { /* section for 8723ae */ | 2046 | int usb_data_index; |
2039 | bool reg_init; /* true if regs saved */ | 2047 | bool initialized; |
2040 | u32 reg_874; | ||
2041 | u32 reg_c70; | ||
2042 | u32 reg_85c; | ||
2043 | u32 reg_a74; | ||
2044 | bool bt_operation_on; | ||
2045 | }; | ||
2046 | }; | ||
2047 | bool enter_ps; /* true when entering PS */ | 2048 | bool enter_ps; /* true when entering PS */ |
2048 | u8 rate_mask[5]; | 2049 | u8 rate_mask[5]; |
2049 | 2050 | ||
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index db6430c1a084..374268d5ac6a 100644 --- a/drivers/net/wireless/ti/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c | |||
@@ -18,10 +18,8 @@ int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, | |||
18 | wl1251_debug(DEBUG_ACX, "acx frame rates"); | 18 | wl1251_debug(DEBUG_ACX, "acx frame rates"); |
19 | 19 | ||
20 | rates = kzalloc(sizeof(*rates), GFP_KERNEL); | 20 | rates = kzalloc(sizeof(*rates), GFP_KERNEL); |
21 | if (!rates) { | 21 | if (!rates) |
22 | ret = -ENOMEM; | 22 | return -ENOMEM; |
23 | goto out; | ||
24 | } | ||
25 | 23 | ||
26 | rates->tx_ctrl_frame_rate = ctrl_rate; | 24 | rates->tx_ctrl_frame_rate = ctrl_rate; |
27 | rates->tx_ctrl_frame_mod = ctrl_mod; | 25 | rates->tx_ctrl_frame_mod = ctrl_mod; |
@@ -49,10 +47,8 @@ int wl1251_acx_station_id(struct wl1251 *wl) | |||
49 | wl1251_debug(DEBUG_ACX, "acx dot11_station_id"); | 47 | wl1251_debug(DEBUG_ACX, "acx dot11_station_id"); |
50 | 48 | ||
51 | mac = kzalloc(sizeof(*mac), GFP_KERNEL); | 49 | mac = kzalloc(sizeof(*mac), GFP_KERNEL); |
52 | if (!mac) { | 50 | if (!mac) |
53 | ret = -ENOMEM; | 51 | return -ENOMEM; |
54 | goto out; | ||
55 | } | ||
56 | 52 | ||
57 | for (i = 0; i < ETH_ALEN; i++) | 53 | for (i = 0; i < ETH_ALEN; i++) |
58 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; | 54 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; |
@@ -74,10 +70,8 @@ int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) | |||
74 | wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); | 70 | wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); |
75 | 71 | ||
76 | default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); | 72 | default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); |
77 | if (!default_key) { | 73 | if (!default_key) |
78 | ret = -ENOMEM; | 74 | return -ENOMEM; |
79 | goto out; | ||
80 | } | ||
81 | 75 | ||
82 | default_key->id = key_id; | 76 | default_key->id = key_id; |
83 | 77 | ||
@@ -104,10 +98,8 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, | |||
104 | wl1251_debug(DEBUG_ACX, "acx wake up conditions"); | 98 | wl1251_debug(DEBUG_ACX, "acx wake up conditions"); |
105 | 99 | ||
106 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); | 100 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); |
107 | if (!wake_up) { | 101 | if (!wake_up) |
108 | ret = -ENOMEM; | 102 | return -ENOMEM; |
109 | goto out; | ||
110 | } | ||
111 | 103 | ||
112 | wake_up->wake_up_event = wake_up_event; | 104 | wake_up->wake_up_event = wake_up_event; |
113 | wake_up->listen_interval = listen_interval; | 105 | wake_up->listen_interval = listen_interval; |
@@ -132,16 +124,13 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth) | |||
132 | wl1251_debug(DEBUG_ACX, "acx sleep auth"); | 124 | wl1251_debug(DEBUG_ACX, "acx sleep auth"); |
133 | 125 | ||
134 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); | 126 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); |
135 | if (!auth) { | 127 | if (!auth) |
136 | ret = -ENOMEM; | 128 | return -ENOMEM; |
137 | goto out; | ||
138 | } | ||
139 | 129 | ||
140 | auth->sleep_auth = sleep_auth; | 130 | auth->sleep_auth = sleep_auth; |
141 | 131 | ||
142 | ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); | 132 | ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); |
143 | 133 | ||
144 | out: | ||
145 | kfree(auth); | 134 | kfree(auth); |
146 | return ret; | 135 | return ret; |
147 | } | 136 | } |
@@ -154,10 +143,8 @@ int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len) | |||
154 | wl1251_debug(DEBUG_ACX, "acx fw rev"); | 143 | wl1251_debug(DEBUG_ACX, "acx fw rev"); |
155 | 144 | ||
156 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); | 145 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); |
157 | if (!rev) { | 146 | if (!rev) |
158 | ret = -ENOMEM; | 147 | return -ENOMEM; |
159 | goto out; | ||
160 | } | ||
161 | 148 | ||
162 | ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); | 149 | ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); |
163 | if (ret < 0) { | 150 | if (ret < 0) { |
@@ -191,10 +178,8 @@ int wl1251_acx_tx_power(struct wl1251 *wl, int power) | |||
191 | return -EINVAL; | 178 | return -EINVAL; |
192 | 179 | ||
193 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 180 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
194 | if (!acx) { | 181 | if (!acx) |
195 | ret = -ENOMEM; | 182 | return -ENOMEM; |
196 | goto out; | ||
197 | } | ||
198 | 183 | ||
199 | acx->current_tx_power = power * 10; | 184 | acx->current_tx_power = power * 10; |
200 | 185 | ||
@@ -217,10 +202,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl) | |||
217 | wl1251_debug(DEBUG_ACX, "acx feature cfg"); | 202 | wl1251_debug(DEBUG_ACX, "acx feature cfg"); |
218 | 203 | ||
219 | feature = kzalloc(sizeof(*feature), GFP_KERNEL); | 204 | feature = kzalloc(sizeof(*feature), GFP_KERNEL); |
220 | if (!feature) { | 205 | if (!feature) |
221 | ret = -ENOMEM; | 206 | return -ENOMEM; |
222 | goto out; | ||
223 | } | ||
224 | 207 | ||
225 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ | 208 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ |
226 | feature->data_flow_options = 0; | 209 | feature->data_flow_options = 0; |
@@ -261,10 +244,8 @@ int wl1251_acx_data_path_params(struct wl1251 *wl, | |||
261 | wl1251_debug(DEBUG_ACX, "acx data path params"); | 244 | wl1251_debug(DEBUG_ACX, "acx data path params"); |
262 | 245 | ||
263 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 246 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
264 | if (!params) { | 247 | if (!params) |
265 | ret = -ENOMEM; | 248 | return -ENOMEM; |
266 | goto out; | ||
267 | } | ||
268 | 249 | ||
269 | params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; | 250 | params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; |
270 | params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; | 251 | params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; |
@@ -309,10 +290,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time) | |||
309 | wl1251_debug(DEBUG_ACX, "acx rx msdu life time"); | 290 | wl1251_debug(DEBUG_ACX, "acx rx msdu life time"); |
310 | 291 | ||
311 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 292 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
312 | if (!acx) { | 293 | if (!acx) |
313 | ret = -ENOMEM; | 294 | return -ENOMEM; |
314 | goto out; | ||
315 | } | ||
316 | 295 | ||
317 | acx->lifetime = life_time; | 296 | acx->lifetime = life_time; |
318 | ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, | 297 | ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, |
@@ -335,10 +314,8 @@ int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter) | |||
335 | wl1251_debug(DEBUG_ACX, "acx rx config"); | 314 | wl1251_debug(DEBUG_ACX, "acx rx config"); |
336 | 315 | ||
337 | rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); | 316 | rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); |
338 | if (!rx_config) { | 317 | if (!rx_config) |
339 | ret = -ENOMEM; | 318 | return -ENOMEM; |
340 | goto out; | ||
341 | } | ||
342 | 319 | ||
343 | rx_config->config_options = config; | 320 | rx_config->config_options = config; |
344 | rx_config->filter_options = filter; | 321 | rx_config->filter_options = filter; |
@@ -363,10 +340,8 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl) | |||
363 | wl1251_debug(DEBUG_ACX, "acx data pd threshold"); | 340 | wl1251_debug(DEBUG_ACX, "acx data pd threshold"); |
364 | 341 | ||
365 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | 342 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); |
366 | if (!pd) { | 343 | if (!pd) |
367 | ret = -ENOMEM; | 344 | return -ENOMEM; |
368 | goto out; | ||
369 | } | ||
370 | 345 | ||
371 | /* FIXME: threshold value not set */ | 346 | /* FIXME: threshold value not set */ |
372 | 347 | ||
@@ -389,10 +364,8 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) | |||
389 | wl1251_debug(DEBUG_ACX, "acx slot"); | 364 | wl1251_debug(DEBUG_ACX, "acx slot"); |
390 | 365 | ||
391 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 366 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
392 | if (!slot) { | 367 | if (!slot) |
393 | ret = -ENOMEM; | 368 | return -ENOMEM; |
394 | goto out; | ||
395 | } | ||
396 | 369 | ||
397 | slot->wone_index = STATION_WONE_INDEX; | 370 | slot->wone_index = STATION_WONE_INDEX; |
398 | slot->slot_time = slot_time; | 371 | slot->slot_time = slot_time; |
@@ -416,10 +389,8 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl) | |||
416 | wl1251_debug(DEBUG_ACX, "acx group address tbl"); | 389 | wl1251_debug(DEBUG_ACX, "acx group address tbl"); |
417 | 390 | ||
418 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 391 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
419 | if (!acx) { | 392 | if (!acx) |
420 | ret = -ENOMEM; | 393 | return -ENOMEM; |
421 | goto out; | ||
422 | } | ||
423 | 394 | ||
424 | /* MAC filtering */ | 395 | /* MAC filtering */ |
425 | acx->enabled = 0; | 396 | acx->enabled = 0; |
@@ -444,10 +415,8 @@ int wl1251_acx_service_period_timeout(struct wl1251 *wl) | |||
444 | int ret; | 415 | int ret; |
445 | 416 | ||
446 | rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); | 417 | rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); |
447 | if (!rx_timeout) { | 418 | if (!rx_timeout) |
448 | ret = -ENOMEM; | 419 | return -ENOMEM; |
449 | goto out; | ||
450 | } | ||
451 | 420 | ||
452 | wl1251_debug(DEBUG_ACX, "acx service period timeout"); | 421 | wl1251_debug(DEBUG_ACX, "acx service period timeout"); |
453 | 422 | ||
@@ -475,10 +444,8 @@ int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold) | |||
475 | wl1251_debug(DEBUG_ACX, "acx rts threshold"); | 444 | wl1251_debug(DEBUG_ACX, "acx rts threshold"); |
476 | 445 | ||
477 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); | 446 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); |
478 | if (!rts) { | 447 | if (!rts) |
479 | ret = -ENOMEM; | 448 | return -ENOMEM; |
480 | goto out; | ||
481 | } | ||
482 | 449 | ||
483 | rts->threshold = rts_threshold; | 450 | rts->threshold = rts_threshold; |
484 | 451 | ||
@@ -501,10 +468,8 @@ int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter) | |||
501 | wl1251_debug(DEBUG_ACX, "acx beacon filter opt"); | 468 | wl1251_debug(DEBUG_ACX, "acx beacon filter opt"); |
502 | 469 | ||
503 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); | 470 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); |
504 | if (!beacon_filter) { | 471 | if (!beacon_filter) |
505 | ret = -ENOMEM; | 472 | return -ENOMEM; |
506 | goto out; | ||
507 | } | ||
508 | 473 | ||
509 | beacon_filter->enable = enable_filter; | 474 | beacon_filter->enable = enable_filter; |
510 | beacon_filter->max_num_beacons = 0; | 475 | beacon_filter->max_num_beacons = 0; |
@@ -530,10 +495,8 @@ int wl1251_acx_beacon_filter_table(struct wl1251 *wl) | |||
530 | wl1251_debug(DEBUG_ACX, "acx beacon filter table"); | 495 | wl1251_debug(DEBUG_ACX, "acx beacon filter table"); |
531 | 496 | ||
532 | ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); | 497 | ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); |
533 | if (!ie_table) { | 498 | if (!ie_table) |
534 | ret = -ENOMEM; | 499 | return -ENOMEM; |
535 | goto out; | ||
536 | } | ||
537 | 500 | ||
538 | /* configure default beacon pass-through rules */ | 501 | /* configure default beacon pass-through rules */ |
539 | ie_table->num_ie = 1; | 502 | ie_table->num_ie = 1; |
@@ -560,10 +523,8 @@ int wl1251_acx_conn_monit_params(struct wl1251 *wl) | |||
560 | wl1251_debug(DEBUG_ACX, "acx connection monitor parameters"); | 523 | wl1251_debug(DEBUG_ACX, "acx connection monitor parameters"); |
561 | 524 | ||
562 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 525 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
563 | if (!acx) { | 526 | if (!acx) |
564 | ret = -ENOMEM; | 527 | return -ENOMEM; |
565 | goto out; | ||
566 | } | ||
567 | 528 | ||
568 | acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD; | 529 | acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD; |
569 | acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT; | 530 | acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT; |
@@ -589,10 +550,8 @@ int wl1251_acx_sg_enable(struct wl1251 *wl) | |||
589 | wl1251_debug(DEBUG_ACX, "acx sg enable"); | 550 | wl1251_debug(DEBUG_ACX, "acx sg enable"); |
590 | 551 | ||
591 | pta = kzalloc(sizeof(*pta), GFP_KERNEL); | 552 | pta = kzalloc(sizeof(*pta), GFP_KERNEL); |
592 | if (!pta) { | 553 | if (!pta) |
593 | ret = -ENOMEM; | 554 | return -ENOMEM; |
594 | goto out; | ||
595 | } | ||
596 | 555 | ||
597 | pta->enable = SG_ENABLE; | 556 | pta->enable = SG_ENABLE; |
598 | 557 | ||
@@ -615,10 +574,8 @@ int wl1251_acx_sg_cfg(struct wl1251 *wl) | |||
615 | wl1251_debug(DEBUG_ACX, "acx sg cfg"); | 574 | wl1251_debug(DEBUG_ACX, "acx sg cfg"); |
616 | 575 | ||
617 | param = kzalloc(sizeof(*param), GFP_KERNEL); | 576 | param = kzalloc(sizeof(*param), GFP_KERNEL); |
618 | if (!param) { | 577 | if (!param) |
619 | ret = -ENOMEM; | 578 | return -ENOMEM; |
620 | goto out; | ||
621 | } | ||
622 | 579 | ||
623 | /* BT-WLAN coext parameters */ | 580 | /* BT-WLAN coext parameters */ |
624 | param->min_rate = RATE_INDEX_24MBPS; | 581 | param->min_rate = RATE_INDEX_24MBPS; |
@@ -669,10 +626,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl) | |||
669 | wl1251_debug(DEBUG_ACX, "acx cca threshold"); | 626 | wl1251_debug(DEBUG_ACX, "acx cca threshold"); |
670 | 627 | ||
671 | detection = kzalloc(sizeof(*detection), GFP_KERNEL); | 628 | detection = kzalloc(sizeof(*detection), GFP_KERNEL); |
672 | if (!detection) { | 629 | if (!detection) |
673 | ret = -ENOMEM; | 630 | return -ENOMEM; |
674 | goto out; | ||
675 | } | ||
676 | 631 | ||
677 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; | 632 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; |
678 | detection->tx_energy_detection = 0; | 633 | detection->tx_energy_detection = 0; |
@@ -682,7 +637,6 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl) | |||
682 | if (ret < 0) | 637 | if (ret < 0) |
683 | wl1251_warning("failed to set cca threshold: %d", ret); | 638 | wl1251_warning("failed to set cca threshold: %d", ret); |
684 | 639 | ||
685 | out: | ||
686 | kfree(detection); | 640 | kfree(detection); |
687 | return ret; | 641 | return ret; |
688 | } | 642 | } |
@@ -695,10 +649,8 @@ int wl1251_acx_bcn_dtim_options(struct wl1251 *wl) | |||
695 | wl1251_debug(DEBUG_ACX, "acx bcn dtim options"); | 649 | wl1251_debug(DEBUG_ACX, "acx bcn dtim options"); |
696 | 650 | ||
697 | bb = kzalloc(sizeof(*bb), GFP_KERNEL); | 651 | bb = kzalloc(sizeof(*bb), GFP_KERNEL); |
698 | if (!bb) { | 652 | if (!bb) |
699 | ret = -ENOMEM; | 653 | return -ENOMEM; |
700 | goto out; | ||
701 | } | ||
702 | 654 | ||
703 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; | 655 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; |
704 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; | 656 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; |
@@ -724,10 +676,8 @@ int wl1251_acx_aid(struct wl1251 *wl, u16 aid) | |||
724 | wl1251_debug(DEBUG_ACX, "acx aid"); | 676 | wl1251_debug(DEBUG_ACX, "acx aid"); |
725 | 677 | ||
726 | acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); | 678 | acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); |
727 | if (!acx_aid) { | 679 | if (!acx_aid) |
728 | ret = -ENOMEM; | 680 | return -ENOMEM; |
729 | goto out; | ||
730 | } | ||
731 | 681 | ||
732 | acx_aid->aid = aid; | 682 | acx_aid->aid = aid; |
733 | 683 | ||
@@ -750,10 +700,8 @@ int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask) | |||
750 | wl1251_debug(DEBUG_ACX, "acx event mbox mask"); | 700 | wl1251_debug(DEBUG_ACX, "acx event mbox mask"); |
751 | 701 | ||
752 | mask = kzalloc(sizeof(*mask), GFP_KERNEL); | 702 | mask = kzalloc(sizeof(*mask), GFP_KERNEL); |
753 | if (!mask) { | 703 | if (!mask) |
754 | ret = -ENOMEM; | 704 | return -ENOMEM; |
755 | goto out; | ||
756 | } | ||
757 | 705 | ||
758 | /* high event mask is unused */ | 706 | /* high event mask is unused */ |
759 | mask->high_event_mask = 0xffffffff; | 707 | mask->high_event_mask = 0xffffffff; |
@@ -805,10 +753,8 @@ int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) | |||
805 | wl1251_debug(DEBUG_ACX, "acx_set_preamble"); | 753 | wl1251_debug(DEBUG_ACX, "acx_set_preamble"); |
806 | 754 | ||
807 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 755 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
808 | if (!acx) { | 756 | if (!acx) |
809 | ret = -ENOMEM; | 757 | return -ENOMEM; |
810 | goto out; | ||
811 | } | ||
812 | 758 | ||
813 | acx->preamble = preamble; | 759 | acx->preamble = preamble; |
814 | 760 | ||
@@ -832,10 +778,8 @@ int wl1251_acx_cts_protect(struct wl1251 *wl, | |||
832 | wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect"); | 778 | wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect"); |
833 | 779 | ||
834 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 780 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
835 | if (!acx) { | 781 | if (!acx) |
836 | ret = -ENOMEM; | 782 | return -ENOMEM; |
837 | goto out; | ||
838 | } | ||
839 | 783 | ||
840 | acx->ctsprotect = ctsprotect; | 784 | acx->ctsprotect = ctsprotect; |
841 | 785 | ||
@@ -856,10 +800,8 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime) | |||
856 | int ret; | 800 | int ret; |
857 | 801 | ||
858 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); | 802 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); |
859 | if (!tsf_info) { | 803 | if (!tsf_info) |
860 | ret = -ENOMEM; | 804 | return -ENOMEM; |
861 | goto out; | ||
862 | } | ||
863 | 805 | ||
864 | ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, | 806 | ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, |
865 | tsf_info, sizeof(*tsf_info)); | 807 | tsf_info, sizeof(*tsf_info)); |
@@ -900,11 +842,8 @@ int wl1251_acx_rate_policies(struct wl1251 *wl) | |||
900 | wl1251_debug(DEBUG_ACX, "acx rate policies"); | 842 | wl1251_debug(DEBUG_ACX, "acx rate policies"); |
901 | 843 | ||
902 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 844 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
903 | 845 | if (!acx) | |
904 | if (!acx) { | 846 | return -ENOMEM; |
905 | ret = -ENOMEM; | ||
906 | goto out; | ||
907 | } | ||
908 | 847 | ||
909 | /* configure one default (one-size-fits-all) rate class */ | 848 | /* configure one default (one-size-fits-all) rate class */ |
910 | acx->rate_class_cnt = 1; | 849 | acx->rate_class_cnt = 1; |
@@ -932,10 +871,8 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl) | |||
932 | wl1251_debug(DEBUG_ACX, "acx mem cfg"); | 871 | wl1251_debug(DEBUG_ACX, "acx mem cfg"); |
933 | 872 | ||
934 | mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); | 873 | mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); |
935 | if (!mem_conf) { | 874 | if (!mem_conf) |
936 | ret = -ENOMEM; | 875 | return -ENOMEM; |
937 | goto out; | ||
938 | } | ||
939 | 876 | ||
940 | /* memory config */ | 877 | /* memory config */ |
941 | mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); | 878 | mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); |
@@ -979,10 +916,8 @@ int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim) | |||
979 | wl1251_debug(DEBUG_ACX, "acx tbtt and dtim"); | 916 | wl1251_debug(DEBUG_ACX, "acx tbtt and dtim"); |
980 | 917 | ||
981 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 918 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
982 | if (!acx) { | 919 | if (!acx) |
983 | ret = -ENOMEM; | 920 | return -ENOMEM; |
984 | goto out; | ||
985 | } | ||
986 | 921 | ||
987 | acx->tbtt = tbtt; | 922 | acx->tbtt = tbtt; |
988 | acx->dtim = dtim; | 923 | acx->dtim = dtim; |
@@ -1008,10 +943,8 @@ int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, | |||
1008 | wl1251_debug(DEBUG_ACX, "acx bet enable"); | 943 | wl1251_debug(DEBUG_ACX, "acx bet enable"); |
1009 | 944 | ||
1010 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 945 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1011 | if (!acx) { | 946 | if (!acx) |
1012 | ret = -ENOMEM; | 947 | return -ENOMEM; |
1013 | goto out; | ||
1014 | } | ||
1015 | 948 | ||
1016 | acx->enable = mode; | 949 | acx->enable = mode; |
1017 | acx->max_consecutive = max_consecutive; | 950 | acx->max_consecutive = max_consecutive; |
@@ -1037,11 +970,8 @@ int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | |||
1037 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); | 970 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); |
1038 | 971 | ||
1039 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 972 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1040 | 973 | if (!acx) | |
1041 | if (!acx) { | 974 | return -ENOMEM; |
1042 | ret = -ENOMEM; | ||
1043 | goto out; | ||
1044 | } | ||
1045 | 975 | ||
1046 | acx->ac = ac; | 976 | acx->ac = ac; |
1047 | acx->cw_min = cw_min; | 977 | acx->cw_min = cw_min; |
@@ -1073,11 +1003,8 @@ int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | |||
1073 | ps_scheme, ack_policy); | 1003 | ps_scheme, ack_policy); |
1074 | 1004 | ||
1075 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 1005 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1076 | 1006 | if (!acx) | |
1077 | if (!acx) { | 1007 | return -ENOMEM; |
1078 | ret = -ENOMEM; | ||
1079 | goto out; | ||
1080 | } | ||
1081 | 1008 | ||
1082 | acx->queue = queue; | 1009 | acx->queue = queue; |
1083 | acx->type = type; | 1010 | acx->type = type; |
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index 4a0bbb13806b..7541bd1a4a4b 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c | |||
@@ -47,7 +47,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, | |||
47 | * In active scans, we only scan channels not | 47 | * In active scans, we only scan channels not |
48 | * marked as passive. | 48 | * marked as passive. |
49 | */ | 49 | */ |
50 | (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { | 50 | (passive || !(flags & IEEE80211_CHAN_NO_IR))) { |
51 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | 51 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", |
52 | req->channels[i]->band, | 52 | req->channels[i]->band, |
53 | req->channels[i]->center_freq); | 53 | req->channels[i]->center_freq); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 34d9dfff2ad3..9b2ecf52449f 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -1688,7 +1688,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) | |||
1688 | 1688 | ||
1689 | if (channel->flags & (IEEE80211_CHAN_DISABLED | | 1689 | if (channel->flags & (IEEE80211_CHAN_DISABLED | |
1690 | IEEE80211_CHAN_RADAR | | 1690 | IEEE80211_CHAN_RADAR | |
1691 | IEEE80211_CHAN_PASSIVE_SCAN)) | 1691 | IEEE80211_CHAN_NO_IR)) |
1692 | continue; | 1692 | continue; |
1693 | 1693 | ||
1694 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch); | 1694 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch); |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 0368b9cbfb89..e9da47cead58 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -91,8 +91,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy, | |||
91 | continue; | 91 | continue; |
92 | 92 | ||
93 | if (ch->flags & IEEE80211_CHAN_RADAR) | 93 | if (ch->flags & IEEE80211_CHAN_RADAR) |
94 | ch->flags |= IEEE80211_CHAN_NO_IBSS | | 94 | ch->flags |= IEEE80211_CHAN_NO_IR; |
95 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
96 | 95 | ||
97 | } | 96 | } |
98 | 97 | ||
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index 7ed86203304b..1e3d51cd673a 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
@@ -188,16 +188,14 @@ wlcore_scan_get_channels(struct wl1271 *wl, | |||
188 | flags = req_channels[i]->flags; | 188 | flags = req_channels[i]->flags; |
189 | 189 | ||
190 | if (force_passive) | 190 | if (force_passive) |
191 | flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 191 | flags |= IEEE80211_CHAN_NO_IR; |
192 | 192 | ||
193 | if ((req_channels[i]->band == band) && | 193 | if ((req_channels[i]->band == band) && |
194 | !(flags & IEEE80211_CHAN_DISABLED) && | 194 | !(flags & IEEE80211_CHAN_DISABLED) && |
195 | (!!(flags & IEEE80211_CHAN_RADAR) == radar) && | 195 | (!!(flags & IEEE80211_CHAN_RADAR) == radar) && |
196 | /* if radar is set, we ignore the passive flag */ | 196 | /* if radar is set, we ignore the passive flag */ |
197 | (radar || | 197 | (radar || |
198 | !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { | 198 | !!(flags & IEEE80211_CHAN_NO_IR) == passive)) { |
199 | |||
200 | |||
201 | if (flags & IEEE80211_CHAN_RADAR) { | 199 | if (flags & IEEE80211_CHAN_RADAR) { |
202 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; | 200 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; |
203 | 201 | ||
@@ -220,7 +218,7 @@ wlcore_scan_get_channels(struct wl1271 *wl, | |||
220 | (band == IEEE80211_BAND_2GHZ) && | 218 | (band == IEEE80211_BAND_2GHZ) && |
221 | (channels[j].channel >= 12) && | 219 | (channels[j].channel >= 12) && |
222 | (channels[j].channel <= 14) && | 220 | (channels[j].channel <= 14) && |
223 | (flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 221 | (flags & IEEE80211_CHAN_NO_IR) && |
224 | !force_passive) { | 222 | !force_passive) { |
225 | /* pactive channels treated as DFS */ | 223 | /* pactive channels treated as DFS */ |
226 | channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; | 224 | channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; |
@@ -243,8 +241,8 @@ wlcore_scan_get_channels(struct wl1271 *wl, | |||
243 | max_dwell_time_active, | 241 | max_dwell_time_active, |
244 | flags & IEEE80211_CHAN_RADAR ? | 242 | flags & IEEE80211_CHAN_RADAR ? |
245 | ", DFS" : "", | 243 | ", DFS" : "", |
246 | flags & IEEE80211_CHAN_PASSIVE_SCAN ? | 244 | flags & IEEE80211_CHAN_NO_IR ? |
247 | ", PASSIVE" : ""); | 245 | ", NO-IR" : ""); |
248 | j++; | 246 | j++; |
249 | } | 247 | } |
250 | } | 248 | } |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 8c3b26a21574..776cbb80d098 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1411,8 +1411,12 @@ struct ieee80211_vht_operation { | |||
1411 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 | 1411 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 |
1412 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 | 1412 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
1413 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 | 1413 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
1414 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX 0x0000e000 | 1414 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 |
1415 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00070000 | 1415 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK \ |
1416 | (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) | ||
1417 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 | ||
1418 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \ | ||
1419 | (7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) | ||
1416 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 | 1420 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 |
1417 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 | 1421 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 |
1418 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 | 1422 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3eae46cb1acf..e9abc7b536cd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -91,9 +91,8 @@ enum ieee80211_band { | |||
91 | * Channel flags set by the regulatory control code. | 91 | * Channel flags set by the regulatory control code. |
92 | * | 92 | * |
93 | * @IEEE80211_CHAN_DISABLED: This channel is disabled. | 93 | * @IEEE80211_CHAN_DISABLED: This channel is disabled. |
94 | * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted | 94 | * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes |
95 | * on this channel. | 95 | * sending probe requests or beaconing. |
96 | * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. | ||
97 | * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. | 96 | * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. |
98 | * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel | 97 | * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel |
99 | * is not permitted. | 98 | * is not permitted. |
@@ -113,8 +112,8 @@ enum ieee80211_band { | |||
113 | */ | 112 | */ |
114 | enum ieee80211_channel_flags { | 113 | enum ieee80211_channel_flags { |
115 | IEEE80211_CHAN_DISABLED = 1<<0, | 114 | IEEE80211_CHAN_DISABLED = 1<<0, |
116 | IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, | 115 | IEEE80211_CHAN_NO_IR = 1<<1, |
117 | IEEE80211_CHAN_NO_IBSS = 1<<2, | 116 | /* hole at 1<<2 */ |
118 | IEEE80211_CHAN_RADAR = 1<<3, | 117 | IEEE80211_CHAN_RADAR = 1<<3, |
119 | IEEE80211_CHAN_NO_HT40PLUS = 1<<4, | 118 | IEEE80211_CHAN_NO_HT40PLUS = 1<<4, |
120 | IEEE80211_CHAN_NO_HT40MINUS = 1<<5, | 119 | IEEE80211_CHAN_NO_HT40MINUS = 1<<5, |
@@ -1945,6 +1944,29 @@ struct cfg80211_update_ft_ies_params { | |||
1945 | }; | 1944 | }; |
1946 | 1945 | ||
1947 | /** | 1946 | /** |
1947 | * struct cfg80211_mgmt_tx_params - mgmt tx parameters | ||
1948 | * | ||
1949 | * This structure provides information needed to transmit a mgmt frame | ||
1950 | * | ||
1951 | * @chan: channel to use | ||
1952 | * @offchan: indicates wether off channel operation is required | ||
1953 | * @wait: duration for ROC | ||
1954 | * @buf: buffer to transmit | ||
1955 | * @len: buffer length | ||
1956 | * @no_cck: don't use cck rates for this frame | ||
1957 | * @dont_wait_for_ack: tells the low level not to wait for an ack | ||
1958 | */ | ||
1959 | struct cfg80211_mgmt_tx_params { | ||
1960 | struct ieee80211_channel *chan; | ||
1961 | bool offchan; | ||
1962 | unsigned int wait; | ||
1963 | const u8 *buf; | ||
1964 | size_t len; | ||
1965 | bool no_cck; | ||
1966 | bool dont_wait_for_ack; | ||
1967 | }; | ||
1968 | |||
1969 | /** | ||
1948 | * struct cfg80211_ops - backend description for wireless configuration | 1970 | * struct cfg80211_ops - backend description for wireless configuration |
1949 | * | 1971 | * |
1950 | * This struct is registered by fullmac card drivers and/or wireless stacks | 1972 | * This struct is registered by fullmac card drivers and/or wireless stacks |
@@ -2342,9 +2364,8 @@ struct cfg80211_ops { | |||
2342 | u64 cookie); | 2364 | u64 cookie); |
2343 | 2365 | ||
2344 | int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, | 2366 | int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, |
2345 | struct ieee80211_channel *chan, bool offchan, | 2367 | struct cfg80211_mgmt_tx_params *params, |
2346 | unsigned int wait, const u8 *buf, size_t len, | 2368 | u64 *cookie); |
2347 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); | ||
2348 | int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, | 2369 | int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, |
2349 | struct wireless_dev *wdev, | 2370 | struct wireless_dev *wdev, |
2350 | u64 cookie); | 2371 | u64 cookie); |
@@ -2438,27 +2459,6 @@ struct cfg80211_ops { | |||
2438 | /** | 2459 | /** |
2439 | * enum wiphy_flags - wiphy capability flags | 2460 | * enum wiphy_flags - wiphy capability flags |
2440 | * | 2461 | * |
2441 | * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device | ||
2442 | * has its own custom regulatory domain and cannot identify the | ||
2443 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled | ||
2444 | * we will disregard the first regulatory hint (when the | ||
2445 | * initiator is %REGDOM_SET_BY_CORE). | ||
2446 | * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will | ||
2447 | * ignore regulatory domain settings until it gets its own regulatory | ||
2448 | * domain via its regulatory_hint() unless the regulatory hint is | ||
2449 | * from a country IE. After its gets its own regulatory domain it will | ||
2450 | * only allow further regulatory domain settings to further enhance | ||
2451 | * compliance. For example if channel 13 and 14 are disabled by this | ||
2452 | * regulatory domain no user regulatory domain can enable these channels | ||
2453 | * at a later time. This can be used for devices which do not have | ||
2454 | * calibration information guaranteed for frequencies or settings | ||
2455 | * outside of its regulatory domain. If used in combination with | ||
2456 | * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings | ||
2457 | * will be followed. | ||
2458 | * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure | ||
2459 | * that passive scan flags and beaconing flags may not be lifted by | ||
2460 | * cfg80211 due to regulatory beacon hints. For more information on beacon | ||
2461 | * hints read the documenation for regulatory_hint_found_beacon() | ||
2462 | * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this | 2462 | * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this |
2463 | * wiphy at all | 2463 | * wiphy at all |
2464 | * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled | 2464 | * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled |
@@ -2497,9 +2497,9 @@ struct cfg80211_ops { | |||
2497 | * beaconing mode (AP, IBSS, Mesh, ...). | 2497 | * beaconing mode (AP, IBSS, Mesh, ...). |
2498 | */ | 2498 | */ |
2499 | enum wiphy_flags { | 2499 | enum wiphy_flags { |
2500 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), | 2500 | /* use hole at 0 */ |
2501 | WIPHY_FLAG_STRICT_REGULATORY = BIT(1), | 2501 | /* use hole at 1 */ |
2502 | WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), | 2502 | /* use hole at 2 */ |
2503 | WIPHY_FLAG_NETNS_OK = BIT(3), | 2503 | WIPHY_FLAG_NETNS_OK = BIT(3), |
2504 | WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), | 2504 | WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), |
2505 | WIPHY_FLAG_4ADDR_AP = BIT(5), | 2505 | WIPHY_FLAG_4ADDR_AP = BIT(5), |
@@ -2721,6 +2721,8 @@ struct wiphy_coalesce_support { | |||
2721 | * @software_iftypes: bitmask of software interface types, these are not | 2721 | * @software_iftypes: bitmask of software interface types, these are not |
2722 | * subject to any restrictions since they are purely managed in SW. | 2722 | * subject to any restrictions since they are purely managed in SW. |
2723 | * @flags: wiphy flags, see &enum wiphy_flags | 2723 | * @flags: wiphy flags, see &enum wiphy_flags |
2724 | * @regulatory_flags: wiphy regulatory flags, see | ||
2725 | * &enum ieee80211_regulatory_flags | ||
2724 | * @features: features advertised to nl80211, see &enum nl80211_feature_flags. | 2726 | * @features: features advertised to nl80211, see &enum nl80211_feature_flags. |
2725 | * @bss_priv_size: each BSS struct has private data allocated with it, | 2727 | * @bss_priv_size: each BSS struct has private data allocated with it, |
2726 | * this variable determines its size | 2728 | * this variable determines its size |
@@ -2809,7 +2811,7 @@ struct wiphy { | |||
2809 | 2811 | ||
2810 | u16 max_acl_mac_addrs; | 2812 | u16 max_acl_mac_addrs; |
2811 | 2813 | ||
2812 | u32 flags, features; | 2814 | u32 flags, regulatory_flags, features; |
2813 | 2815 | ||
2814 | u32 ap_sme_capa; | 2816 | u32 ap_sme_capa; |
2815 | 2817 | ||
@@ -3472,6 +3474,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2); | |||
3472 | * custom regulatory domain will be trusted completely and as such previous | 3474 | * custom regulatory domain will be trusted completely and as such previous |
3473 | * default channel settings will be disregarded. If no rule is found for a | 3475 | * default channel settings will be disregarded. If no rule is found for a |
3474 | * channel on the regulatory domain the channel will be disabled. | 3476 | * channel on the regulatory domain the channel will be disabled. |
3477 | * Drivers using this for a wiphy should also set the wiphy flag | ||
3478 | * WIPHY_FLAG_CUSTOM_REGULATORY or cfg80211 will set it for the wiphy | ||
3479 | * that called this helper. | ||
3475 | */ | 3480 | */ |
3476 | void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | 3481 | void wiphy_apply_custom_regulatory(struct wiphy *wiphy, |
3477 | const struct ieee80211_regdomain *regd); | 3482 | const struct ieee80211_regdomain *regd); |
@@ -4146,6 +4151,7 @@ void cfg80211_radar_event(struct wiphy *wiphy, | |||
4146 | /** | 4151 | /** |
4147 | * cfg80211_cac_event - Channel availability check (CAC) event | 4152 | * cfg80211_cac_event - Channel availability check (CAC) event |
4148 | * @netdev: network device | 4153 | * @netdev: network device |
4154 | * @chandef: chandef for the current channel | ||
4149 | * @event: type of event | 4155 | * @event: type of event |
4150 | * @gfp: context flags | 4156 | * @gfp: context flags |
4151 | * | 4157 | * |
@@ -4154,6 +4160,7 @@ void cfg80211_radar_event(struct wiphy *wiphy, | |||
4154 | * also by full-MAC drivers. | 4160 | * also by full-MAC drivers. |
4155 | */ | 4161 | */ |
4156 | void cfg80211_cac_event(struct net_device *netdev, | 4162 | void cfg80211_cac_event(struct net_device *netdev, |
4163 | const struct cfg80211_chan_def *chandef, | ||
4157 | enum nl80211_radar_event event, gfp_t gfp); | 4164 | enum nl80211_radar_event event, gfp_t gfp); |
4158 | 4165 | ||
4159 | 4166 | ||
@@ -4279,7 +4286,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
4279 | * @dev: the device which switched channels | 4286 | * @dev: the device which switched channels |
4280 | * @chandef: the new channel definition | 4287 | * @chandef: the new channel definition |
4281 | * | 4288 | * |
4282 | * Acquires wdev_lock, so must only be called from sleepable driver context! | 4289 | * Caller must acquire wdev_lock, therefore must only be called from sleepable |
4290 | * driver context! | ||
4283 | */ | 4291 | */ |
4284 | void cfg80211_ch_switch_notify(struct net_device *dev, | 4292 | void cfg80211_ch_switch_notify(struct net_device *dev, |
4285 | struct cfg80211_chan_def *chandef); | 4293 | struct cfg80211_chan_def *chandef); |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7ceed99a05bc..3cd408b326de 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -154,12 +154,14 @@ struct ieee80211_low_level_stats { | |||
154 | * @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed | 154 | * @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed |
155 | * @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel, | 155 | * @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel, |
156 | * this is used only with channel switching with CSA | 156 | * this is used only with channel switching with CSA |
157 | * @IEEE80211_CHANCTX_CHANGE_MIN_WIDTH: The min required channel width changed | ||
157 | */ | 158 | */ |
158 | enum ieee80211_chanctx_change { | 159 | enum ieee80211_chanctx_change { |
159 | IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0), | 160 | IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0), |
160 | IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), | 161 | IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), |
161 | IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2), | 162 | IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2), |
162 | IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(3), | 163 | IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(3), |
164 | IEEE80211_CHANCTX_CHANGE_MIN_WIDTH = BIT(4), | ||
163 | }; | 165 | }; |
164 | 166 | ||
165 | /** | 167 | /** |
@@ -169,6 +171,7 @@ enum ieee80211_chanctx_change { | |||
169 | * that contains it is visible in mac80211 only. | 171 | * that contains it is visible in mac80211 only. |
170 | * | 172 | * |
171 | * @def: the channel definition | 173 | * @def: the channel definition |
174 | * @min_def: the minimum channel definition currently required. | ||
172 | * @rx_chains_static: The number of RX chains that must always be | 175 | * @rx_chains_static: The number of RX chains that must always be |
173 | * active on the channel to receive MIMO transmissions | 176 | * active on the channel to receive MIMO transmissions |
174 | * @rx_chains_dynamic: The number of RX chains that must be enabled | 177 | * @rx_chains_dynamic: The number of RX chains that must be enabled |
@@ -180,6 +183,7 @@ enum ieee80211_chanctx_change { | |||
180 | */ | 183 | */ |
181 | struct ieee80211_chanctx_conf { | 184 | struct ieee80211_chanctx_conf { |
182 | struct cfg80211_chan_def def; | 185 | struct cfg80211_chan_def def; |
186 | struct cfg80211_chan_def min_def; | ||
183 | 187 | ||
184 | u8 rx_chains_static, rx_chains_dynamic; | 188 | u8 rx_chains_static, rx_chains_dynamic; |
185 | 189 | ||
@@ -1229,6 +1233,36 @@ struct ieee80211_key_conf { | |||
1229 | }; | 1233 | }; |
1230 | 1234 | ||
1231 | /** | 1235 | /** |
1236 | * struct ieee80211_cipher_scheme - cipher scheme | ||
1237 | * | ||
1238 | * This structure contains a cipher scheme information defining | ||
1239 | * the secure packet crypto handling. | ||
1240 | * | ||
1241 | * @cipher: a cipher suite selector | ||
1242 | * @iftype: a cipher iftype bit mask indicating an allowed cipher usage | ||
1243 | * @hdr_len: a length of a security header used the cipher | ||
1244 | * @pn_len: a length of a packet number in the security header | ||
1245 | * @pn_off: an offset of pn from the beginning of the security header | ||
1246 | * @key_idx_off: an offset of key index byte in the security header | ||
1247 | * @key_idx_mask: a bit mask of key_idx bits | ||
1248 | * @key_idx_shift: a bit shift needed to get key_idx | ||
1249 | * key_idx value calculation: | ||
1250 | * (sec_header_base[key_idx_off] & key_idx_mask) >> key_idx_shift | ||
1251 | * @mic_len: a mic length in bytes | ||
1252 | */ | ||
1253 | struct ieee80211_cipher_scheme { | ||
1254 | u32 cipher; | ||
1255 | u16 iftype; | ||
1256 | u8 hdr_len; | ||
1257 | u8 pn_len; | ||
1258 | u8 pn_off; | ||
1259 | u8 key_idx_off; | ||
1260 | u8 key_idx_mask; | ||
1261 | u8 key_idx_shift; | ||
1262 | u8 mic_len; | ||
1263 | }; | ||
1264 | |||
1265 | /** | ||
1232 | * enum set_key_cmd - key command | 1266 | * enum set_key_cmd - key command |
1233 | * | 1267 | * |
1234 | * Used with the set_key() callback in &struct ieee80211_ops, this | 1268 | * Used with the set_key() callback in &struct ieee80211_ops, this |
@@ -1636,6 +1670,10 @@ enum ieee80211_hw_flags { | |||
1636 | * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may | 1670 | * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may |
1637 | * deliver to a WMM STA during any Service Period triggered by the WMM STA. | 1671 | * deliver to a WMM STA during any Service Period triggered by the WMM STA. |
1638 | * Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values. | 1672 | * Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values. |
1673 | * | ||
1674 | * @n_cipher_schemes: a size of an array of cipher schemes definitions. | ||
1675 | * @cipher_schemes: a pointer to an array of cipher scheme definitions | ||
1676 | * supported by HW. | ||
1639 | */ | 1677 | */ |
1640 | struct ieee80211_hw { | 1678 | struct ieee80211_hw { |
1641 | struct ieee80211_conf conf; | 1679 | struct ieee80211_conf conf; |
@@ -1663,6 +1701,8 @@ struct ieee80211_hw { | |||
1663 | netdev_features_t netdev_features; | 1701 | netdev_features_t netdev_features; |
1664 | u8 uapsd_queues; | 1702 | u8 uapsd_queues; |
1665 | u8 uapsd_max_sp_len; | 1703 | u8 uapsd_max_sp_len; |
1704 | u8 n_cipher_schemes; | ||
1705 | const struct ieee80211_cipher_scheme *cipher_schemes; | ||
1666 | }; | 1706 | }; |
1667 | 1707 | ||
1668 | /** | 1708 | /** |
diff --git a/include/net/regulatory.h b/include/net/regulatory.h index f17ed590d64a..c96a0b86f342 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h | |||
@@ -38,17 +38,17 @@ enum environment_cap { | |||
38 | * | 38 | * |
39 | * @rcu_head: RCU head struct used to free the request | 39 | * @rcu_head: RCU head struct used to free the request |
40 | * @wiphy_idx: this is set if this request's initiator is | 40 | * @wiphy_idx: this is set if this request's initiator is |
41 | * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This | 41 | * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This |
42 | * can be used by the wireless core to deal with conflicts | 42 | * can be used by the wireless core to deal with conflicts |
43 | * and potentially inform users of which devices specifically | 43 | * and potentially inform users of which devices specifically |
44 | * cased the conflicts. | 44 | * cased the conflicts. |
45 | * @initiator: indicates who sent this request, could be any of | 45 | * @initiator: indicates who sent this request, could be any of |
46 | * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) | 46 | * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) |
47 | * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested | 47 | * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested |
48 | * regulatory domain. We have a few special codes: | 48 | * regulatory domain. We have a few special codes: |
49 | * 00 - World regulatory domain | 49 | * 00 - World regulatory domain |
50 | * 99 - built by driver but a specific alpha2 cannot be determined | 50 | * 99 - built by driver but a specific alpha2 cannot be determined |
51 | * 98 - result of an intersection between two regulatory domains | 51 | * 98 - result of an intersection between two regulatory domains |
52 | * 97 - regulatory domain has not yet been configured | 52 | * 97 - regulatory domain has not yet been configured |
53 | * @dfs_region: If CRDA responded with a regulatory domain that requires | 53 | * @dfs_region: If CRDA responded with a regulatory domain that requires |
54 | * DFS master operation on a known DFS region (NL80211_DFS_*), | 54 | * DFS master operation on a known DFS region (NL80211_DFS_*), |
@@ -59,8 +59,8 @@ enum environment_cap { | |||
59 | * of hint passed. This could be any of the %NL80211_USER_REG_HINT_* | 59 | * of hint passed. This could be any of the %NL80211_USER_REG_HINT_* |
60 | * types. | 60 | * types. |
61 | * @intersect: indicates whether the wireless core should intersect | 61 | * @intersect: indicates whether the wireless core should intersect |
62 | * the requested regulatory domain with the presently set regulatory | 62 | * the requested regulatory domain with the presently set regulatory |
63 | * domain. | 63 | * domain. |
64 | * @processed: indicates whether or not this requests has already been | 64 | * @processed: indicates whether or not this requests has already been |
65 | * processed. When the last request is processed it means that the | 65 | * processed. When the last request is processed it means that the |
66 | * currently regulatory domain set on cfg80211 is updated from | 66 | * currently regulatory domain set on cfg80211 is updated from |
@@ -68,9 +68,9 @@ enum environment_cap { | |||
68 | * the last request is not yet processed we must yield until it | 68 | * the last request is not yet processed we must yield until it |
69 | * is processed before processing any new requests. | 69 | * is processed before processing any new requests. |
70 | * @country_ie_checksum: checksum of the last processed and accepted | 70 | * @country_ie_checksum: checksum of the last processed and accepted |
71 | * country IE | 71 | * country IE |
72 | * @country_ie_env: lets us know if the AP is telling us we are outdoor, | 72 | * @country_ie_env: lets us know if the AP is telling us we are outdoor, |
73 | * indoor, or if it doesn't matter | 73 | * indoor, or if it doesn't matter |
74 | * @list: used to insert into the reg_requests_list linked list | 74 | * @list: used to insert into the reg_requests_list linked list |
75 | */ | 75 | */ |
76 | struct regulatory_request { | 76 | struct regulatory_request { |
@@ -79,13 +79,63 @@ struct regulatory_request { | |||
79 | enum nl80211_reg_initiator initiator; | 79 | enum nl80211_reg_initiator initiator; |
80 | enum nl80211_user_reg_hint_type user_reg_hint_type; | 80 | enum nl80211_user_reg_hint_type user_reg_hint_type; |
81 | char alpha2[2]; | 81 | char alpha2[2]; |
82 | u8 dfs_region; | 82 | enum nl80211_dfs_regions dfs_region; |
83 | bool intersect; | 83 | bool intersect; |
84 | bool processed; | 84 | bool processed; |
85 | enum environment_cap country_ie_env; | 85 | enum environment_cap country_ie_env; |
86 | struct list_head list; | 86 | struct list_head list; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /** | ||
90 | * enum ieee80211_regulatory_flags - device regulatory flags | ||
91 | * | ||
92 | * @REGULATORY_CUSTOM_REG: tells us the driver for this device | ||
93 | * has its own custom regulatory domain and cannot identify the | ||
94 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled | ||
95 | * we will disregard the first regulatory hint (when the | ||
96 | * initiator is %REGDOM_SET_BY_CORE). Drivers that use | ||
97 | * wiphy_apply_custom_regulatory() should have this flag set | ||
98 | * or the regulatory core will set it for the wiphy. | ||
99 | * @REGULATORY_STRICT_REG: tells us that the wiphy for this device | ||
100 | * has regulatory domain that it wishes to be considered as the | ||
101 | * superset for regulatory rules. After this device gets its regulatory | ||
102 | * domain programmed further regulatory hints shall only be considered | ||
103 | * for this device to enhance regulatory compliance, forcing the | ||
104 | * device to only possibly use subsets of the original regulatory | ||
105 | * rules. For example if channel 13 and 14 are disabled by this | ||
106 | * device's regulatory domain no user specified regulatory hint which | ||
107 | * has these channels enabled would enable them for this wiphy, | ||
108 | * the device's original regulatory domain will be trusted as the | ||
109 | * base. You can program the superset of regulatory rules for this | ||
110 | * wiphy with regulatory_hint() for cards programmed with an | ||
111 | * ISO3166-alpha2 country code. wiphys that use regulatory_hint() | ||
112 | * will have their wiphy->regd programmed once the regulatory | ||
113 | * domain is set, and all other regulatory hints will be ignored | ||
114 | * until their own regulatory domain gets programmed. | ||
115 | * @REGULATORY_DISABLE_BEACON_HINTS: enable this if your driver needs to | ||
116 | * ensure that passive scan flags and beaconing flags may not be lifted by | ||
117 | * cfg80211 due to regulatory beacon hints. For more information on beacon | ||
118 | * hints read the documenation for regulatory_hint_found_beacon() | ||
119 | * @REGULATORY_COUNTRY_IE_FOLLOW_POWER: for devices that have a preference | ||
120 | * that even though they may have programmed their own custom power | ||
121 | * setting prior to wiphy registration, they want to ensure their channel | ||
122 | * power settings are updated for this connection with the power settings | ||
123 | * derived from the regulatory domain. The regulatory domain used will be | ||
124 | * based on the ISO3166-alpha2 from country IE provided through | ||
125 | * regulatory_hint_country_ie() | ||
126 | * @REGULATORY_COUNTRY_IE_IGNORE: for devices that have a preference to ignore | ||
127 | * all country IE information processed by the regulatory core. This will | ||
128 | * override %REGULATORY_COUNTRY_IE_FOLLOW_POWER as all country IEs will | ||
129 | * be ignored. | ||
130 | */ | ||
131 | enum ieee80211_regulatory_flags { | ||
132 | REGULATORY_CUSTOM_REG = BIT(0), | ||
133 | REGULATORY_STRICT_REG = BIT(1), | ||
134 | REGULATORY_DISABLE_BEACON_HINTS = BIT(2), | ||
135 | REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3), | ||
136 | REGULATORY_COUNTRY_IE_IGNORE = BIT(4), | ||
137 | }; | ||
138 | |||
89 | struct ieee80211_freq_range { | 139 | struct ieee80211_freq_range { |
90 | u32 start_freq_khz; | 140 | u32 start_freq_khz; |
91 | u32 end_freq_khz; | 141 | u32 end_freq_khz; |
@@ -107,7 +157,7 @@ struct ieee80211_regdomain { | |||
107 | struct rcu_head rcu_head; | 157 | struct rcu_head rcu_head; |
108 | u32 n_reg_rules; | 158 | u32 n_reg_rules; |
109 | char alpha2[2]; | 159 | char alpha2[2]; |
110 | u8 dfs_region; | 160 | enum nl80211_dfs_regions dfs_region; |
111 | struct ieee80211_reg_rule reg_rules[]; | 161 | struct ieee80211_reg_rule reg_rules[]; |
112 | }; | 162 | }; |
113 | 163 | ||
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f752e9821e71..129b7b087148 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -581,7 +581,14 @@ | |||
581 | * operation, %NL80211_ATTR_MAC contains the peer MAC address, and | 581 | * operation, %NL80211_ATTR_MAC contains the peer MAC address, and |
582 | * %NL80211_ATTR_REASON_CODE the reason code to be used (only with | 582 | * %NL80211_ATTR_REASON_CODE the reason code to be used (only with |
583 | * %NL80211_TDLS_TEARDOWN). | 583 | * %NL80211_TDLS_TEARDOWN). |
584 | * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. | 584 | * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The |
585 | * %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be | ||
586 | * sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as | ||
587 | * 802.11 management frames, while TDLS action codes (802.11-2012 | ||
588 | * 8.5.13.1) will be encapsulated and sent as data frames. The currently | ||
589 | * supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES | ||
590 | * and the currently supported TDLS actions codes are given in | ||
591 | * &enum ieee80211_tdls_actioncode. | ||
585 | * | 592 | * |
586 | * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP | 593 | * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP |
587 | * (or GO) interface (i.e. hostapd) to ask for unexpected frames to | 594 | * (or GO) interface (i.e. hostapd) to ask for unexpected frames to |
@@ -1508,6 +1515,11 @@ enum nl80211_commands { | |||
1508 | * to react to radar events, e.g. initiate a channel switch or leave the | 1515 | * to react to radar events, e.g. initiate a channel switch or leave the |
1509 | * IBSS network. | 1516 | * IBSS network. |
1510 | * | 1517 | * |
1518 | * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports | ||
1519 | * 5 MHz channel bandwidth. | ||
1520 | * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports | ||
1521 | * 10 MHz channel bandwidth. | ||
1522 | * | ||
1511 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1523 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1512 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1524 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1513 | */ | 1525 | */ |
@@ -1824,6 +1836,9 @@ enum nl80211_attrs { | |||
1824 | 1836 | ||
1825 | NL80211_ATTR_HANDLE_DFS, | 1837 | NL80211_ATTR_HANDLE_DFS, |
1826 | 1838 | ||
1839 | NL80211_ATTR_SUPPORT_5_MHZ, | ||
1840 | NL80211_ATTR_SUPPORT_10_MHZ, | ||
1841 | |||
1827 | /* add attributes here, update the policy in nl80211.c */ | 1842 | /* add attributes here, update the policy in nl80211.c */ |
1828 | 1843 | ||
1829 | __NL80211_ATTR_AFTER_LAST, | 1844 | __NL80211_ATTR_AFTER_LAST, |
@@ -2224,10 +2239,9 @@ enum nl80211_band_attr { | |||
2224 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz | 2239 | * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz |
2225 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current | 2240 | * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current |
2226 | * regulatory domain. | 2241 | * regulatory domain. |
2227 | * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is | 2242 | * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation |
2228 | * permitted on this channel in current regulatory domain. | 2243 | * are permitted on this channel, this includes sending probe |
2229 | * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted | 2244 | * requests, or modes of operation that require beaconing. |
2230 | * on this channel in current regulatory domain. | ||
2231 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory | 2245 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory |
2232 | * on this channel in current regulatory domain. | 2246 | * on this channel in current regulatory domain. |
2233 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm | 2247 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm |
@@ -2254,8 +2268,8 @@ enum nl80211_frequency_attr { | |||
2254 | __NL80211_FREQUENCY_ATTR_INVALID, | 2268 | __NL80211_FREQUENCY_ATTR_INVALID, |
2255 | NL80211_FREQUENCY_ATTR_FREQ, | 2269 | NL80211_FREQUENCY_ATTR_FREQ, |
2256 | NL80211_FREQUENCY_ATTR_DISABLED, | 2270 | NL80211_FREQUENCY_ATTR_DISABLED, |
2257 | NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, | 2271 | NL80211_FREQUENCY_ATTR_NO_IR, |
2258 | NL80211_FREQUENCY_ATTR_NO_IBSS, | 2272 | __NL80211_FREQUENCY_ATTR_NO_IBSS, |
2259 | NL80211_FREQUENCY_ATTR_RADAR, | 2273 | NL80211_FREQUENCY_ATTR_RADAR, |
2260 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 2274 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
2261 | NL80211_FREQUENCY_ATTR_DFS_STATE, | 2275 | NL80211_FREQUENCY_ATTR_DFS_STATE, |
@@ -2271,6 +2285,9 @@ enum nl80211_frequency_attr { | |||
2271 | }; | 2285 | }; |
2272 | 2286 | ||
2273 | #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER | 2287 | #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER |
2288 | #define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR | ||
2289 | #define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR | ||
2290 | #define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR | ||
2274 | 2291 | ||
2275 | /** | 2292 | /** |
2276 | * enum nl80211_bitrate_attr - bitrate attributes | 2293 | * enum nl80211_bitrate_attr - bitrate attributes |
@@ -2413,8 +2430,9 @@ enum nl80211_sched_scan_match_attr { | |||
2413 | * @NL80211_RRF_DFS: DFS support is required to be used | 2430 | * @NL80211_RRF_DFS: DFS support is required to be used |
2414 | * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links | 2431 | * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links |
2415 | * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links | 2432 | * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links |
2416 | * @NL80211_RRF_PASSIVE_SCAN: passive scan is required | 2433 | * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, |
2417 | * @NL80211_RRF_NO_IBSS: no IBSS is allowed | 2434 | * this includes probe requests or modes of operation that require |
2435 | * beaconing. | ||
2418 | */ | 2436 | */ |
2419 | enum nl80211_reg_rule_flags { | 2437 | enum nl80211_reg_rule_flags { |
2420 | NL80211_RRF_NO_OFDM = 1<<0, | 2438 | NL80211_RRF_NO_OFDM = 1<<0, |
@@ -2424,10 +2442,17 @@ enum nl80211_reg_rule_flags { | |||
2424 | NL80211_RRF_DFS = 1<<4, | 2442 | NL80211_RRF_DFS = 1<<4, |
2425 | NL80211_RRF_PTP_ONLY = 1<<5, | 2443 | NL80211_RRF_PTP_ONLY = 1<<5, |
2426 | NL80211_RRF_PTMP_ONLY = 1<<6, | 2444 | NL80211_RRF_PTMP_ONLY = 1<<6, |
2427 | NL80211_RRF_PASSIVE_SCAN = 1<<7, | 2445 | NL80211_RRF_NO_IR = 1<<7, |
2428 | NL80211_RRF_NO_IBSS = 1<<8, | 2446 | __NL80211_RRF_NO_IBSS = 1<<8, |
2429 | }; | 2447 | }; |
2430 | 2448 | ||
2449 | #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR | ||
2450 | #define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR | ||
2451 | #define NL80211_RRF_NO_IR NL80211_RRF_NO_IR | ||
2452 | |||
2453 | /* For backport compatibility with older userspace */ | ||
2454 | #define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) | ||
2455 | |||
2431 | /** | 2456 | /** |
2432 | * enum nl80211_dfs_regions - regulatory DFS regions | 2457 | * enum nl80211_dfs_regions - regulatory DFS regions |
2433 | * | 2458 | * |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 364ce0c5962f..f80e8c4c6bcd 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -133,7 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
133 | struct key_params *params) | 133 | struct key_params *params) |
134 | { | 134 | { |
135 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 135 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
136 | struct ieee80211_local *local = sdata->local; | ||
136 | struct sta_info *sta = NULL; | 137 | struct sta_info *sta = NULL; |
138 | const struct ieee80211_cipher_scheme *cs = NULL; | ||
137 | struct ieee80211_key *key; | 139 | struct ieee80211_key *key; |
138 | int err; | 140 | int err; |
139 | 141 | ||
@@ -145,22 +147,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
145 | case WLAN_CIPHER_SUITE_WEP40: | 147 | case WLAN_CIPHER_SUITE_WEP40: |
146 | case WLAN_CIPHER_SUITE_TKIP: | 148 | case WLAN_CIPHER_SUITE_TKIP: |
147 | case WLAN_CIPHER_SUITE_WEP104: | 149 | case WLAN_CIPHER_SUITE_WEP104: |
148 | if (IS_ERR(sdata->local->wep_tx_tfm)) | 150 | if (IS_ERR(local->wep_tx_tfm)) |
149 | return -EINVAL; | 151 | return -EINVAL; |
150 | break; | 152 | break; |
153 | case WLAN_CIPHER_SUITE_CCMP: | ||
154 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
155 | case WLAN_CIPHER_SUITE_GCMP: | ||
156 | break; | ||
151 | default: | 157 | default: |
158 | cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); | ||
152 | break; | 159 | break; |
153 | } | 160 | } |
154 | 161 | ||
155 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, | 162 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
156 | params->key, params->seq_len, params->seq); | 163 | params->key, params->seq_len, params->seq, |
164 | cs); | ||
157 | if (IS_ERR(key)) | 165 | if (IS_ERR(key)) |
158 | return PTR_ERR(key); | 166 | return PTR_ERR(key); |
159 | 167 | ||
160 | if (pairwise) | 168 | if (pairwise) |
161 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | 169 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
162 | 170 | ||
163 | mutex_lock(&sdata->local->sta_mtx); | 171 | mutex_lock(&local->sta_mtx); |
164 | 172 | ||
165 | if (mac_addr) { | 173 | if (mac_addr) { |
166 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 174 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -216,10 +224,13 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
216 | break; | 224 | break; |
217 | } | 225 | } |
218 | 226 | ||
227 | if (sta) | ||
228 | sta->cipher_scheme = cs; | ||
229 | |||
219 | err = ieee80211_key_link(key, sdata, sta); | 230 | err = ieee80211_key_link(key, sdata, sta); |
220 | 231 | ||
221 | out_unlock: | 232 | out_unlock: |
222 | mutex_unlock(&sdata->local->sta_mtx); | 233 | mutex_unlock(&local->sta_mtx); |
223 | 234 | ||
224 | return err; | 235 | return err; |
225 | } | 236 | } |
@@ -244,7 +255,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
244 | goto out_unlock; | 255 | goto out_unlock; |
245 | 256 | ||
246 | if (pairwise) | 257 | if (pairwise) |
247 | key = key_mtx_dereference(local, sta->ptk); | 258 | key = key_mtx_dereference(local, sta->ptk[key_idx]); |
248 | else | 259 | else |
249 | key = key_mtx_dereference(local, sta->gtk[key_idx]); | 260 | key = key_mtx_dereference(local, sta->gtk[key_idx]); |
250 | } else | 261 | } else |
@@ -291,7 +302,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
291 | goto out; | 302 | goto out; |
292 | 303 | ||
293 | if (pairwise) | 304 | if (pairwise) |
294 | key = rcu_dereference(sta->ptk); | 305 | key = rcu_dereference(sta->ptk[key_idx]); |
295 | else if (key_idx < NUM_DEFAULT_KEYS) | 306 | else if (key_idx < NUM_DEFAULT_KEYS) |
296 | key = rcu_dereference(sta->gtk[key_idx]); | 307 | key = rcu_dereference(sta->gtk[key_idx]); |
297 | } else | 308 | } else |
@@ -521,8 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
521 | STATION_INFO_PEER_PM | | 532 | STATION_INFO_PEER_PM | |
522 | STATION_INFO_NONPEER_PM; | 533 | STATION_INFO_NONPEER_PM; |
523 | 534 | ||
524 | sinfo->llid = le16_to_cpu(sta->llid); | 535 | sinfo->llid = sta->llid; |
525 | sinfo->plid = le16_to_cpu(sta->plid); | 536 | sinfo->plid = sta->plid; |
526 | sinfo->plink_state = sta->plink_state; | 537 | sinfo->plink_state = sta->plink_state; |
527 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 538 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
528 | sinfo->filled |= STATION_INFO_T_OFFSET; | 539 | sinfo->filled |= STATION_INFO_T_OFFSET; |
@@ -846,7 +857,7 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
846 | if (!resp || !resp_len) | 857 | if (!resp || !resp_len) |
847 | return 1; | 858 | return 1; |
848 | 859 | ||
849 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 860 | old = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
850 | 861 | ||
851 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); | 862 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
852 | if (!new) | 863 | if (!new) |
@@ -870,7 +881,8 @@ int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | |||
870 | int size, err; | 881 | int size, err; |
871 | u32 changed = BSS_CHANGED_BEACON; | 882 | u32 changed = BSS_CHANGED_BEACON; |
872 | 883 | ||
873 | old = rtnl_dereference(sdata->u.ap.beacon); | 884 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
885 | |||
874 | 886 | ||
875 | /* Need to have a beacon head if we don't have one yet */ | 887 | /* Need to have a beacon head if we don't have one yet */ |
876 | if (!params->head && !old) | 888 | if (!params->head && !old) |
@@ -947,7 +959,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
947 | BSS_CHANGED_P2P_PS; | 959 | BSS_CHANGED_P2P_PS; |
948 | int err; | 960 | int err; |
949 | 961 | ||
950 | old = rtnl_dereference(sdata->u.ap.beacon); | 962 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
951 | if (old) | 963 | if (old) |
952 | return -EALREADY; | 964 | return -EALREADY; |
953 | 965 | ||
@@ -968,11 +980,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
968 | */ | 980 | */ |
969 | sdata->control_port_protocol = params->crypto.control_port_ethertype; | 981 | sdata->control_port_protocol = params->crypto.control_port_ethertype; |
970 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; | 982 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; |
983 | sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, | ||
984 | ¶ms->crypto, | ||
985 | sdata->vif.type); | ||
986 | |||
971 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { | 987 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
972 | vlan->control_port_protocol = | 988 | vlan->control_port_protocol = |
973 | params->crypto.control_port_ethertype; | 989 | params->crypto.control_port_ethertype; |
974 | vlan->control_port_no_encrypt = | 990 | vlan->control_port_no_encrypt = |
975 | params->crypto.control_port_no_encrypt; | 991 | params->crypto.control_port_no_encrypt; |
992 | vlan->encrypt_headroom = | ||
993 | ieee80211_cs_headroom(sdata->local, | ||
994 | ¶ms->crypto, | ||
995 | vlan->vif.type); | ||
976 | } | 996 | } |
977 | 997 | ||
978 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 998 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
@@ -1001,7 +1021,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
1001 | 1021 | ||
1002 | err = drv_start_ap(sdata->local, sdata); | 1022 | err = drv_start_ap(sdata->local, sdata); |
1003 | if (err) { | 1023 | if (err) { |
1004 | old = rtnl_dereference(sdata->u.ap.beacon); | 1024 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
1025 | |||
1005 | if (old) | 1026 | if (old) |
1006 | kfree_rcu(old, rcu_head); | 1027 | kfree_rcu(old, rcu_head); |
1007 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 1028 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
@@ -1032,7 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1032 | if (sdata->vif.csa_active) | 1053 | if (sdata->vif.csa_active) |
1033 | return -EBUSY; | 1054 | return -EBUSY; |
1034 | 1055 | ||
1035 | old = rtnl_dereference(sdata->u.ap.beacon); | 1056 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
1036 | if (!old) | 1057 | if (!old) |
1037 | return -ENOENT; | 1058 | return -ENOENT; |
1038 | 1059 | ||
@@ -1050,15 +1071,18 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1050 | struct ieee80211_local *local = sdata->local; | 1071 | struct ieee80211_local *local = sdata->local; |
1051 | struct beacon_data *old_beacon; | 1072 | struct beacon_data *old_beacon; |
1052 | struct probe_resp *old_probe_resp; | 1073 | struct probe_resp *old_probe_resp; |
1074 | struct cfg80211_chan_def chandef; | ||
1053 | 1075 | ||
1054 | old_beacon = rtnl_dereference(sdata->u.ap.beacon); | 1076 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); |
1055 | if (!old_beacon) | 1077 | if (!old_beacon) |
1056 | return -ENOENT; | 1078 | return -ENOENT; |
1057 | old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp); | 1079 | old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
1058 | 1080 | ||
1059 | /* abort any running channel switch */ | 1081 | /* abort any running channel switch */ |
1060 | sdata->vif.csa_active = false; | 1082 | sdata->vif.csa_active = false; |
1061 | cancel_work_sync(&sdata->csa_finalize_work); | 1083 | kfree(sdata->u.ap.next_beacon); |
1084 | sdata->u.ap.next_beacon = NULL; | ||
1085 | |||
1062 | cancel_work_sync(&sdata->u.ap.request_smps_work); | 1086 | cancel_work_sync(&sdata->u.ap.request_smps_work); |
1063 | 1087 | ||
1064 | /* turn off carrier for this interface and dependent VLANs */ | 1088 | /* turn off carrier for this interface and dependent VLANs */ |
@@ -1091,8 +1115,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1091 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1115 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1092 | 1116 | ||
1093 | if (sdata->wdev.cac_started) { | 1117 | if (sdata->wdev.cac_started) { |
1118 | chandef = sdata->vif.bss_conf.chandef; | ||
1094 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 1119 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
1095 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, | 1120 | cfg80211_cac_event(sdata->dev, &chandef, |
1121 | NL80211_RADAR_CAC_ABORTED, | ||
1096 | GFP_KERNEL); | 1122 | GFP_KERNEL); |
1097 | } | 1123 | } |
1098 | 1124 | ||
@@ -1953,7 +1979,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1953 | enum ieee80211_band band; | 1979 | enum ieee80211_band band; |
1954 | u32 changed = 0; | 1980 | u32 changed = 0; |
1955 | 1981 | ||
1956 | if (!rtnl_dereference(sdata->u.ap.beacon)) | 1982 | if (!sdata_dereference(sdata->u.ap.beacon, sdata)) |
1957 | return -ENOENT; | 1983 | return -ENOENT; |
1958 | 1984 | ||
1959 | band = ieee80211_get_sdata_band(sdata); | 1985 | band = ieee80211_get_sdata_band(sdata); |
@@ -2963,27 +2989,33 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2963 | struct ieee80211_local *local = sdata->local; | 2989 | struct ieee80211_local *local = sdata->local; |
2964 | int err, changed = 0; | 2990 | int err, changed = 0; |
2965 | 2991 | ||
2992 | sdata_lock(sdata); | ||
2993 | /* AP might have been stopped while waiting for the lock. */ | ||
2994 | if (!sdata->vif.csa_active) | ||
2995 | goto unlock; | ||
2996 | |||
2966 | if (!ieee80211_sdata_running(sdata)) | 2997 | if (!ieee80211_sdata_running(sdata)) |
2967 | return; | 2998 | goto unlock; |
2968 | 2999 | ||
2969 | sdata->radar_required = sdata->csa_radar_required; | 3000 | sdata->radar_required = sdata->csa_radar_required; |
2970 | err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, | 3001 | err = ieee80211_vif_change_channel(sdata, &changed); |
2971 | &changed); | ||
2972 | if (WARN_ON(err < 0)) | 3002 | if (WARN_ON(err < 0)) |
2973 | return; | 3003 | goto unlock; |
2974 | 3004 | ||
2975 | if (!local->use_chanctx) { | 3005 | if (!local->use_chanctx) { |
2976 | local->_oper_chandef = local->csa_chandef; | 3006 | local->_oper_chandef = sdata->csa_chandef; |
2977 | ieee80211_hw_config(local, 0); | 3007 | ieee80211_hw_config(local, 0); |
2978 | } | 3008 | } |
2979 | 3009 | ||
2980 | ieee80211_bss_info_change_notify(sdata, changed); | 3010 | ieee80211_bss_info_change_notify(sdata, changed); |
2981 | 3011 | ||
3012 | sdata->vif.csa_active = false; | ||
2982 | switch (sdata->vif.type) { | 3013 | switch (sdata->vif.type) { |
2983 | case NL80211_IFTYPE_AP: | 3014 | case NL80211_IFTYPE_AP: |
2984 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3015 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
2985 | if (err < 0) | 3016 | if (err < 0) |
2986 | return; | 3017 | goto unlock; |
3018 | |||
2987 | changed |= err; | 3019 | changed |= err; |
2988 | kfree(sdata->u.ap.next_beacon); | 3020 | kfree(sdata->u.ap.next_beacon); |
2989 | sdata->u.ap.next_beacon = NULL; | 3021 | sdata->u.ap.next_beacon = NULL; |
@@ -2997,20 +3029,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2997 | case NL80211_IFTYPE_MESH_POINT: | 3029 | case NL80211_IFTYPE_MESH_POINT: |
2998 | err = ieee80211_mesh_finish_csa(sdata); | 3030 | err = ieee80211_mesh_finish_csa(sdata); |
2999 | if (err < 0) | 3031 | if (err < 0) |
3000 | return; | 3032 | goto unlock; |
3001 | break; | 3033 | break; |
3002 | #endif | 3034 | #endif |
3003 | default: | 3035 | default: |
3004 | WARN_ON(1); | 3036 | WARN_ON(1); |
3005 | return; | 3037 | goto unlock; |
3006 | } | 3038 | } |
3007 | sdata->vif.csa_active = false; | ||
3008 | 3039 | ||
3009 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3040 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
3010 | IEEE80211_MAX_QUEUE_MAP, | 3041 | IEEE80211_MAX_QUEUE_MAP, |
3011 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3042 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3012 | 3043 | ||
3013 | cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); | 3044 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3045 | |||
3046 | unlock: | ||
3047 | sdata_unlock(sdata); | ||
3014 | } | 3048 | } |
3015 | 3049 | ||
3016 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3050 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
@@ -3023,6 +3057,8 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3023 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | 3057 | struct ieee80211_if_mesh __maybe_unused *ifmsh; |
3024 | int err, num_chanctx; | 3058 | int err, num_chanctx; |
3025 | 3059 | ||
3060 | lockdep_assert_held(&sdata->wdev.mtx); | ||
3061 | |||
3026 | if (!list_empty(&local->roc_list) || local->scanning) | 3062 | if (!list_empty(&local->roc_list) || local->scanning) |
3027 | return -EBUSY; | 3063 | return -EBUSY; |
3028 | 3064 | ||
@@ -3143,7 +3179,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3143 | IEEE80211_MAX_QUEUE_MAP, | 3179 | IEEE80211_MAX_QUEUE_MAP, |
3144 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3180 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3145 | 3181 | ||
3146 | local->csa_chandef = params->chandef; | 3182 | sdata->csa_chandef = params->chandef; |
3147 | sdata->vif.csa_active = true; | 3183 | sdata->vif.csa_active = true; |
3148 | 3184 | ||
3149 | ieee80211_bss_info_change_notify(sdata, err); | 3185 | ieee80211_bss_info_change_notify(sdata, err); |
@@ -3153,26 +3189,25 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3153 | } | 3189 | } |
3154 | 3190 | ||
3155 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 3191 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
3156 | struct ieee80211_channel *chan, bool offchan, | 3192 | struct cfg80211_mgmt_tx_params *params, |
3157 | unsigned int wait, const u8 *buf, size_t len, | 3193 | u64 *cookie) |
3158 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
3159 | { | 3194 | { |
3160 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3195 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3161 | struct ieee80211_local *local = sdata->local; | 3196 | struct ieee80211_local *local = sdata->local; |
3162 | struct sk_buff *skb; | 3197 | struct sk_buff *skb; |
3163 | struct sta_info *sta; | 3198 | struct sta_info *sta; |
3164 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 3199 | const struct ieee80211_mgmt *mgmt = (void *)params->buf; |
3165 | bool need_offchan = false; | 3200 | bool need_offchan = false; |
3166 | u32 flags; | 3201 | u32 flags; |
3167 | int ret; | 3202 | int ret; |
3168 | 3203 | ||
3169 | if (dont_wait_for_ack) | 3204 | if (params->dont_wait_for_ack) |
3170 | flags = IEEE80211_TX_CTL_NO_ACK; | 3205 | flags = IEEE80211_TX_CTL_NO_ACK; |
3171 | else | 3206 | else |
3172 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 3207 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
3173 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 3208 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
3174 | 3209 | ||
3175 | if (no_cck) | 3210 | if (params->no_cck) |
3176 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 3211 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
3177 | 3212 | ||
3178 | switch (sdata->vif.type) { | 3213 | switch (sdata->vif.type) { |
@@ -3220,7 +3255,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3220 | /* configurations requiring offchan cannot work if no channel has been | 3255 | /* configurations requiring offchan cannot work if no channel has been |
3221 | * specified | 3256 | * specified |
3222 | */ | 3257 | */ |
3223 | if (need_offchan && !chan) | 3258 | if (need_offchan && !params->chan) |
3224 | return -EINVAL; | 3259 | return -EINVAL; |
3225 | 3260 | ||
3226 | mutex_lock(&local->mtx); | 3261 | mutex_lock(&local->mtx); |
@@ -3233,8 +3268,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3233 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3268 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3234 | 3269 | ||
3235 | if (chanctx_conf) { | 3270 | if (chanctx_conf) { |
3236 | need_offchan = chan && (chan != chanctx_conf->def.chan); | 3271 | need_offchan = params->chan && |
3237 | } else if (!chan) { | 3272 | (params->chan != |
3273 | chanctx_conf->def.chan); | ||
3274 | } else if (!params->chan) { | ||
3238 | ret = -EINVAL; | 3275 | ret = -EINVAL; |
3239 | rcu_read_unlock(); | 3276 | rcu_read_unlock(); |
3240 | goto out_unlock; | 3277 | goto out_unlock; |
@@ -3244,19 +3281,19 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3244 | rcu_read_unlock(); | 3281 | rcu_read_unlock(); |
3245 | } | 3282 | } |
3246 | 3283 | ||
3247 | if (need_offchan && !offchan) { | 3284 | if (need_offchan && !params->offchan) { |
3248 | ret = -EBUSY; | 3285 | ret = -EBUSY; |
3249 | goto out_unlock; | 3286 | goto out_unlock; |
3250 | } | 3287 | } |
3251 | 3288 | ||
3252 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 3289 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len); |
3253 | if (!skb) { | 3290 | if (!skb) { |
3254 | ret = -ENOMEM; | 3291 | ret = -ENOMEM; |
3255 | goto out_unlock; | 3292 | goto out_unlock; |
3256 | } | 3293 | } |
3257 | skb_reserve(skb, local->hw.extra_tx_headroom); | 3294 | skb_reserve(skb, local->hw.extra_tx_headroom); |
3258 | 3295 | ||
3259 | memcpy(skb_put(skb, len), buf, len); | 3296 | memcpy(skb_put(skb, params->len), params->buf, params->len); |
3260 | 3297 | ||
3261 | IEEE80211_SKB_CB(skb)->flags = flags; | 3298 | IEEE80211_SKB_CB(skb)->flags = flags; |
3262 | 3299 | ||
@@ -3276,8 +3313,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3276 | local->hw.offchannel_tx_hw_queue; | 3313 | local->hw.offchannel_tx_hw_queue; |
3277 | 3314 | ||
3278 | /* This will handle all kinds of coalescing and immediate TX */ | 3315 | /* This will handle all kinds of coalescing and immediate TX */ |
3279 | ret = ieee80211_start_roc_work(local, sdata, chan, | 3316 | ret = ieee80211_start_roc_work(local, sdata, params->chan, |
3280 | wait, cookie, skb, | 3317 | params->wait, cookie, skb, |
3281 | IEEE80211_ROC_TYPE_MGMT_TX); | 3318 | IEEE80211_ROC_TYPE_MGMT_TX); |
3282 | if (ret) | 3319 | if (ret) |
3283 | kfree_skb(skb); | 3320 | kfree_skb(skb); |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 03ba6b5c5373..a57d5d9466bc 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -9,6 +9,140 @@ | |||
9 | #include "ieee80211_i.h" | 9 | #include "ieee80211_i.h" |
10 | #include "driver-ops.h" | 10 | #include "driver-ops.h" |
11 | 11 | ||
12 | static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta) | ||
13 | { | ||
14 | switch (sta->bandwidth) { | ||
15 | case IEEE80211_STA_RX_BW_20: | ||
16 | if (sta->ht_cap.ht_supported) | ||
17 | return NL80211_CHAN_WIDTH_20; | ||
18 | else | ||
19 | return NL80211_CHAN_WIDTH_20_NOHT; | ||
20 | case IEEE80211_STA_RX_BW_40: | ||
21 | return NL80211_CHAN_WIDTH_40; | ||
22 | case IEEE80211_STA_RX_BW_80: | ||
23 | return NL80211_CHAN_WIDTH_80; | ||
24 | case IEEE80211_STA_RX_BW_160: | ||
25 | /* | ||
26 | * This applied for both 160 and 80+80. since we use | ||
27 | * the returned value to consider degradation of | ||
28 | * ctx->conf.min_def, we have to make sure to take | ||
29 | * the bigger one (NL80211_CHAN_WIDTH_160). | ||
30 | * Otherwise we might try degrading even when not | ||
31 | * needed, as the max required sta_bw returned (80+80) | ||
32 | * might be smaller than the configured bw (160). | ||
33 | */ | ||
34 | return NL80211_CHAN_WIDTH_160; | ||
35 | default: | ||
36 | WARN_ON(1); | ||
37 | return NL80211_CHAN_WIDTH_20; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static enum nl80211_chan_width | ||
42 | ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata) | ||
43 | { | ||
44 | enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; | ||
45 | struct sta_info *sta; | ||
46 | |||
47 | rcu_read_lock(); | ||
48 | list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { | ||
49 | if (sdata != sta->sdata && | ||
50 | !(sta->sdata->bss && sta->sdata->bss == sdata->bss)) | ||
51 | continue; | ||
52 | |||
53 | if (!sta->uploaded) | ||
54 | continue; | ||
55 | |||
56 | max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta)); | ||
57 | } | ||
58 | rcu_read_unlock(); | ||
59 | |||
60 | return max_bw; | ||
61 | } | ||
62 | |||
63 | static enum nl80211_chan_width | ||
64 | ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, | ||
65 | struct ieee80211_chanctx_conf *conf) | ||
66 | { | ||
67 | struct ieee80211_sub_if_data *sdata; | ||
68 | enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; | ||
69 | |||
70 | rcu_read_lock(); | ||
71 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
72 | struct ieee80211_vif *vif = &sdata->vif; | ||
73 | enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT; | ||
74 | |||
75 | if (!ieee80211_sdata_running(sdata)) | ||
76 | continue; | ||
77 | |||
78 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) | ||
79 | continue; | ||
80 | |||
81 | switch (vif->type) { | ||
82 | case NL80211_IFTYPE_AP: | ||
83 | case NL80211_IFTYPE_AP_VLAN: | ||
84 | width = ieee80211_get_max_required_bw(sdata); | ||
85 | break; | ||
86 | case NL80211_IFTYPE_P2P_DEVICE: | ||
87 | continue; | ||
88 | case NL80211_IFTYPE_STATION: | ||
89 | case NL80211_IFTYPE_ADHOC: | ||
90 | case NL80211_IFTYPE_WDS: | ||
91 | case NL80211_IFTYPE_MESH_POINT: | ||
92 | width = vif->bss_conf.chandef.width; | ||
93 | break; | ||
94 | case NL80211_IFTYPE_UNSPECIFIED: | ||
95 | case NUM_NL80211_IFTYPES: | ||
96 | case NL80211_IFTYPE_MONITOR: | ||
97 | case NL80211_IFTYPE_P2P_CLIENT: | ||
98 | case NL80211_IFTYPE_P2P_GO: | ||
99 | WARN_ON_ONCE(1); | ||
100 | } | ||
101 | max_bw = max(max_bw, width); | ||
102 | } | ||
103 | rcu_read_unlock(); | ||
104 | |||
105 | return max_bw; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * recalc the min required chan width of the channel context, which is | ||
110 | * the max of min required widths of all the interfaces bound to this | ||
111 | * channel context. | ||
112 | */ | ||
113 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, | ||
114 | struct ieee80211_chanctx *ctx) | ||
115 | { | ||
116 | enum nl80211_chan_width max_bw; | ||
117 | struct cfg80211_chan_def min_def; | ||
118 | |||
119 | lockdep_assert_held(&local->chanctx_mtx); | ||
120 | |||
121 | /* don't optimize 5MHz, 10MHz, and radar_enabled confs */ | ||
122 | if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 || | ||
123 | ctx->conf.def.width == NL80211_CHAN_WIDTH_10 || | ||
124 | ctx->conf.radar_enabled) { | ||
125 | ctx->conf.min_def = ctx->conf.def; | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf); | ||
130 | |||
131 | /* downgrade chandef up to max_bw */ | ||
132 | min_def = ctx->conf.def; | ||
133 | while (min_def.width > max_bw) | ||
134 | ieee80211_chandef_downgrade(&min_def); | ||
135 | |||
136 | if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def)) | ||
137 | return; | ||
138 | |||
139 | ctx->conf.min_def = min_def; | ||
140 | if (!ctx->driver_present) | ||
141 | return; | ||
142 | |||
143 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH); | ||
144 | } | ||
145 | |||
12 | static void ieee80211_change_chanctx(struct ieee80211_local *local, | 146 | static void ieee80211_change_chanctx(struct ieee80211_local *local, |
13 | struct ieee80211_chanctx *ctx, | 147 | struct ieee80211_chanctx *ctx, |
14 | const struct cfg80211_chan_def *chandef) | 148 | const struct cfg80211_chan_def *chandef) |
@@ -20,6 +154,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, | |||
20 | 154 | ||
21 | ctx->conf.def = *chandef; | 155 | ctx->conf.def = *chandef; |
22 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); | 156 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); |
157 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
23 | 158 | ||
24 | if (!local->use_chanctx) { | 159 | if (!local->use_chanctx) { |
25 | local->_oper_chandef = *chandef; | 160 | local->_oper_chandef = *chandef; |
@@ -93,6 +228,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
93 | ctx->conf.rx_chains_dynamic = 1; | 228 | ctx->conf.rx_chains_dynamic = 1; |
94 | ctx->mode = mode; | 229 | ctx->mode = mode; |
95 | ctx->conf.radar_enabled = ieee80211_is_radar_required(local); | 230 | ctx->conf.radar_enabled = ieee80211_is_radar_required(local); |
231 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
96 | if (!local->use_chanctx) | 232 | if (!local->use_chanctx) |
97 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | 233 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; |
98 | 234 | ||
@@ -179,6 +315,7 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
179 | ctx->refcount++; | 315 | ctx->refcount++; |
180 | 316 | ||
181 | ieee80211_recalc_txpower(sdata); | 317 | ieee80211_recalc_txpower(sdata); |
318 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
182 | sdata->vif.bss_conf.idle = false; | 319 | sdata->vif.bss_conf.idle = false; |
183 | 320 | ||
184 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && | 321 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && |
@@ -243,6 +380,7 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
243 | ieee80211_recalc_chanctx_chantype(sdata->local, ctx); | 380 | ieee80211_recalc_chanctx_chantype(sdata->local, ctx); |
244 | ieee80211_recalc_smps_chanctx(local, ctx); | 381 | ieee80211_recalc_smps_chanctx(local, ctx); |
245 | ieee80211_recalc_radar_chanctx(local, ctx); | 382 | ieee80211_recalc_radar_chanctx(local, ctx); |
383 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
246 | } | 384 | } |
247 | } | 385 | } |
248 | 386 | ||
@@ -411,12 +549,12 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
411 | } | 549 | } |
412 | 550 | ||
413 | int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | 551 | int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, |
414 | const struct cfg80211_chan_def *chandef, | ||
415 | u32 *changed) | 552 | u32 *changed) |
416 | { | 553 | { |
417 | struct ieee80211_local *local = sdata->local; | 554 | struct ieee80211_local *local = sdata->local; |
418 | struct ieee80211_chanctx_conf *conf; | 555 | struct ieee80211_chanctx_conf *conf; |
419 | struct ieee80211_chanctx *ctx; | 556 | struct ieee80211_chanctx *ctx; |
557 | const struct cfg80211_chan_def *chandef = &sdata->csa_chandef; | ||
420 | int ret; | 558 | int ret; |
421 | u32 chanctx_changed = 0; | 559 | u32 chanctx_changed = 0; |
422 | 560 | ||
@@ -456,6 +594,7 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | |||
456 | ieee80211_recalc_chanctx_chantype(local, ctx); | 594 | ieee80211_recalc_chanctx_chantype(local, ctx); |
457 | ieee80211_recalc_smps_chanctx(local, ctx); | 595 | ieee80211_recalc_smps_chanctx(local, ctx); |
458 | ieee80211_recalc_radar_chanctx(local, ctx); | 596 | ieee80211_recalc_radar_chanctx(local, ctx); |
597 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
459 | 598 | ||
460 | ret = 0; | 599 | ret = 0; |
461 | out: | 600 | out: |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 5c090e41d9bb..fa16e54980a1 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -17,6 +17,172 @@ | |||
17 | 17 | ||
18 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 | 18 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 |
19 | 19 | ||
20 | #define TX_LATENCY_BIN_DELIMTER_C ',' | ||
21 | #define TX_LATENCY_BIN_DELIMTER_S "," | ||
22 | #define TX_LATENCY_BINS_DISABLED "enable(bins disabled)\n" | ||
23 | #define TX_LATENCY_DISABLED "disable\n" | ||
24 | |||
25 | |||
26 | /* | ||
27 | * Display if Tx latency statistics & bins are enabled/disabled | ||
28 | */ | ||
29 | static ssize_t sta_tx_latency_stat_read(struct file *file, | ||
30 | char __user *userbuf, | ||
31 | size_t count, loff_t *ppos) | ||
32 | { | ||
33 | struct ieee80211_local *local = file->private_data; | ||
34 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
35 | char *buf; | ||
36 | int bufsz, i, ret; | ||
37 | int pos = 0; | ||
38 | |||
39 | rcu_read_lock(); | ||
40 | |||
41 | tx_latency = rcu_dereference(local->tx_latency); | ||
42 | |||
43 | if (tx_latency && tx_latency->n_ranges) { | ||
44 | bufsz = tx_latency->n_ranges * 15; | ||
45 | buf = kzalloc(bufsz, GFP_ATOMIC); | ||
46 | if (!buf) | ||
47 | goto err; | ||
48 | |||
49 | for (i = 0; i < tx_latency->n_ranges; i++) | ||
50 | pos += scnprintf(buf + pos, bufsz - pos, "%d,", | ||
51 | tx_latency->ranges[i]); | ||
52 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
53 | } else if (tx_latency) { | ||
54 | bufsz = sizeof(TX_LATENCY_BINS_DISABLED) + 1; | ||
55 | buf = kzalloc(bufsz, GFP_ATOMIC); | ||
56 | if (!buf) | ||
57 | goto err; | ||
58 | |||
59 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | ||
60 | TX_LATENCY_BINS_DISABLED); | ||
61 | } else { | ||
62 | bufsz = sizeof(TX_LATENCY_DISABLED) + 1; | ||
63 | buf = kzalloc(bufsz, GFP_ATOMIC); | ||
64 | if (!buf) | ||
65 | goto err; | ||
66 | |||
67 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | ||
68 | TX_LATENCY_DISABLED); | ||
69 | } | ||
70 | |||
71 | rcu_read_unlock(); | ||
72 | |||
73 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | ||
74 | kfree(buf); | ||
75 | |||
76 | return ret; | ||
77 | err: | ||
78 | rcu_read_unlock(); | ||
79 | return -ENOMEM; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Receive input from user regarding Tx latency statistics | ||
84 | * The input should indicate if Tx latency statistics and bins are | ||
85 | * enabled/disabled. | ||
86 | * If bins are enabled input should indicate the amount of different bins and | ||
87 | * their ranges. Each bin will count how many Tx frames transmitted within the | ||
88 | * appropriate latency. | ||
89 | * Legal input is: | ||
90 | * a) "enable(bins disabled)" - to enable only general statistics | ||
91 | * b) "a,b,c,d,...z" - to enable general statistics and bins, where all are | ||
92 | * numbers and a < b < c < d.. < z | ||
93 | * c) "disable" - disable all statistics | ||
94 | * NOTE: must configure Tx latency statistics bins before stations connected. | ||
95 | */ | ||
96 | |||
97 | static ssize_t sta_tx_latency_stat_write(struct file *file, | ||
98 | const char __user *userbuf, | ||
99 | size_t count, loff_t *ppos) | ||
100 | { | ||
101 | struct ieee80211_local *local = file->private_data; | ||
102 | char buf[128] = {}; | ||
103 | char *bins = buf; | ||
104 | char *token; | ||
105 | int buf_size, i, alloc_size; | ||
106 | int prev_bin = 0; | ||
107 | int n_ranges = 0; | ||
108 | int ret = count; | ||
109 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
110 | |||
111 | if (sizeof(buf) <= count) | ||
112 | return -EINVAL; | ||
113 | buf_size = count; | ||
114 | if (copy_from_user(buf, userbuf, buf_size)) | ||
115 | return -EFAULT; | ||
116 | |||
117 | mutex_lock(&local->sta_mtx); | ||
118 | |||
119 | /* cannot change config once we have stations */ | ||
120 | if (local->num_sta) | ||
121 | goto unlock; | ||
122 | |||
123 | tx_latency = | ||
124 | rcu_dereference_protected(local->tx_latency, | ||
125 | lockdep_is_held(&local->sta_mtx)); | ||
126 | |||
127 | /* disable Tx statistics */ | ||
128 | if (!strcmp(buf, TX_LATENCY_DISABLED)) { | ||
129 | if (!tx_latency) | ||
130 | goto unlock; | ||
131 | rcu_assign_pointer(local->tx_latency, NULL); | ||
132 | synchronize_rcu(); | ||
133 | kfree(tx_latency); | ||
134 | goto unlock; | ||
135 | } | ||
136 | |||
137 | /* Tx latency already enabled */ | ||
138 | if (tx_latency) | ||
139 | goto unlock; | ||
140 | |||
141 | if (strcmp(TX_LATENCY_BINS_DISABLED, buf)) { | ||
142 | /* check how many bins and between what ranges user requested */ | ||
143 | token = buf; | ||
144 | while (*token != '\0') { | ||
145 | if (*token == TX_LATENCY_BIN_DELIMTER_C) | ||
146 | n_ranges++; | ||
147 | token++; | ||
148 | } | ||
149 | n_ranges++; | ||
150 | } | ||
151 | |||
152 | alloc_size = sizeof(struct ieee80211_tx_latency_bin_ranges) + | ||
153 | n_ranges * sizeof(u32); | ||
154 | tx_latency = kzalloc(alloc_size, GFP_ATOMIC); | ||
155 | if (!tx_latency) { | ||
156 | ret = -ENOMEM; | ||
157 | goto unlock; | ||
158 | } | ||
159 | tx_latency->n_ranges = n_ranges; | ||
160 | for (i = 0; i < n_ranges; i++) { /* setting bin ranges */ | ||
161 | token = strsep(&bins, TX_LATENCY_BIN_DELIMTER_S); | ||
162 | sscanf(token, "%d", &tx_latency->ranges[i]); | ||
163 | /* bins values should be in ascending order */ | ||
164 | if (prev_bin >= tx_latency->ranges[i]) { | ||
165 | ret = -EINVAL; | ||
166 | kfree(tx_latency); | ||
167 | goto unlock; | ||
168 | } | ||
169 | prev_bin = tx_latency->ranges[i]; | ||
170 | } | ||
171 | rcu_assign_pointer(local->tx_latency, tx_latency); | ||
172 | |||
173 | unlock: | ||
174 | mutex_unlock(&local->sta_mtx); | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static const struct file_operations stats_tx_latency_ops = { | ||
180 | .write = sta_tx_latency_stat_write, | ||
181 | .read = sta_tx_latency_stat_read, | ||
182 | .open = simple_open, | ||
183 | .llseek = generic_file_llseek, | ||
184 | }; | ||
185 | |||
20 | int mac80211_format_buffer(char __user *userbuf, size_t count, | 186 | int mac80211_format_buffer(char __user *userbuf, size_t count, |
21 | loff_t *ppos, char *fmt, ...) | 187 | loff_t *ppos, char *fmt, ...) |
22 | { | 188 | { |
@@ -315,4 +481,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
315 | DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); | 481 | DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); |
316 | DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount); | 482 | DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount); |
317 | DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount); | 483 | DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount); |
484 | |||
485 | DEBUGFS_DEVSTATS_ADD(tx_latency); | ||
318 | } | 486 | } |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 19c54a44ed47..80194b557a0c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -38,6 +38,13 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
38 | .llseek = generic_file_llseek, \ | 38 | .llseek = generic_file_llseek, \ |
39 | } | 39 | } |
40 | 40 | ||
41 | #define STA_OPS_W(name) \ | ||
42 | static const struct file_operations sta_ ##name## _ops = { \ | ||
43 | .write = sta_##name##_write, \ | ||
44 | .open = simple_open, \ | ||
45 | .llseek = generic_file_llseek, \ | ||
46 | } | ||
47 | |||
41 | #define STA_OPS_RW(name) \ | 48 | #define STA_OPS_RW(name) \ |
42 | static const struct file_operations sta_ ##name## _ops = { \ | 49 | static const struct file_operations sta_ ##name## _ops = { \ |
43 | .read = sta_##name##_read, \ | 50 | .read = sta_##name##_read, \ |
@@ -388,6 +395,131 @@ static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf, | |||
388 | } | 395 | } |
389 | STA_OPS(last_rx_rate); | 396 | STA_OPS(last_rx_rate); |
390 | 397 | ||
398 | static int | ||
399 | sta_tx_latency_stat_header(struct ieee80211_tx_latency_bin_ranges *tx_latency, | ||
400 | char *buf, int pos, int bufsz) | ||
401 | { | ||
402 | int i; | ||
403 | int range_count = tx_latency->n_ranges; | ||
404 | u32 *bin_ranges = tx_latency->ranges; | ||
405 | |||
406 | pos += scnprintf(buf + pos, bufsz - pos, | ||
407 | "Station\t\t\tTID\tMax\tAvg"); | ||
408 | if (range_count) { | ||
409 | pos += scnprintf(buf + pos, bufsz - pos, | ||
410 | "\t<=%d", bin_ranges[0]); | ||
411 | for (i = 0; i < range_count - 1; i++) | ||
412 | pos += scnprintf(buf + pos, bufsz - pos, "\t%d-%d", | ||
413 | bin_ranges[i], bin_ranges[i+1]); | ||
414 | pos += scnprintf(buf + pos, bufsz - pos, | ||
415 | "\t%d<", bin_ranges[range_count - 1]); | ||
416 | } | ||
417 | |||
418 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
419 | |||
420 | return pos; | ||
421 | } | ||
422 | |||
423 | static int | ||
424 | sta_tx_latency_stat_table(struct ieee80211_tx_latency_bin_ranges *tx_lat_range, | ||
425 | struct ieee80211_tx_latency_stat *tx_lat, | ||
426 | char *buf, int pos, int bufsz, int tid) | ||
427 | { | ||
428 | u32 avg = 0; | ||
429 | int j; | ||
430 | int bin_count = tx_lat->bin_count; | ||
431 | |||
432 | pos += scnprintf(buf + pos, bufsz - pos, "\t\t\t%d", tid); | ||
433 | /* make sure you don't divide in 0 */ | ||
434 | if (tx_lat->counter) | ||
435 | avg = tx_lat->sum / tx_lat->counter; | ||
436 | |||
437 | pos += scnprintf(buf + pos, bufsz - pos, "\t%d\t%d", | ||
438 | tx_lat->max, avg); | ||
439 | |||
440 | if (tx_lat_range->n_ranges && tx_lat->bins) | ||
441 | for (j = 0; j < bin_count; j++) | ||
442 | pos += scnprintf(buf + pos, bufsz - pos, | ||
443 | "\t%d", tx_lat->bins[j]); | ||
444 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
445 | |||
446 | return pos; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * Output Tx latency statistics station && restart all statistics information | ||
451 | */ | ||
452 | static ssize_t sta_tx_latency_stat_read(struct file *file, | ||
453 | char __user *userbuf, | ||
454 | size_t count, loff_t *ppos) | ||
455 | { | ||
456 | struct sta_info *sta = file->private_data; | ||
457 | struct ieee80211_local *local = sta->local; | ||
458 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
459 | char *buf; | ||
460 | int bufsz, ret, i; | ||
461 | int pos = 0; | ||
462 | |||
463 | bufsz = 20 * IEEE80211_NUM_TIDS * | ||
464 | sizeof(struct ieee80211_tx_latency_stat); | ||
465 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
466 | if (!buf) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | rcu_read_lock(); | ||
470 | |||
471 | tx_latency = rcu_dereference(local->tx_latency); | ||
472 | |||
473 | if (!sta->tx_lat) { | ||
474 | pos += scnprintf(buf + pos, bufsz - pos, | ||
475 | "Tx latency statistics are not enabled\n"); | ||
476 | goto unlock; | ||
477 | } | ||
478 | |||
479 | pos = sta_tx_latency_stat_header(tx_latency, buf, pos, bufsz); | ||
480 | |||
481 | pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", sta->sta.addr); | ||
482 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) | ||
483 | pos = sta_tx_latency_stat_table(tx_latency, &sta->tx_lat[i], | ||
484 | buf, pos, bufsz, i); | ||
485 | unlock: | ||
486 | rcu_read_unlock(); | ||
487 | |||
488 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | ||
489 | kfree(buf); | ||
490 | |||
491 | return ret; | ||
492 | } | ||
493 | STA_OPS(tx_latency_stat); | ||
494 | |||
495 | static ssize_t sta_tx_latency_stat_reset_write(struct file *file, | ||
496 | const char __user *userbuf, | ||
497 | size_t count, loff_t *ppos) | ||
498 | { | ||
499 | u32 *bins; | ||
500 | int bin_count; | ||
501 | struct sta_info *sta = file->private_data; | ||
502 | int i; | ||
503 | |||
504 | if (!sta->tx_lat) | ||
505 | return -EINVAL; | ||
506 | |||
507 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | ||
508 | bins = sta->tx_lat[i].bins; | ||
509 | bin_count = sta->tx_lat[i].bin_count; | ||
510 | |||
511 | sta->tx_lat[i].max = 0; | ||
512 | sta->tx_lat[i].sum = 0; | ||
513 | sta->tx_lat[i].counter = 0; | ||
514 | |||
515 | if (bin_count) | ||
516 | memset(bins, 0, bin_count * sizeof(u32)); | ||
517 | } | ||
518 | |||
519 | return count; | ||
520 | } | ||
521 | STA_OPS_W(tx_latency_stat_reset); | ||
522 | |||
391 | #define DEBUGFS_ADD(name) \ | 523 | #define DEBUGFS_ADD(name) \ |
392 | debugfs_create_file(#name, 0400, \ | 524 | debugfs_create_file(#name, 0400, \ |
393 | sta->debugfs.dir, sta, &sta_ ##name## _ops); | 525 | sta->debugfs.dir, sta, &sta_ ##name## _ops); |
@@ -441,6 +573,8 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
441 | DEBUGFS_ADD(last_ack_signal); | 573 | DEBUGFS_ADD(last_ack_signal); |
442 | DEBUGFS_ADD(current_tx_rate); | 574 | DEBUGFS_ADD(current_tx_rate); |
443 | DEBUGFS_ADD(last_rx_rate); | 575 | DEBUGFS_ADD(last_rx_rate); |
576 | DEBUGFS_ADD(tx_latency_stat); | ||
577 | DEBUGFS_ADD(tx_latency_stat_reset); | ||
444 | 578 | ||
445 | DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); | 579 | DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); |
446 | DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); | 580 | DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 27a39de89679..2eda7b13124a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -550,12 +550,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
550 | capability); | 550 | capability); |
551 | /* XXX: should not really modify cfg80211 data */ | 551 | /* XXX: should not really modify cfg80211 data */ |
552 | if (cbss) { | 552 | if (cbss) { |
553 | cbss->channel = sdata->local->csa_chandef.chan; | 553 | cbss->channel = sdata->csa_chandef.chan; |
554 | cfg80211_put_bss(sdata->local->hw.wiphy, cbss); | 554 | cfg80211_put_bss(sdata->local->hw.wiphy, cbss); |
555 | } | 555 | } |
556 | } | 556 | } |
557 | 557 | ||
558 | ifibss->chandef = sdata->local->csa_chandef; | 558 | ifibss->chandef = sdata->csa_chandef; |
559 | 559 | ||
560 | /* generate the beacon */ | 560 | /* generate the beacon */ |
561 | err = ieee80211_ibss_csa_beacon(sdata, NULL); | 561 | err = ieee80211_ibss_csa_beacon(sdata, NULL); |
@@ -926,7 +926,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
926 | IEEE80211_MAX_QUEUE_MAP, | 926 | IEEE80211_MAX_QUEUE_MAP, |
927 | IEEE80211_QUEUE_STOP_REASON_CSA); | 927 | IEEE80211_QUEUE_STOP_REASON_CSA); |
928 | 928 | ||
929 | sdata->local->csa_chandef = params.chandef; | 929 | sdata->csa_chandef = params.chandef; |
930 | sdata->vif.csa_active = true; | 930 | sdata->vif.csa_active = true; |
931 | 931 | ||
932 | ieee80211_bss_info_change_notify(sdata, err); | 932 | ieee80211_bss_info_change_notify(sdata, err); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4aea4e791113..ed5bf8b4b5c2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -728,6 +728,7 @@ struct ieee80211_sub_if_data { | |||
728 | u16 sequence_number; | 728 | u16 sequence_number; |
729 | __be16 control_port_protocol; | 729 | __be16 control_port_protocol; |
730 | bool control_port_no_encrypt; | 730 | bool control_port_no_encrypt; |
731 | int encrypt_headroom; | ||
731 | 732 | ||
732 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; | 733 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; |
733 | 734 | ||
@@ -735,6 +736,7 @@ struct ieee80211_sub_if_data { | |||
735 | int csa_counter_offset_beacon; | 736 | int csa_counter_offset_beacon; |
736 | int csa_counter_offset_presp; | 737 | int csa_counter_offset_presp; |
737 | bool csa_radar_required; | 738 | bool csa_radar_required; |
739 | struct cfg80211_chan_def csa_chandef; | ||
738 | 740 | ||
739 | /* used to reconfigure hardware SM PS */ | 741 | /* used to reconfigure hardware SM PS */ |
740 | struct work_struct recalc_smps; | 742 | struct work_struct recalc_smps; |
@@ -811,6 +813,9 @@ static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata) | |||
811 | __release(&sdata->wdev.mtx); | 813 | __release(&sdata->wdev.mtx); |
812 | } | 814 | } |
813 | 815 | ||
816 | #define sdata_dereference(p, sdata) \ | ||
817 | rcu_dereference_protected(p, lockdep_is_held(&sdata->wdev.mtx)) | ||
818 | |||
814 | static inline void | 819 | static inline void |
815 | sdata_assert_lock(struct ieee80211_sub_if_data *sdata) | 820 | sdata_assert_lock(struct ieee80211_sub_if_data *sdata) |
816 | { | 821 | { |
@@ -896,6 +901,24 @@ struct tpt_led_trigger { | |||
896 | }; | 901 | }; |
897 | #endif | 902 | #endif |
898 | 903 | ||
904 | /* | ||
905 | * struct ieee80211_tx_latency_bin_ranges - Tx latency statistics bins ranges | ||
906 | * | ||
907 | * Measuring Tx latency statistics. Counts how many Tx frames transmitted in a | ||
908 | * certain latency range (in Milliseconds). Each station that uses these | ||
909 | * ranges will have bins to count the amount of frames received in that range. | ||
910 | * The user can configure the ranges via debugfs. | ||
911 | * If ranges is NULL then Tx latency statistics bins are disabled for all | ||
912 | * stations. | ||
913 | * | ||
914 | * @n_ranges: number of ranges that are taken in account | ||
915 | * @ranges: the ranges that the user requested or NULL if disabled. | ||
916 | */ | ||
917 | struct ieee80211_tx_latency_bin_ranges { | ||
918 | int n_ranges; | ||
919 | u32 ranges[]; | ||
920 | }; | ||
921 | |||
899 | /** | 922 | /** |
900 | * mac80211 scan flags - currently active scan mode | 923 | * mac80211 scan flags - currently active scan mode |
901 | * | 924 | * |
@@ -1048,6 +1071,12 @@ struct ieee80211_local { | |||
1048 | struct timer_list sta_cleanup; | 1071 | struct timer_list sta_cleanup; |
1049 | int sta_generation; | 1072 | int sta_generation; |
1050 | 1073 | ||
1074 | /* | ||
1075 | * Tx latency statistics parameters for all stations. | ||
1076 | * Can enable via debugfs (NULL when disabled). | ||
1077 | */ | ||
1078 | struct ieee80211_tx_latency_bin_ranges __rcu *tx_latency; | ||
1079 | |||
1051 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 1080 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
1052 | struct tasklet_struct tx_pending_tasklet; | 1081 | struct tasklet_struct tx_pending_tasklet; |
1053 | 1082 | ||
@@ -1093,7 +1122,6 @@ struct ieee80211_local { | |||
1093 | enum mac80211_scan_state next_scan_state; | 1122 | enum mac80211_scan_state next_scan_state; |
1094 | struct delayed_work scan_work; | 1123 | struct delayed_work scan_work; |
1095 | struct ieee80211_sub_if_data __rcu *scan_sdata; | 1124 | struct ieee80211_sub_if_data __rcu *scan_sdata; |
1096 | struct cfg80211_chan_def csa_chandef; | ||
1097 | /* For backward compatibility only -- do not use */ | 1125 | /* For backward compatibility only -- do not use */ |
1098 | struct cfg80211_chan_def _oper_chandef; | 1126 | struct cfg80211_chan_def _oper_chandef; |
1099 | 1127 | ||
@@ -1693,6 +1721,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, | |||
1693 | int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, | 1721 | int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, |
1694 | enum ieee80211_smps_mode smps_mode); | 1722 | enum ieee80211_smps_mode smps_mode); |
1695 | void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); | 1723 | void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); |
1724 | void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata); | ||
1696 | 1725 | ||
1697 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1726 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
1698 | const u8 *ids, int n_ids, size_t offset); | 1727 | const u8 *ids, int n_ids, size_t offset); |
@@ -1731,7 +1760,6 @@ ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | |||
1731 | /* NOTE: only use ieee80211_vif_change_channel() for channel switch */ | 1760 | /* NOTE: only use ieee80211_vif_change_channel() for channel switch */ |
1732 | int __must_check | 1761 | int __must_check |
1733 | ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | 1762 | ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, |
1734 | const struct cfg80211_chan_def *chandef, | ||
1735 | u32 *changed); | 1763 | u32 *changed); |
1736 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1764 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1737 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); | 1765 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); |
@@ -1742,6 +1770,8 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | |||
1742 | struct ieee80211_chanctx *chanctx); | 1770 | struct ieee80211_chanctx *chanctx); |
1743 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | 1771 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, |
1744 | struct ieee80211_chanctx *chanctx); | 1772 | struct ieee80211_chanctx *chanctx); |
1773 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, | ||
1774 | struct ieee80211_chanctx *ctx); | ||
1745 | 1775 | ||
1746 | void ieee80211_dfs_cac_timer(unsigned long data); | 1776 | void ieee80211_dfs_cac_timer(unsigned long data); |
1747 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); | 1777 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); |
@@ -1750,6 +1780,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work); | |||
1750 | int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | 1780 | int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, |
1751 | struct cfg80211_csa_settings *csa_settings); | 1781 | struct cfg80211_csa_settings *csa_settings); |
1752 | 1782 | ||
1783 | bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs); | ||
1784 | bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n); | ||
1785 | const struct ieee80211_cipher_scheme * | ||
1786 | ieee80211_cs_get(struct ieee80211_local *local, u32 cipher, | ||
1787 | enum nl80211_iftype iftype); | ||
1788 | int ieee80211_cs_headroom(struct ieee80211_local *local, | ||
1789 | struct cfg80211_crypto_settings *crypto, | ||
1790 | enum nl80211_iftype iftype); | ||
1791 | |||
1753 | #ifdef CONFIG_MAC80211_NOINLINE | 1792 | #ifdef CONFIG_MAC80211_NOINLINE |
1754 | #define debug_noinline noinline | 1793 | #define debug_noinline noinline |
1755 | #else | 1794 | #else |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 36c3a4cbcabf..7aa9f9dea9df 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
401 | snprintf(sdata->name, IFNAMSIZ, "%s-monitor", | 401 | snprintf(sdata->name, IFNAMSIZ, "%s-monitor", |
402 | wiphy_name(local->hw.wiphy)); | 402 | wiphy_name(local->hw.wiphy)); |
403 | 403 | ||
404 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
405 | |||
404 | ieee80211_set_default_queues(sdata); | 406 | ieee80211_set_default_queues(sdata); |
405 | 407 | ||
406 | ret = drv_add_interface(local, sdata); | 408 | ret = drv_add_interface(local, sdata); |
@@ -749,6 +751,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
749 | u32 hw_reconf_flags = 0; | 751 | u32 hw_reconf_flags = 0; |
750 | int i, flushed; | 752 | int i, flushed; |
751 | struct ps_data *ps; | 753 | struct ps_data *ps; |
754 | struct cfg80211_chan_def chandef; | ||
752 | 755 | ||
753 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 756 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
754 | 757 | ||
@@ -823,11 +826,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
823 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 826 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
824 | 827 | ||
825 | if (sdata->wdev.cac_started) { | 828 | if (sdata->wdev.cac_started) { |
829 | chandef = sdata->vif.bss_conf.chandef; | ||
826 | WARN_ON(local->suspended); | 830 | WARN_ON(local->suspended); |
827 | mutex_lock(&local->iflist_mtx); | 831 | mutex_lock(&local->iflist_mtx); |
828 | ieee80211_vif_release_channel(sdata); | 832 | ieee80211_vif_release_channel(sdata); |
829 | mutex_unlock(&local->iflist_mtx); | 833 | mutex_unlock(&local->iflist_mtx); |
830 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, | 834 | cfg80211_cac_event(sdata->dev, &chandef, |
835 | NL80211_RADAR_CAC_ABORTED, | ||
831 | GFP_KERNEL); | 836 | GFP_KERNEL); |
832 | } | 837 | } |
833 | 838 | ||
@@ -1036,7 +1041,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1036 | */ | 1041 | */ |
1037 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | 1042 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
1038 | { | 1043 | { |
1039 | int flushed; | ||
1040 | int i; | 1044 | int i; |
1041 | 1045 | ||
1042 | /* free extra data */ | 1046 | /* free extra data */ |
@@ -1050,9 +1054,6 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | |||
1050 | 1054 | ||
1051 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1055 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1052 | mesh_rmc_free(sdata); | 1056 | mesh_rmc_free(sdata); |
1053 | |||
1054 | flushed = sta_info_flush(sdata); | ||
1055 | WARN_ON(flushed); | ||
1056 | } | 1057 | } |
1057 | 1058 | ||
1058 | static void ieee80211_uninit(struct net_device *dev) | 1059 | static void ieee80211_uninit(struct net_device *dev) |
@@ -1270,6 +1271,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1270 | 1271 | ||
1271 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 1272 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
1272 | sdata->control_port_no_encrypt = false; | 1273 | sdata->control_port_no_encrypt = false; |
1274 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
1273 | 1275 | ||
1274 | sdata->noack_map = 0; | 1276 | sdata->noack_map = 0; |
1275 | 1277 | ||
@@ -1685,6 +1687,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1685 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | 1687 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1686 | sdata->user_power_level = local->user_power_level; | 1688 | sdata->user_power_level = local->user_power_level; |
1687 | 1689 | ||
1690 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
1691 | |||
1688 | /* setup type-dependent data */ | 1692 | /* setup type-dependent data */ |
1689 | ieee80211_setup_sdata(sdata, type); | 1693 | ieee80211_setup_sdata(sdata, type); |
1690 | 1694 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 3e51dd7d98b3..e568d98167d0 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -260,25 +260,29 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
260 | int idx; | 260 | int idx; |
261 | bool defunikey, defmultikey, defmgmtkey; | 261 | bool defunikey, defmultikey, defmgmtkey; |
262 | 262 | ||
263 | /* caller must provide at least one old/new */ | ||
264 | if (WARN_ON(!new && !old)) | ||
265 | return; | ||
266 | |||
263 | if (new) | 267 | if (new) |
264 | list_add_tail(&new->list, &sdata->key_list); | 268 | list_add_tail(&new->list, &sdata->key_list); |
265 | 269 | ||
266 | if (sta && pairwise) { | 270 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
267 | rcu_assign_pointer(sta->ptk, new); | ||
268 | } else if (sta) { | ||
269 | if (old) | ||
270 | idx = old->conf.keyidx; | ||
271 | else | ||
272 | idx = new->conf.keyidx; | ||
273 | rcu_assign_pointer(sta->gtk[idx], new); | ||
274 | } else { | ||
275 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); | ||
276 | 271 | ||
277 | if (old) | 272 | if (old) |
278 | idx = old->conf.keyidx; | 273 | idx = old->conf.keyidx; |
279 | else | 274 | else |
280 | idx = new->conf.keyidx; | 275 | idx = new->conf.keyidx; |
281 | 276 | ||
277 | if (sta) { | ||
278 | if (pairwise) { | ||
279 | rcu_assign_pointer(sta->ptk[idx], new); | ||
280 | sta->ptk_idx = idx; | ||
281 | } else { | ||
282 | rcu_assign_pointer(sta->gtk[idx], new); | ||
283 | sta->gtk_idx = idx; | ||
284 | } | ||
285 | } else { | ||
282 | defunikey = old && | 286 | defunikey = old && |
283 | old == key_mtx_dereference(sdata->local, | 287 | old == key_mtx_dereference(sdata->local, |
284 | sdata->default_unicast_key); | 288 | sdata->default_unicast_key); |
@@ -312,9 +316,11 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
312 | list_del(&old->list); | 316 | list_del(&old->list); |
313 | } | 317 | } |
314 | 318 | ||
315 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | 319 | struct ieee80211_key * |
316 | const u8 *key_data, | 320 | ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
317 | size_t seq_len, const u8 *seq) | 321 | const u8 *key_data, |
322 | size_t seq_len, const u8 *seq, | ||
323 | const struct ieee80211_cipher_scheme *cs) | ||
318 | { | 324 | { |
319 | struct ieee80211_key *key; | 325 | struct ieee80211_key *key; |
320 | int i, j, err; | 326 | int i, j, err; |
@@ -393,6 +399,18 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
393 | return ERR_PTR(err); | 399 | return ERR_PTR(err); |
394 | } | 400 | } |
395 | break; | 401 | break; |
402 | default: | ||
403 | if (cs) { | ||
404 | size_t len = (seq_len > MAX_PN_LEN) ? | ||
405 | MAX_PN_LEN : seq_len; | ||
406 | |||
407 | key->conf.iv_len = cs->hdr_len; | ||
408 | key->conf.icv_len = cs->mic_len; | ||
409 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) | ||
410 | for (j = 0; j < len; j++) | ||
411 | key->u.gen.rx_pn[i][j] = | ||
412 | seq[len - j - 1]; | ||
413 | } | ||
396 | } | 414 | } |
397 | memcpy(key->conf.key, key_data, key_len); | 415 | memcpy(key->conf.key, key_data, key_len); |
398 | INIT_LIST_HEAD(&key->list); | 416 | INIT_LIST_HEAD(&key->list); |
@@ -475,7 +493,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
475 | mutex_lock(&sdata->local->key_mtx); | 493 | mutex_lock(&sdata->local->key_mtx); |
476 | 494 | ||
477 | if (sta && pairwise) | 495 | if (sta && pairwise) |
478 | old_key = key_mtx_dereference(sdata->local, sta->ptk); | 496 | old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]); |
479 | else if (sta) | 497 | else if (sta) |
480 | old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); | 498 | old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); |
481 | else | 499 | else |
@@ -625,8 +643,10 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, | |||
625 | list_add(&key->list, &keys); | 643 | list_add(&key->list, &keys); |
626 | } | 644 | } |
627 | 645 | ||
628 | key = key_mtx_dereference(local, sta->ptk); | 646 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { |
629 | if (key) { | 647 | key = key_mtx_dereference(local, sta->ptk[i]); |
648 | if (!key) | ||
649 | continue; | ||
630 | ieee80211_key_replace(key->sdata, key->sta, | 650 | ieee80211_key_replace(key->sdata, key->sta, |
631 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 651 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
632 | key, NULL); | 652 | key, NULL); |
@@ -877,7 +897,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, | |||
877 | 897 | ||
878 | key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, | 898 | key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, |
879 | keyconf->keylen, keyconf->key, | 899 | keyconf->keylen, keyconf->key, |
880 | 0, NULL); | 900 | 0, NULL, NULL); |
881 | if (IS_ERR(key)) | 901 | if (IS_ERR(key)) |
882 | return ERR_CAST(key); | 902 | return ERR_CAST(key); |
883 | 903 | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index aaae0ed37004..0aebb889caba 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #define NUM_DEFAULT_KEYS 4 | 19 | #define NUM_DEFAULT_KEYS 4 |
20 | #define NUM_DEFAULT_MGMT_KEYS 2 | 20 | #define NUM_DEFAULT_MGMT_KEYS 2 |
21 | #define MAX_PN_LEN 16 | ||
21 | 22 | ||
22 | struct ieee80211_local; | 23 | struct ieee80211_local; |
23 | struct ieee80211_sub_if_data; | 24 | struct ieee80211_sub_if_data; |
@@ -93,6 +94,10 @@ struct ieee80211_key { | |||
93 | u32 replays; /* dot11RSNAStatsCMACReplays */ | 94 | u32 replays; /* dot11RSNAStatsCMACReplays */ |
94 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | 95 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ |
95 | } aes_cmac; | 96 | } aes_cmac; |
97 | struct { | ||
98 | /* generic cipher scheme */ | ||
99 | u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN]; | ||
100 | } gen; | ||
96 | } u; | 101 | } u; |
97 | 102 | ||
98 | /* number of times this key has been used */ | 103 | /* number of times this key has been used */ |
@@ -113,9 +118,11 @@ struct ieee80211_key { | |||
113 | struct ieee80211_key_conf conf; | 118 | struct ieee80211_key_conf conf; |
114 | }; | 119 | }; |
115 | 120 | ||
116 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | 121 | struct ieee80211_key * |
117 | const u8 *key_data, | 122 | ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
118 | size_t seq_len, const u8 *seq); | 123 | const u8 *key_data, |
124 | size_t seq_len, const u8 *seq, | ||
125 | const struct ieee80211_cipher_scheme *cs); | ||
119 | /* | 126 | /* |
120 | * Insert a key into data structures (sdata, sta if necessary) | 127 | * Insert a key into data structures (sdata, sta if necessary) |
121 | * to make it used, free old key. On failure, also free the new key. | 128 | * to make it used, free old key. On failure, also free the new key. |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7d1c3ac48ed9..fa34cd2344b9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -651,15 +651,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
651 | } | 651 | } |
652 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 652 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
653 | 653 | ||
654 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 654 | static int ieee80211_init_cipher_suites(struct ieee80211_local *local) |
655 | { | 655 | { |
656 | struct ieee80211_local *local = hw_to_local(hw); | 656 | bool have_wep = !(IS_ERR(local->wep_tx_tfm) || |
657 | int result, i; | 657 | IS_ERR(local->wep_rx_tfm)); |
658 | enum ieee80211_band band; | 658 | bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE; |
659 | int channels, max_bitrates; | 659 | const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes; |
660 | bool supp_ht, supp_vht; | 660 | int n_suites = 0, r = 0, w = 0; |
661 | netdev_features_t feature_whitelist; | 661 | u32 *suites; |
662 | struct cfg80211_chan_def dflt_chandef = {}; | ||
663 | static const u32 cipher_suites[] = { | 662 | static const u32 cipher_suites[] = { |
664 | /* keep WEP first, it may be removed below */ | 663 | /* keep WEP first, it may be removed below */ |
665 | WLAN_CIPHER_SUITE_WEP40, | 664 | WLAN_CIPHER_SUITE_WEP40, |
@@ -671,6 +670,93 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
671 | WLAN_CIPHER_SUITE_AES_CMAC | 670 | WLAN_CIPHER_SUITE_AES_CMAC |
672 | }; | 671 | }; |
673 | 672 | ||
673 | /* Driver specifies the ciphers, we have nothing to do... */ | ||
674 | if (local->hw.wiphy->cipher_suites && have_wep) | ||
675 | return 0; | ||
676 | |||
677 | /* Set up cipher suites if driver relies on mac80211 cipher defs */ | ||
678 | if (!local->hw.wiphy->cipher_suites && !cs) { | ||
679 | local->hw.wiphy->cipher_suites = cipher_suites; | ||
680 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
681 | |||
682 | if (!have_mfp) | ||
683 | local->hw.wiphy->n_cipher_suites--; | ||
684 | |||
685 | if (!have_wep) { | ||
686 | local->hw.wiphy->cipher_suites += 2; | ||
687 | local->hw.wiphy->n_cipher_suites -= 2; | ||
688 | } | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | if (!local->hw.wiphy->cipher_suites) { | ||
694 | /* | ||
695 | * Driver specifies cipher schemes only | ||
696 | * We start counting ciphers defined by schemes, TKIP and CCMP | ||
697 | */ | ||
698 | n_suites = local->hw.n_cipher_schemes + 2; | ||
699 | |||
700 | /* check if we have WEP40 and WEP104 */ | ||
701 | if (have_wep) | ||
702 | n_suites += 2; | ||
703 | |||
704 | /* check if we have AES_CMAC */ | ||
705 | if (have_mfp) | ||
706 | n_suites++; | ||
707 | |||
708 | suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); | ||
709 | if (!suites) | ||
710 | return -ENOMEM; | ||
711 | |||
712 | suites[w++] = WLAN_CIPHER_SUITE_CCMP; | ||
713 | suites[w++] = WLAN_CIPHER_SUITE_TKIP; | ||
714 | |||
715 | if (have_wep) { | ||
716 | suites[w++] = WLAN_CIPHER_SUITE_WEP40; | ||
717 | suites[w++] = WLAN_CIPHER_SUITE_WEP104; | ||
718 | } | ||
719 | |||
720 | if (have_mfp) | ||
721 | suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; | ||
722 | |||
723 | for (r = 0; r < local->hw.n_cipher_schemes; r++) | ||
724 | suites[w++] = cs[r].cipher; | ||
725 | } else { | ||
726 | /* Driver provides cipher suites, but we need to exclude WEP */ | ||
727 | suites = kmemdup(local->hw.wiphy->cipher_suites, | ||
728 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
729 | GFP_KERNEL); | ||
730 | if (!suites) | ||
731 | return -ENOMEM; | ||
732 | |||
733 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
734 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
735 | |||
736 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
737 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
738 | continue; | ||
739 | suites[w++] = suite; | ||
740 | } | ||
741 | } | ||
742 | |||
743 | local->hw.wiphy->cipher_suites = suites; | ||
744 | local->hw.wiphy->n_cipher_suites = w; | ||
745 | local->wiphy_ciphers_allocated = true; | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | int ieee80211_register_hw(struct ieee80211_hw *hw) | ||
751 | { | ||
752 | struct ieee80211_local *local = hw_to_local(hw); | ||
753 | int result, i; | ||
754 | enum ieee80211_band band; | ||
755 | int channels, max_bitrates; | ||
756 | bool supp_ht, supp_vht; | ||
757 | netdev_features_t feature_whitelist; | ||
758 | struct cfg80211_chan_def dflt_chandef = {}; | ||
759 | |||
674 | if (hw->flags & IEEE80211_HW_QUEUE_CONTROL && | 760 | if (hw->flags & IEEE80211_HW_QUEUE_CONTROL && |
675 | (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || | 761 | (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || |
676 | local->hw.offchannel_tx_hw_queue >= local->hw.queues)) | 762 | local->hw.offchannel_tx_hw_queue >= local->hw.queues)) |
@@ -851,43 +937,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
851 | if (local->hw.wiphy->max_scan_ie_len) | 937 | if (local->hw.wiphy->max_scan_ie_len) |
852 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; | 938 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; |
853 | 939 | ||
854 | /* Set up cipher suites unless driver already did */ | 940 | WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes, |
855 | if (!local->hw.wiphy->cipher_suites) { | 941 | local->hw.n_cipher_schemes)); |
856 | local->hw.wiphy->cipher_suites = cipher_suites; | 942 | |
857 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 943 | result = ieee80211_init_cipher_suites(local); |
858 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | 944 | if (result < 0) |
859 | local->hw.wiphy->n_cipher_suites--; | 945 | goto fail_wiphy_register; |
860 | } | ||
861 | if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { | ||
862 | if (local->hw.wiphy->cipher_suites == cipher_suites) { | ||
863 | local->hw.wiphy->cipher_suites += 2; | ||
864 | local->hw.wiphy->n_cipher_suites -= 2; | ||
865 | } else { | ||
866 | u32 *suites; | ||
867 | int r, w = 0; | ||
868 | |||
869 | /* Filter out WEP */ | ||
870 | |||
871 | suites = kmemdup( | ||
872 | local->hw.wiphy->cipher_suites, | ||
873 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
874 | GFP_KERNEL); | ||
875 | if (!suites) { | ||
876 | result = -ENOMEM; | ||
877 | goto fail_wiphy_register; | ||
878 | } | ||
879 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
880 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
881 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
882 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
883 | continue; | ||
884 | suites[w++] = suite; | ||
885 | } | ||
886 | local->hw.wiphy->cipher_suites = suites; | ||
887 | local->hw.wiphy->n_cipher_suites = w; | ||
888 | local->wiphy_ciphers_allocated = true; | ||
889 | } | ||
890 | } | ||
891 | 946 | ||
892 | if (!local->ops->remain_on_channel) | 947 | if (!local->ops->remain_on_channel) |
893 | local->hw.wiphy->max_remain_on_channel_duration = 5000; | 948 | local->hw.wiphy->max_remain_on_channel_duration = 5000; |
@@ -1090,6 +1145,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1090 | ieee80211_free_ack_frame, NULL); | 1145 | ieee80211_free_ack_frame, NULL); |
1091 | idr_destroy(&local->ack_status_frames); | 1146 | idr_destroy(&local->ack_status_frames); |
1092 | 1147 | ||
1148 | kfree(rcu_access_pointer(local->tx_latency)); | ||
1149 | |||
1093 | wiphy_free(local->hw.wiphy); | 1150 | wiphy_free(local->hw.wiphy); |
1094 | } | 1151 | } |
1095 | EXPORT_SYMBOL(ieee80211_free_hw); | 1152 | EXPORT_SYMBOL(ieee80211_free_hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index ba105257d03f..89df62b2b689 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -674,8 +674,6 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
674 | rcu_read_lock(); | 674 | rcu_read_lock(); |
675 | csa = rcu_dereference(ifmsh->csa); | 675 | csa = rcu_dereference(ifmsh->csa); |
676 | if (csa) { | 676 | if (csa) { |
677 | __le16 pre_value; | ||
678 | |||
679 | pos = skb_put(skb, 13); | 677 | pos = skb_put(skb, 13); |
680 | memset(pos, 0, 13); | 678 | memset(pos, 0, 13); |
681 | *pos++ = WLAN_EID_CHANNEL_SWITCH; | 679 | *pos++ = WLAN_EID_CHANNEL_SWITCH; |
@@ -697,8 +695,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
697 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; | 695 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; |
698 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); | 696 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); |
699 | pos += 2; | 697 | pos += 2; |
700 | pre_value = cpu_to_le16(ifmsh->pre_value); | 698 | put_unaligned_le16(ifmsh->pre_value, pos); |
701 | memcpy(pos, &pre_value, 2); | ||
702 | pos += 2; | 699 | pos += 2; |
703 | } | 700 | } |
704 | rcu_read_unlock(); | 701 | rcu_read_unlock(); |
@@ -964,7 +961,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
964 | IEEE80211_MAX_QUEUE_MAP, | 961 | IEEE80211_MAX_QUEUE_MAP, |
965 | IEEE80211_QUEUE_STOP_REASON_CSA); | 962 | IEEE80211_QUEUE_STOP_REASON_CSA); |
966 | 963 | ||
967 | sdata->local->csa_chandef = params.chandef; | 964 | sdata->csa_chandef = params.chandef; |
968 | sdata->vif.csa_active = true; | 965 | sdata->vif.csa_active = true; |
969 | 966 | ||
970 | ieee80211_bss_info_change_notify(sdata, err); | 967 | ieee80211_bss_info_change_notify(sdata, err); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 2bc7fd2f787d..f39a19f9090f 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -215,8 +215,6 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, | |||
215 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | 215 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
216 | struct ieee802_11_elems *ie); | 216 | struct ieee802_11_elems *ie); |
217 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 217 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
218 | void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata, | ||
219 | struct sk_buff *skb); | ||
220 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, | 218 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, |
221 | struct sk_buff *skb); | 219 | struct sk_buff *skb); |
222 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, | 220 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, |
@@ -303,8 +301,8 @@ void mesh_mpath_table_grow(void); | |||
303 | void mesh_mpp_table_grow(void); | 301 | void mesh_mpp_table_grow(void); |
304 | /* Mesh paths */ | 302 | /* Mesh paths */ |
305 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, | 303 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
306 | u8 ttl, const u8 *target, __le32 target_sn, | 304 | u8 ttl, const u8 *target, u32 target_sn, |
307 | __le16 target_rcode, const u8 *ra); | 305 | u16 target_rcode, const u8 *ra); |
308 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 306 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
309 | void mesh_path_flush_pending(struct mesh_path *mpath); | 307 | void mesh_path_flush_pending(struct mesh_path *mpath); |
310 | void mesh_path_tx_pending(struct mesh_path *mpath); | 308 | void mesh_path_tx_pending(struct mesh_path *mpath); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 486819cd02cd..f9514685d45a 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -102,12 +102,11 @@ enum mpath_frame_type { | |||
102 | static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 102 | static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
103 | 103 | ||
104 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | 104 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, |
105 | const u8 *orig_addr, __le32 orig_sn, | 105 | const u8 *orig_addr, u32 orig_sn, |
106 | u8 target_flags, const u8 *target, | 106 | u8 target_flags, const u8 *target, |
107 | __le32 target_sn, const u8 *da, | 107 | u32 target_sn, const u8 *da, |
108 | u8 hop_count, u8 ttl, | 108 | u8 hop_count, u8 ttl, |
109 | __le32 lifetime, __le32 metric, | 109 | u32 lifetime, u32 metric, u32 preq_id, |
110 | __le32 preq_id, | ||
111 | struct ieee80211_sub_if_data *sdata) | 110 | struct ieee80211_sub_if_data *sdata) |
112 | { | 111 | { |
113 | struct ieee80211_local *local = sdata->local; | 112 | struct ieee80211_local *local = sdata->local; |
@@ -167,33 +166,33 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
167 | if (action == MPATH_PREP) { | 166 | if (action == MPATH_PREP) { |
168 | memcpy(pos, target, ETH_ALEN); | 167 | memcpy(pos, target, ETH_ALEN); |
169 | pos += ETH_ALEN; | 168 | pos += ETH_ALEN; |
170 | memcpy(pos, &target_sn, 4); | 169 | put_unaligned_le32(target_sn, pos); |
171 | pos += 4; | 170 | pos += 4; |
172 | } else { | 171 | } else { |
173 | if (action == MPATH_PREQ) { | 172 | if (action == MPATH_PREQ) { |
174 | memcpy(pos, &preq_id, 4); | 173 | put_unaligned_le32(preq_id, pos); |
175 | pos += 4; | 174 | pos += 4; |
176 | } | 175 | } |
177 | memcpy(pos, orig_addr, ETH_ALEN); | 176 | memcpy(pos, orig_addr, ETH_ALEN); |
178 | pos += ETH_ALEN; | 177 | pos += ETH_ALEN; |
179 | memcpy(pos, &orig_sn, 4); | 178 | put_unaligned_le32(orig_sn, pos); |
180 | pos += 4; | 179 | pos += 4; |
181 | } | 180 | } |
182 | memcpy(pos, &lifetime, 4); /* interval for RANN */ | 181 | put_unaligned_le32(lifetime, pos); /* interval for RANN */ |
183 | pos += 4; | 182 | pos += 4; |
184 | memcpy(pos, &metric, 4); | 183 | put_unaligned_le32(metric, pos); |
185 | pos += 4; | 184 | pos += 4; |
186 | if (action == MPATH_PREQ) { | 185 | if (action == MPATH_PREQ) { |
187 | *pos++ = 1; /* destination count */ | 186 | *pos++ = 1; /* destination count */ |
188 | *pos++ = target_flags; | 187 | *pos++ = target_flags; |
189 | memcpy(pos, target, ETH_ALEN); | 188 | memcpy(pos, target, ETH_ALEN); |
190 | pos += ETH_ALEN; | 189 | pos += ETH_ALEN; |
191 | memcpy(pos, &target_sn, 4); | 190 | put_unaligned_le32(target_sn, pos); |
192 | pos += 4; | 191 | pos += 4; |
193 | } else if (action == MPATH_PREP) { | 192 | } else if (action == MPATH_PREP) { |
194 | memcpy(pos, orig_addr, ETH_ALEN); | 193 | memcpy(pos, orig_addr, ETH_ALEN); |
195 | pos += ETH_ALEN; | 194 | pos += ETH_ALEN; |
196 | memcpy(pos, &orig_sn, 4); | 195 | put_unaligned_le32(orig_sn, pos); |
197 | pos += 4; | 196 | pos += 4; |
198 | } | 197 | } |
199 | 198 | ||
@@ -239,8 +238,8 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, | |||
239 | * frame directly but add it to the pending queue instead. | 238 | * frame directly but add it to the pending queue instead. |
240 | */ | 239 | */ |
241 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, | 240 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
242 | u8 ttl, const u8 *target, __le32 target_sn, | 241 | u8 ttl, const u8 *target, u32 target_sn, |
243 | __le16 target_rcode, const u8 *ra) | 242 | u16 target_rcode, const u8 *ra) |
244 | { | 243 | { |
245 | struct ieee80211_local *local = sdata->local; | 244 | struct ieee80211_local *local = sdata->local; |
246 | struct sk_buff *skb; | 245 | struct sk_buff *skb; |
@@ -254,13 +253,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, | |||
254 | return -EAGAIN; | 253 | return -EAGAIN; |
255 | 254 | ||
256 | skb = dev_alloc_skb(local->tx_headroom + | 255 | skb = dev_alloc_skb(local->tx_headroom + |
257 | IEEE80211_ENCRYPT_HEADROOM + | 256 | sdata->encrypt_headroom + |
258 | IEEE80211_ENCRYPT_TAILROOM + | 257 | IEEE80211_ENCRYPT_TAILROOM + |
259 | hdr_len + | 258 | hdr_len + |
260 | 2 + 15 /* PERR IE */); | 259 | 2 + 15 /* PERR IE */); |
261 | if (!skb) | 260 | if (!skb) |
262 | return -1; | 261 | return -1; |
263 | skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); | 262 | skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom); |
264 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); | 263 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
265 | memset(mgmt, 0, hdr_len); | 264 | memset(mgmt, 0, hdr_len); |
266 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 265 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
@@ -293,9 +292,9 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, | |||
293 | pos++; | 292 | pos++; |
294 | memcpy(pos, target, ETH_ALEN); | 293 | memcpy(pos, target, ETH_ALEN); |
295 | pos += ETH_ALEN; | 294 | pos += ETH_ALEN; |
296 | memcpy(pos, &target_sn, 4); | 295 | put_unaligned_le32(target_sn, pos); |
297 | pos += 4; | 296 | pos += 4; |
298 | memcpy(pos, &target_rcode, 2); | 297 | put_unaligned_le16(target_rcode, pos); |
299 | 298 | ||
300 | /* see note in function header */ | 299 | /* see note in function header */ |
301 | prepare_frame_for_deferred_tx(sdata, skb); | 300 | prepare_frame_for_deferred_tx(sdata, skb); |
@@ -592,10 +591,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
592 | if (ttl != 0) { | 591 | if (ttl != 0) { |
593 | mhwmp_dbg(sdata, "replying to the PREQ\n"); | 592 | mhwmp_dbg(sdata, "replying to the PREQ\n"); |
594 | mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr, | 593 | mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr, |
595 | cpu_to_le32(orig_sn), 0, target_addr, | 594 | orig_sn, 0, target_addr, |
596 | cpu_to_le32(target_sn), mgmt->sa, 0, ttl, | 595 | target_sn, mgmt->sa, 0, ttl, |
597 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 596 | lifetime, metric, 0, sdata); |
598 | 0, sdata); | ||
599 | } else { | 597 | } else { |
600 | ifmsh->mshstats.dropped_frames_ttl++; | 598 | ifmsh->mshstats.dropped_frames_ttl++; |
601 | } | 599 | } |
@@ -625,11 +623,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
625 | } | 623 | } |
626 | 624 | ||
627 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, | 625 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, |
628 | cpu_to_le32(orig_sn), target_flags, target_addr, | 626 | orig_sn, target_flags, target_addr, |
629 | cpu_to_le32(target_sn), da, | 627 | target_sn, da, hopcount, ttl, lifetime, |
630 | hopcount, ttl, cpu_to_le32(lifetime), | 628 | metric, preq_id, sdata); |
631 | cpu_to_le32(metric), cpu_to_le32(preq_id), | ||
632 | sdata); | ||
633 | if (!is_multicast_ether_addr(da)) | 629 | if (!is_multicast_ether_addr(da)) |
634 | ifmsh->mshstats.fwded_unicast++; | 630 | ifmsh->mshstats.fwded_unicast++; |
635 | else | 631 | else |
@@ -695,11 +691,9 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
695 | target_sn = PREP_IE_TARGET_SN(prep_elem); | 691 | target_sn = PREP_IE_TARGET_SN(prep_elem); |
696 | orig_sn = PREP_IE_ORIG_SN(prep_elem); | 692 | orig_sn = PREP_IE_ORIG_SN(prep_elem); |
697 | 693 | ||
698 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, | 694 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, orig_sn, 0, |
699 | cpu_to_le32(orig_sn), 0, target_addr, | 695 | target_addr, target_sn, next_hop, hopcount, |
700 | cpu_to_le32(target_sn), next_hop, hopcount, | 696 | ttl, lifetime, metric, 0, sdata); |
701 | ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), | ||
702 | 0, sdata); | ||
703 | rcu_read_unlock(); | 697 | rcu_read_unlock(); |
704 | 698 | ||
705 | sdata->u.mesh.mshstats.fwded_unicast++; | 699 | sdata->u.mesh.mshstats.fwded_unicast++; |
@@ -750,8 +744,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
750 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 744 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
751 | goto endperr; | 745 | goto endperr; |
752 | mesh_path_error_tx(sdata, ttl, target_addr, | 746 | mesh_path_error_tx(sdata, ttl, target_addr, |
753 | cpu_to_le32(target_sn), | 747 | target_sn, target_rcode, |
754 | cpu_to_le16(target_rcode), | ||
755 | broadcast_addr); | 748 | broadcast_addr); |
756 | } else | 749 | } else |
757 | spin_unlock_bh(&mpath->state_lock); | 750 | spin_unlock_bh(&mpath->state_lock); |
@@ -847,11 +840,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
847 | 840 | ||
848 | if (ifmsh->mshcfg.dot11MeshForwarding) { | 841 | if (ifmsh->mshcfg.dot11MeshForwarding) { |
849 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 842 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
850 | cpu_to_le32(orig_sn), | 843 | orig_sn, 0, NULL, 0, broadcast_addr, |
851 | 0, NULL, 0, broadcast_addr, | 844 | hopcount, ttl, interval, |
852 | hopcount, ttl, cpu_to_le32(interval), | 845 | metric + metric_txsta, 0, sdata); |
853 | cpu_to_le32(metric + metric_txsta), | ||
854 | 0, sdata); | ||
855 | } | 846 | } |
856 | 847 | ||
857 | rcu_read_unlock(); | 848 | rcu_read_unlock(); |
@@ -1049,11 +1040,9 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
1049 | 1040 | ||
1050 | spin_unlock_bh(&mpath->state_lock); | 1041 | spin_unlock_bh(&mpath->state_lock); |
1051 | da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr; | 1042 | da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr; |
1052 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, | 1043 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn, |
1053 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, | 1044 | target_flags, mpath->dst, mpath->sn, da, 0, |
1054 | cpu_to_le32(mpath->sn), da, 0, | 1045 | ttl, lifetime, 0, ifmsh->preq_id++, sdata); |
1055 | ttl, cpu_to_le32(lifetime), 0, | ||
1056 | cpu_to_le32(ifmsh->preq_id++), sdata); | ||
1057 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 1046 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
1058 | 1047 | ||
1059 | enddiscovery: | 1048 | enddiscovery: |
@@ -1212,10 +1201,9 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1212 | switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) { | 1201 | switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) { |
1213 | case IEEE80211_PROACTIVE_RANN: | 1202 | case IEEE80211_PROACTIVE_RANN: |
1214 | mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr, | 1203 | mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr, |
1215 | cpu_to_le32(++ifmsh->sn), | 1204 | ++ifmsh->sn, 0, NULL, 0, broadcast_addr, |
1216 | 0, NULL, 0, broadcast_addr, | 1205 | 0, ifmsh->mshcfg.element_ttl, |
1217 | 0, ifmsh->mshcfg.element_ttl, | 1206 | interval, 0, 0, sdata); |
1218 | cpu_to_le32(interval), 0, 0, sdata); | ||
1219 | break; | 1207 | break; |
1220 | case IEEE80211_PROACTIVE_PREQ_WITH_PREP: | 1208 | case IEEE80211_PROACTIVE_PREQ_WITH_PREP: |
1221 | flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG; | 1209 | flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG; |
@@ -1224,11 +1212,10 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1224 | target_flags |= IEEE80211_PREQ_TO_FLAG | | 1212 | target_flags |= IEEE80211_PREQ_TO_FLAG | |
1225 | IEEE80211_PREQ_USN_FLAG; | 1213 | IEEE80211_PREQ_USN_FLAG; |
1226 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr, | 1214 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr, |
1227 | cpu_to_le32(++ifmsh->sn), target_flags, | 1215 | ++ifmsh->sn, target_flags, |
1228 | (u8 *) broadcast_addr, 0, broadcast_addr, | 1216 | (u8 *) broadcast_addr, 0, broadcast_addr, |
1229 | 0, ifmsh->mshcfg.element_ttl, | 1217 | 0, ifmsh->mshcfg.element_ttl, interval, |
1230 | cpu_to_le32(interval), | 1218 | 0, ifmsh->preq_id++, sdata); |
1231 | 0, cpu_to_le32(ifmsh->preq_id++), sdata); | ||
1232 | break; | 1219 | break; |
1233 | default: | 1220 | default: |
1234 | mhwmp_dbg(sdata, "Proactive mechanism not supported\n"); | 1221 | mhwmp_dbg(sdata, "Proactive mechanism not supported\n"); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 89aacfd2756d..7d050ed6fe5a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -722,7 +722,6 @@ void mesh_plink_broken(struct sta_info *sta) | |||
722 | struct mpath_node *node; | 722 | struct mpath_node *node; |
723 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 723 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
724 | int i; | 724 | int i; |
725 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE); | ||
726 | 725 | ||
727 | rcu_read_lock(); | 726 | rcu_read_lock(); |
728 | tbl = rcu_dereference(mesh_paths); | 727 | tbl = rcu_dereference(mesh_paths); |
@@ -736,9 +735,9 @@ void mesh_plink_broken(struct sta_info *sta) | |||
736 | ++mpath->sn; | 735 | ++mpath->sn; |
737 | spin_unlock_bh(&mpath->state_lock); | 736 | spin_unlock_bh(&mpath->state_lock); |
738 | mesh_path_error_tx(sdata, | 737 | mesh_path_error_tx(sdata, |
739 | sdata->u.mesh.mshcfg.element_ttl, | 738 | sdata->u.mesh.mshcfg.element_ttl, |
740 | mpath->dst, cpu_to_le32(mpath->sn), | 739 | mpath->dst, mpath->sn, |
741 | reason, bcast); | 740 | WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast); |
742 | } | 741 | } |
743 | } | 742 | } |
744 | rcu_read_unlock(); | 743 | rcu_read_unlock(); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4301aa5aa227..cf83217103f9 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -19,12 +19,6 @@ | |||
19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ | 19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ |
20 | jiffies + HZ * t / 1000)) | 20 | jiffies + HZ * t / 1000)) |
21 | 21 | ||
22 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ | ||
23 | #define rssi_threshold_check(sta, sdata) \ | ||
24 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ | ||
25 | (sta && (s8) -ewma_read(&sta->avg_signal) > \ | ||
26 | sdata->u.mesh.mshcfg.rssi_threshold)) | ||
27 | |||
28 | enum plink_event { | 22 | enum plink_event { |
29 | PLINK_UNDEFINED, | 23 | PLINK_UNDEFINED, |
30 | OPN_ACPT, | 24 | OPN_ACPT, |
@@ -61,7 +55,17 @@ static const char * const mplevents[] = { | |||
61 | 55 | ||
62 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 56 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
63 | enum ieee80211_self_protected_actioncode action, | 57 | enum ieee80211_self_protected_actioncode action, |
64 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 58 | u8 *da, u16 llid, u16 plid, u16 reason); |
59 | |||
60 | |||
61 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ | ||
62 | static bool rssi_threshold_check(struct ieee80211_sub_if_data *sdata, | ||
63 | struct sta_info *sta) | ||
64 | { | ||
65 | s32 rssi_threshold = sdata->u.mesh.mshcfg.rssi_threshold; | ||
66 | return rssi_threshold == 0 || | ||
67 | (sta && (s8) -ewma_read(&sta->avg_signal) > rssi_threshold); | ||
68 | } | ||
65 | 69 | ||
66 | /** | 70 | /** |
67 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine | 71 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine |
@@ -242,7 +246,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta) | |||
242 | 246 | ||
243 | spin_lock_bh(&sta->lock); | 247 | spin_lock_bh(&sta->lock); |
244 | changed = __mesh_plink_deactivate(sta); | 248 | changed = __mesh_plink_deactivate(sta); |
245 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); | 249 | sta->reason = WLAN_REASON_MESH_PEER_CANCELED; |
246 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 250 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
247 | sta->sta.addr, sta->llid, sta->plid, | 251 | sta->sta.addr, sta->llid, sta->plid, |
248 | sta->reason); | 252 | sta->reason); |
@@ -253,7 +257,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta) | |||
253 | 257 | ||
254 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 258 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
255 | enum ieee80211_self_protected_actioncode action, | 259 | enum ieee80211_self_protected_actioncode action, |
256 | u8 *da, __le16 llid, __le16 plid, __le16 reason) | 260 | u8 *da, u16 llid, u16 plid, u16 reason) |
257 | { | 261 | { |
258 | struct ieee80211_local *local = sdata->local; | 262 | struct ieee80211_local *local = sdata->local; |
259 | struct sk_buff *skb; | 263 | struct sk_buff *skb; |
@@ -279,7 +283,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
279 | 2 + 8 + /* peering IE */ | 283 | 2 + 8 + /* peering IE */ |
280 | sdata->u.mesh.ie_len); | 284 | sdata->u.mesh.ie_len); |
281 | if (!skb) | 285 | if (!skb) |
282 | return -1; | 286 | return err; |
283 | info = IEEE80211_SKB_CB(skb); | 287 | info = IEEE80211_SKB_CB(skb); |
284 | skb_reserve(skb, local->tx_headroom); | 288 | skb_reserve(skb, local->tx_headroom); |
285 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); | 289 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
@@ -301,7 +305,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
301 | if (action == WLAN_SP_MESH_PEERING_CONFIRM) { | 305 | if (action == WLAN_SP_MESH_PEERING_CONFIRM) { |
302 | /* AID */ | 306 | /* AID */ |
303 | pos = skb_put(skb, 2); | 307 | pos = skb_put(skb, 2); |
304 | memcpy(pos + 2, &plid, 2); | 308 | put_unaligned_le16(plid, pos + 2); |
305 | } | 309 | } |
306 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 310 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
307 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 311 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
@@ -343,14 +347,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
343 | *pos++ = ie_len; | 347 | *pos++ = ie_len; |
344 | memcpy(pos, &peering_proto, 2); | 348 | memcpy(pos, &peering_proto, 2); |
345 | pos += 2; | 349 | pos += 2; |
346 | memcpy(pos, &llid, 2); | 350 | put_unaligned_le16(llid, pos); |
347 | pos += 2; | 351 | pos += 2; |
348 | if (include_plid) { | 352 | if (include_plid) { |
349 | memcpy(pos, &plid, 2); | 353 | put_unaligned_le16(plid, pos); |
350 | pos += 2; | 354 | pos += 2; |
351 | } | 355 | } |
352 | if (action == WLAN_SP_MESH_PEERING_CLOSE) { | 356 | if (action == WLAN_SP_MESH_PEERING_CLOSE) { |
353 | memcpy(pos, &reason, 2); | 357 | put_unaligned_le16(reason, pos); |
354 | pos += 2; | 358 | pos += 2; |
355 | } | 359 | } |
356 | 360 | ||
@@ -518,7 +522,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | |||
518 | sta->plink_state == NL80211_PLINK_LISTEN && | 522 | sta->plink_state == NL80211_PLINK_LISTEN && |
519 | sdata->u.mesh.accepting_plinks && | 523 | sdata->u.mesh.accepting_plinks && |
520 | sdata->u.mesh.mshcfg.auto_open_plinks && | 524 | sdata->u.mesh.mshcfg.auto_open_plinks && |
521 | rssi_threshold_check(sta, sdata)) | 525 | rssi_threshold_check(sdata, sta)) |
522 | changed = mesh_plink_open(sta); | 526 | changed = mesh_plink_open(sta); |
523 | 527 | ||
524 | ieee80211_mps_frame_release(sta, elems); | 528 | ieee80211_mps_frame_release(sta, elems); |
@@ -530,9 +534,10 @@ out: | |||
530 | static void mesh_plink_timer(unsigned long data) | 534 | static void mesh_plink_timer(unsigned long data) |
531 | { | 535 | { |
532 | struct sta_info *sta; | 536 | struct sta_info *sta; |
533 | __le16 llid, plid, reason; | 537 | u16 reason = 0; |
534 | struct ieee80211_sub_if_data *sdata; | 538 | struct ieee80211_sub_if_data *sdata; |
535 | struct mesh_config *mshcfg; | 539 | struct mesh_config *mshcfg; |
540 | enum ieee80211_self_protected_actioncode action = 0; | ||
536 | 541 | ||
537 | /* | 542 | /* |
538 | * This STA is valid because sta_info_destroy() will | 543 | * This STA is valid because sta_info_destroy() will |
@@ -553,9 +558,6 @@ static void mesh_plink_timer(unsigned long data) | |||
553 | mpl_dbg(sta->sdata, | 558 | mpl_dbg(sta->sdata, |
554 | "Mesh plink timer for %pM fired on state %s\n", | 559 | "Mesh plink timer for %pM fired on state %s\n", |
555 | sta->sta.addr, mplstates[sta->plink_state]); | 560 | sta->sta.addr, mplstates[sta->plink_state]); |
556 | reason = 0; | ||
557 | llid = sta->llid; | ||
558 | plid = sta->plid; | ||
559 | sdata = sta->sdata; | 561 | sdata = sta->sdata; |
560 | mshcfg = &sdata->u.mesh.mshcfg; | 562 | mshcfg = &sdata->u.mesh.mshcfg; |
561 | 563 | ||
@@ -574,33 +576,31 @@ static void mesh_plink_timer(unsigned long data) | |||
574 | rand % sta->plink_timeout; | 576 | rand % sta->plink_timeout; |
575 | ++sta->plink_retries; | 577 | ++sta->plink_retries; |
576 | mod_plink_timer(sta, sta->plink_timeout); | 578 | mod_plink_timer(sta, sta->plink_timeout); |
577 | spin_unlock_bh(&sta->lock); | 579 | action = WLAN_SP_MESH_PEERING_OPEN; |
578 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, | ||
579 | sta->sta.addr, llid, 0, 0); | ||
580 | break; | 580 | break; |
581 | } | 581 | } |
582 | reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES); | 582 | reason = WLAN_REASON_MESH_MAX_RETRIES; |
583 | /* fall through on else */ | 583 | /* fall through on else */ |
584 | case NL80211_PLINK_CNF_RCVD: | 584 | case NL80211_PLINK_CNF_RCVD: |
585 | /* confirm timer */ | 585 | /* confirm timer */ |
586 | if (!reason) | 586 | if (!reason) |
587 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); | 587 | reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT; |
588 | sta->plink_state = NL80211_PLINK_HOLDING; | 588 | sta->plink_state = NL80211_PLINK_HOLDING; |
589 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); | 589 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
590 | spin_unlock_bh(&sta->lock); | 590 | action = WLAN_SP_MESH_PEERING_CLOSE; |
591 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
592 | sta->sta.addr, llid, plid, reason); | ||
593 | break; | 591 | break; |
594 | case NL80211_PLINK_HOLDING: | 592 | case NL80211_PLINK_HOLDING: |
595 | /* holding timer */ | 593 | /* holding timer */ |
596 | del_timer(&sta->plink_timer); | 594 | del_timer(&sta->plink_timer); |
597 | mesh_plink_fsm_restart(sta); | 595 | mesh_plink_fsm_restart(sta); |
598 | spin_unlock_bh(&sta->lock); | ||
599 | break; | 596 | break; |
600 | default: | 597 | default: |
601 | spin_unlock_bh(&sta->lock); | ||
602 | break; | 598 | break; |
603 | } | 599 | } |
600 | spin_unlock_bh(&sta->lock); | ||
601 | if (action) | ||
602 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, | ||
603 | sta->llid, sta->plid, reason); | ||
604 | } | 604 | } |
605 | 605 | ||
606 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | 606 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) |
@@ -612,9 +612,40 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | |||
612 | add_timer(&sta->plink_timer); | 612 | add_timer(&sta->plink_timer); |
613 | } | 613 | } |
614 | 614 | ||
615 | static bool llid_in_use(struct ieee80211_sub_if_data *sdata, | ||
616 | u16 llid) | ||
617 | { | ||
618 | struct ieee80211_local *local = sdata->local; | ||
619 | bool in_use = false; | ||
620 | struct sta_info *sta; | ||
621 | |||
622 | rcu_read_lock(); | ||
623 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
624 | if (!memcmp(&sta->llid, &llid, sizeof(llid))) { | ||
625 | in_use = true; | ||
626 | break; | ||
627 | } | ||
628 | } | ||
629 | rcu_read_unlock(); | ||
630 | |||
631 | return in_use; | ||
632 | } | ||
633 | |||
634 | static u16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata) | ||
635 | { | ||
636 | u16 llid; | ||
637 | |||
638 | do { | ||
639 | get_random_bytes(&llid, sizeof(llid)); | ||
640 | /* for mesh PS we still only have the AID range for TIM bits */ | ||
641 | llid = (llid % IEEE80211_MAX_AID) + 1; | ||
642 | } while (llid_in_use(sdata, llid)); | ||
643 | |||
644 | return llid; | ||
645 | } | ||
646 | |||
615 | u32 mesh_plink_open(struct sta_info *sta) | 647 | u32 mesh_plink_open(struct sta_info *sta) |
616 | { | 648 | { |
617 | __le16 llid; | ||
618 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 649 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
619 | u32 changed; | 650 | u32 changed; |
620 | 651 | ||
@@ -622,8 +653,7 @@ u32 mesh_plink_open(struct sta_info *sta) | |||
622 | return 0; | 653 | return 0; |
623 | 654 | ||
624 | spin_lock_bh(&sta->lock); | 655 | spin_lock_bh(&sta->lock); |
625 | get_random_bytes(&llid, 2); | 656 | sta->llid = mesh_get_new_llid(sdata); |
626 | sta->llid = llid; | ||
627 | if (sta->plink_state != NL80211_PLINK_LISTEN && | 657 | if (sta->plink_state != NL80211_PLINK_LISTEN && |
628 | sta->plink_state != NL80211_PLINK_BLOCKED) { | 658 | sta->plink_state != NL80211_PLINK_BLOCKED) { |
629 | spin_unlock_bh(&sta->lock); | 659 | spin_unlock_bh(&sta->lock); |
@@ -640,7 +670,7 @@ u32 mesh_plink_open(struct sta_info *sta) | |||
640 | changed = ieee80211_mps_local_status_update(sdata); | 670 | changed = ieee80211_mps_local_status_update(sdata); |
641 | 671 | ||
642 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, | 672 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, |
643 | sta->sta.addr, llid, 0, 0); | 673 | sta->sta.addr, sta->llid, 0, 0); |
644 | return changed; | 674 | return changed; |
645 | } | 675 | } |
646 | 676 | ||
@@ -656,390 +686,147 @@ u32 mesh_plink_block(struct sta_info *sta) | |||
656 | return changed; | 686 | return changed; |
657 | } | 687 | } |
658 | 688 | ||
659 | 689 | static void mesh_plink_close(struct ieee80211_sub_if_data *sdata, | |
660 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | 690 | struct sta_info *sta, |
661 | struct ieee80211_mgmt *mgmt, size_t len, | 691 | enum plink_event event) |
662 | struct ieee80211_rx_status *rx_status) | ||
663 | { | 692 | { |
664 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; | 693 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; |
665 | struct ieee802_11_elems elems; | ||
666 | struct sta_info *sta; | ||
667 | enum plink_event event; | ||
668 | enum ieee80211_self_protected_actioncode ftype; | ||
669 | size_t baselen; | ||
670 | bool matches_local = true; | ||
671 | u8 ie_len; | ||
672 | u8 *baseaddr; | ||
673 | u32 changed = 0; | ||
674 | __le16 plid, llid, reason; | ||
675 | |||
676 | /* need action_code, aux */ | ||
677 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | ||
678 | return; | ||
679 | |||
680 | if (sdata->u.mesh.user_mpm) | ||
681 | /* userspace must register for these */ | ||
682 | return; | ||
683 | |||
684 | if (is_multicast_ether_addr(mgmt->da)) { | ||
685 | mpl_dbg(sdata, | ||
686 | "Mesh plink: ignore frame from multicast address\n"); | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | baseaddr = mgmt->u.action.u.self_prot.variable; | ||
691 | baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; | ||
692 | if (mgmt->u.action.u.self_prot.action_code == | ||
693 | WLAN_SP_MESH_PEERING_CONFIRM) { | ||
694 | baseaddr += 4; | ||
695 | baselen += 4; | ||
696 | } | ||
697 | ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); | ||
698 | |||
699 | if (!elems.peering) { | ||
700 | mpl_dbg(sdata, | ||
701 | "Mesh plink: missing necessary peer link ie\n"); | ||
702 | return; | ||
703 | } | ||
704 | 694 | ||
705 | if (elems.rsn_len && | 695 | u16 reason = (event == CLS_ACPT) ? |
706 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | 696 | WLAN_REASON_MESH_CLOSE : WLAN_REASON_MESH_CONFIG; |
707 | mpl_dbg(sdata, | ||
708 | "Mesh plink: can't establish link with secure peer\n"); | ||
709 | return; | ||
710 | } | ||
711 | 697 | ||
712 | ftype = mgmt->u.action.u.self_prot.action_code; | 698 | sta->reason = reason; |
713 | ie_len = elems.peering_len; | 699 | sta->plink_state = NL80211_PLINK_HOLDING; |
714 | if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || | 700 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
715 | (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || | 701 | } |
716 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 | ||
717 | && ie_len != 8)) { | ||
718 | mpl_dbg(sdata, | ||
719 | "Mesh plink: incorrect plink ie length %d %d\n", | ||
720 | ftype, ie_len); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | ||
725 | (!elems.mesh_id || !elems.mesh_config)) { | ||
726 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); | ||
727 | return; | ||
728 | } | ||
729 | /* Note the lines below are correct, the llid in the frame is the plid | ||
730 | * from the point of view of this host. | ||
731 | */ | ||
732 | memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); | ||
733 | if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || | ||
734 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) | ||
735 | memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); | ||
736 | |||
737 | /* WARNING: Only for sta pointer, is dropped & re-acquired */ | ||
738 | rcu_read_lock(); | ||
739 | |||
740 | sta = sta_info_get(sdata, mgmt->sa); | ||
741 | if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) { | ||
742 | mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); | ||
743 | rcu_read_unlock(); | ||
744 | return; | ||
745 | } | ||
746 | |||
747 | if (ftype == WLAN_SP_MESH_PEERING_OPEN && | ||
748 | !rssi_threshold_check(sta, sdata)) { | ||
749 | mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", | ||
750 | mgmt->sa); | ||
751 | rcu_read_unlock(); | ||
752 | return; | ||
753 | } | ||
754 | |||
755 | if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
756 | mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); | ||
757 | rcu_read_unlock(); | ||
758 | return; | ||
759 | } | ||
760 | 702 | ||
761 | if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) { | 703 | static u32 mesh_plink_establish(struct ieee80211_sub_if_data *sdata, |
762 | rcu_read_unlock(); | 704 | struct sta_info *sta) |
763 | return; | 705 | { |
764 | } | 706 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; |
707 | u32 changed = 0; | ||
765 | 708 | ||
766 | /* Now we will figure out the appropriate event... */ | 709 | del_timer(&sta->plink_timer); |
767 | event = PLINK_UNDEFINED; | 710 | sta->plink_state = NL80211_PLINK_ESTAB; |
768 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | 711 | changed |= mesh_plink_inc_estab_count(sdata); |
769 | !mesh_matches_local(sdata, &elems)) { | 712 | changed |= mesh_set_ht_prot_mode(sdata); |
770 | matches_local = false; | 713 | changed |= mesh_set_short_slot_time(sdata); |
771 | switch (ftype) { | 714 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); |
772 | case WLAN_SP_MESH_PEERING_OPEN: | 715 | ieee80211_mps_sta_status_update(sta); |
773 | event = OPN_RJCT; | 716 | changed |= ieee80211_mps_set_sta_local_pm(sta, mshcfg->power_mode); |
774 | break; | 717 | return changed; |
775 | case WLAN_SP_MESH_PEERING_CONFIRM: | 718 | } |
776 | event = CNF_RJCT; | ||
777 | break; | ||
778 | default: | ||
779 | break; | ||
780 | } | ||
781 | } | ||
782 | 719 | ||
783 | if (!sta && !matches_local) { | 720 | /** |
784 | rcu_read_unlock(); | 721 | * mesh_plink_fsm - step @sta MPM based on @event |
785 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); | 722 | * |
786 | llid = 0; | 723 | * @sdata: interface |
787 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 724 | * @sta: mesh neighbor |
788 | mgmt->sa, llid, plid, reason); | 725 | * @event: peering event |
789 | return; | 726 | * |
790 | } else if (!sta) { | 727 | * Return: changed MBSS flags |
791 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ | 728 | */ |
792 | if (!mesh_plink_free_count(sdata)) { | 729 | static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, |
793 | mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); | 730 | struct sta_info *sta, enum plink_event event) |
794 | rcu_read_unlock(); | 731 | { |
795 | return; | 732 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; |
796 | } | 733 | enum ieee80211_self_protected_actioncode action = 0; |
797 | event = OPN_ACPT; | 734 | u32 changed = 0; |
798 | } else if (matches_local) { | ||
799 | switch (ftype) { | ||
800 | case WLAN_SP_MESH_PEERING_OPEN: | ||
801 | if (!mesh_plink_free_count(sdata) || | ||
802 | (sta->plid && sta->plid != plid)) | ||
803 | event = OPN_IGNR; | ||
804 | else | ||
805 | event = OPN_ACPT; | ||
806 | break; | ||
807 | case WLAN_SP_MESH_PEERING_CONFIRM: | ||
808 | if (!mesh_plink_free_count(sdata) || | ||
809 | (sta->llid != llid || sta->plid != plid)) | ||
810 | event = CNF_IGNR; | ||
811 | else | ||
812 | event = CNF_ACPT; | ||
813 | break; | ||
814 | case WLAN_SP_MESH_PEERING_CLOSE: | ||
815 | if (sta->plink_state == NL80211_PLINK_ESTAB) | ||
816 | /* Do not check for llid or plid. This does not | ||
817 | * follow the standard but since multiple plinks | ||
818 | * per sta are not supported, it is necessary in | ||
819 | * order to avoid a livelock when MP A sees an | ||
820 | * establish peer link to MP B but MP B does not | ||
821 | * see it. This can be caused by a timeout in | ||
822 | * B's peer link establishment or B beign | ||
823 | * restarted. | ||
824 | */ | ||
825 | event = CLS_ACPT; | ||
826 | else if (sta->plid != plid) | ||
827 | event = CLS_IGNR; | ||
828 | else if (ie_len == 7 && sta->llid != llid) | ||
829 | event = CLS_IGNR; | ||
830 | else | ||
831 | event = CLS_ACPT; | ||
832 | break; | ||
833 | default: | ||
834 | mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); | ||
835 | rcu_read_unlock(); | ||
836 | return; | ||
837 | } | ||
838 | } | ||
839 | 735 | ||
840 | if (event == OPN_ACPT) { | 736 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, |
841 | rcu_read_unlock(); | 737 | mplstates[sta->plink_state], mplevents[event]); |
842 | /* allocate sta entry if necessary and update info */ | ||
843 | sta = mesh_sta_info_get(sdata, mgmt->sa, &elems); | ||
844 | if (!sta) { | ||
845 | mpl_dbg(sdata, "Mesh plink: failed to init peer!\n"); | ||
846 | rcu_read_unlock(); | ||
847 | return; | ||
848 | } | ||
849 | } | ||
850 | 738 | ||
851 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa, | ||
852 | mplstates[sta->plink_state], mplevents[event]); | ||
853 | reason = 0; | ||
854 | spin_lock_bh(&sta->lock); | 739 | spin_lock_bh(&sta->lock); |
855 | switch (sta->plink_state) { | 740 | switch (sta->plink_state) { |
856 | /* spin_unlock as soon as state is updated at each case */ | ||
857 | case NL80211_PLINK_LISTEN: | 741 | case NL80211_PLINK_LISTEN: |
858 | switch (event) { | 742 | switch (event) { |
859 | case CLS_ACPT: | 743 | case CLS_ACPT: |
860 | mesh_plink_fsm_restart(sta); | 744 | mesh_plink_fsm_restart(sta); |
861 | spin_unlock_bh(&sta->lock); | ||
862 | break; | 745 | break; |
863 | case OPN_ACPT: | 746 | case OPN_ACPT: |
864 | sta->plink_state = NL80211_PLINK_OPN_RCVD; | 747 | sta->plink_state = NL80211_PLINK_OPN_RCVD; |
865 | sta->plid = plid; | 748 | sta->llid = mesh_get_new_llid(sdata); |
866 | get_random_bytes(&llid, 2); | ||
867 | sta->llid = llid; | ||
868 | mesh_plink_timer_set(sta, | 749 | mesh_plink_timer_set(sta, |
869 | mshcfg->dot11MeshRetryTimeout); | 750 | mshcfg->dot11MeshRetryTimeout); |
870 | 751 | ||
871 | /* set the non-peer mode to active during peering */ | 752 | /* set the non-peer mode to active during peering */ |
872 | changed |= ieee80211_mps_local_status_update(sdata); | 753 | changed |= ieee80211_mps_local_status_update(sdata); |
873 | 754 | action = WLAN_SP_MESH_PEERING_OPEN; | |
874 | spin_unlock_bh(&sta->lock); | ||
875 | mesh_plink_frame_tx(sdata, | ||
876 | WLAN_SP_MESH_PEERING_OPEN, | ||
877 | sta->sta.addr, llid, 0, 0); | ||
878 | mesh_plink_frame_tx(sdata, | ||
879 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
880 | sta->sta.addr, llid, plid, 0); | ||
881 | break; | 755 | break; |
882 | default: | 756 | default: |
883 | spin_unlock_bh(&sta->lock); | ||
884 | break; | 757 | break; |
885 | } | 758 | } |
886 | break; | 759 | break; |
887 | |||
888 | case NL80211_PLINK_OPN_SNT: | 760 | case NL80211_PLINK_OPN_SNT: |
889 | switch (event) { | 761 | switch (event) { |
890 | case OPN_RJCT: | 762 | case OPN_RJCT: |
891 | case CNF_RJCT: | 763 | case CNF_RJCT: |
892 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); | ||
893 | case CLS_ACPT: | 764 | case CLS_ACPT: |
894 | if (!reason) | 765 | mesh_plink_close(sdata, sta, event); |
895 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | 766 | action = WLAN_SP_MESH_PEERING_CLOSE; |
896 | sta->reason = reason; | ||
897 | sta->plink_state = NL80211_PLINK_HOLDING; | ||
898 | if (!mod_plink_timer(sta, | ||
899 | mshcfg->dot11MeshHoldingTimeout)) | ||
900 | sta->ignore_plink_timer = true; | ||
901 | |||
902 | llid = sta->llid; | ||
903 | spin_unlock_bh(&sta->lock); | ||
904 | mesh_plink_frame_tx(sdata, | ||
905 | WLAN_SP_MESH_PEERING_CLOSE, | ||
906 | sta->sta.addr, llid, plid, reason); | ||
907 | break; | 767 | break; |
908 | case OPN_ACPT: | 768 | case OPN_ACPT: |
909 | /* retry timer is left untouched */ | 769 | /* retry timer is left untouched */ |
910 | sta->plink_state = NL80211_PLINK_OPN_RCVD; | 770 | sta->plink_state = NL80211_PLINK_OPN_RCVD; |
911 | sta->plid = plid; | 771 | action = WLAN_SP_MESH_PEERING_CONFIRM; |
912 | llid = sta->llid; | ||
913 | spin_unlock_bh(&sta->lock); | ||
914 | mesh_plink_frame_tx(sdata, | ||
915 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
916 | sta->sta.addr, llid, plid, 0); | ||
917 | break; | 772 | break; |
918 | case CNF_ACPT: | 773 | case CNF_ACPT: |
919 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 774 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
920 | if (!mod_plink_timer(sta, | 775 | if (!mod_plink_timer(sta, |
921 | mshcfg->dot11MeshConfirmTimeout)) | 776 | mshcfg->dot11MeshConfirmTimeout)) |
922 | sta->ignore_plink_timer = true; | 777 | sta->ignore_plink_timer = true; |
923 | |||
924 | spin_unlock_bh(&sta->lock); | ||
925 | break; | 778 | break; |
926 | default: | 779 | default: |
927 | spin_unlock_bh(&sta->lock); | ||
928 | break; | 780 | break; |
929 | } | 781 | } |
930 | break; | 782 | break; |
931 | |||
932 | case NL80211_PLINK_OPN_RCVD: | 783 | case NL80211_PLINK_OPN_RCVD: |
933 | switch (event) { | 784 | switch (event) { |
934 | case OPN_RJCT: | 785 | case OPN_RJCT: |
935 | case CNF_RJCT: | 786 | case CNF_RJCT: |
936 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); | ||
937 | case CLS_ACPT: | 787 | case CLS_ACPT: |
938 | if (!reason) | 788 | mesh_plink_close(sdata, sta, event); |
939 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | 789 | action = WLAN_SP_MESH_PEERING_CLOSE; |
940 | sta->reason = reason; | ||
941 | sta->plink_state = NL80211_PLINK_HOLDING; | ||
942 | if (!mod_plink_timer(sta, | ||
943 | mshcfg->dot11MeshHoldingTimeout)) | ||
944 | sta->ignore_plink_timer = true; | ||
945 | |||
946 | llid = sta->llid; | ||
947 | spin_unlock_bh(&sta->lock); | ||
948 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
949 | sta->sta.addr, llid, plid, reason); | ||
950 | break; | 790 | break; |
951 | case OPN_ACPT: | 791 | case OPN_ACPT: |
952 | llid = sta->llid; | 792 | action = WLAN_SP_MESH_PEERING_CONFIRM; |
953 | spin_unlock_bh(&sta->lock); | ||
954 | mesh_plink_frame_tx(sdata, | ||
955 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
956 | sta->sta.addr, llid, plid, 0); | ||
957 | break; | 793 | break; |
958 | case CNF_ACPT: | 794 | case CNF_ACPT: |
959 | del_timer(&sta->plink_timer); | 795 | changed |= mesh_plink_establish(sdata, sta); |
960 | sta->plink_state = NL80211_PLINK_ESTAB; | ||
961 | spin_unlock_bh(&sta->lock); | ||
962 | changed |= mesh_plink_inc_estab_count(sdata); | ||
963 | changed |= mesh_set_ht_prot_mode(sdata); | ||
964 | changed |= mesh_set_short_slot_time(sdata); | ||
965 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | ||
966 | sta->sta.addr); | ||
967 | ieee80211_mps_sta_status_update(sta); | ||
968 | changed |= ieee80211_mps_set_sta_local_pm(sta, | ||
969 | mshcfg->power_mode); | ||
970 | break; | 796 | break; |
971 | default: | 797 | default: |
972 | spin_unlock_bh(&sta->lock); | ||
973 | break; | 798 | break; |
974 | } | 799 | } |
975 | break; | 800 | break; |
976 | |||
977 | case NL80211_PLINK_CNF_RCVD: | 801 | case NL80211_PLINK_CNF_RCVD: |
978 | switch (event) { | 802 | switch (event) { |
979 | case OPN_RJCT: | 803 | case OPN_RJCT: |
980 | case CNF_RJCT: | 804 | case CNF_RJCT: |
981 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); | ||
982 | case CLS_ACPT: | 805 | case CLS_ACPT: |
983 | if (!reason) | 806 | mesh_plink_close(sdata, sta, event); |
984 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | 807 | action = WLAN_SP_MESH_PEERING_CLOSE; |
985 | sta->reason = reason; | ||
986 | sta->plink_state = NL80211_PLINK_HOLDING; | ||
987 | if (!mod_plink_timer(sta, | ||
988 | mshcfg->dot11MeshHoldingTimeout)) | ||
989 | sta->ignore_plink_timer = true; | ||
990 | |||
991 | llid = sta->llid; | ||
992 | spin_unlock_bh(&sta->lock); | ||
993 | mesh_plink_frame_tx(sdata, | ||
994 | WLAN_SP_MESH_PEERING_CLOSE, | ||
995 | sta->sta.addr, llid, plid, reason); | ||
996 | break; | 808 | break; |
997 | case OPN_ACPT: | 809 | case OPN_ACPT: |
998 | del_timer(&sta->plink_timer); | 810 | changed |= mesh_plink_establish(sdata, sta); |
999 | sta->plink_state = NL80211_PLINK_ESTAB; | 811 | action = WLAN_SP_MESH_PEERING_CONFIRM; |
1000 | spin_unlock_bh(&sta->lock); | ||
1001 | changed |= mesh_plink_inc_estab_count(sdata); | ||
1002 | changed |= mesh_set_ht_prot_mode(sdata); | ||
1003 | changed |= mesh_set_short_slot_time(sdata); | ||
1004 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | ||
1005 | sta->sta.addr); | ||
1006 | mesh_plink_frame_tx(sdata, | ||
1007 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
1008 | sta->sta.addr, llid, plid, 0); | ||
1009 | ieee80211_mps_sta_status_update(sta); | ||
1010 | changed |= ieee80211_mps_set_sta_local_pm(sta, | ||
1011 | mshcfg->power_mode); | ||
1012 | break; | 812 | break; |
1013 | default: | 813 | default: |
1014 | spin_unlock_bh(&sta->lock); | ||
1015 | break; | 814 | break; |
1016 | } | 815 | } |
1017 | break; | 816 | break; |
1018 | |||
1019 | case NL80211_PLINK_ESTAB: | 817 | case NL80211_PLINK_ESTAB: |
1020 | switch (event) { | 818 | switch (event) { |
1021 | case CLS_ACPT: | 819 | case CLS_ACPT: |
1022 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | ||
1023 | sta->reason = reason; | ||
1024 | changed |= __mesh_plink_deactivate(sta); | 820 | changed |= __mesh_plink_deactivate(sta); |
1025 | sta->plink_state = NL80211_PLINK_HOLDING; | ||
1026 | llid = sta->llid; | ||
1027 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); | ||
1028 | spin_unlock_bh(&sta->lock); | ||
1029 | changed |= mesh_set_ht_prot_mode(sdata); | 821 | changed |= mesh_set_ht_prot_mode(sdata); |
1030 | changed |= mesh_set_short_slot_time(sdata); | 822 | changed |= mesh_set_short_slot_time(sdata); |
1031 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 823 | mesh_plink_close(sdata, sta, event); |
1032 | sta->sta.addr, llid, plid, reason); | 824 | action = WLAN_SP_MESH_PEERING_CLOSE; |
1033 | break; | 825 | break; |
1034 | case OPN_ACPT: | 826 | case OPN_ACPT: |
1035 | llid = sta->llid; | 827 | action = WLAN_SP_MESH_PEERING_CONFIRM; |
1036 | spin_unlock_bh(&sta->lock); | ||
1037 | mesh_plink_frame_tx(sdata, | ||
1038 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
1039 | sta->sta.addr, llid, plid, 0); | ||
1040 | break; | 828 | break; |
1041 | default: | 829 | default: |
1042 | spin_unlock_bh(&sta->lock); | ||
1043 | break; | 830 | break; |
1044 | } | 831 | } |
1045 | break; | 832 | break; |
@@ -1049,32 +836,271 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
1049 | if (del_timer(&sta->plink_timer)) | 836 | if (del_timer(&sta->plink_timer)) |
1050 | sta->ignore_plink_timer = 1; | 837 | sta->ignore_plink_timer = 1; |
1051 | mesh_plink_fsm_restart(sta); | 838 | mesh_plink_fsm_restart(sta); |
1052 | spin_unlock_bh(&sta->lock); | ||
1053 | break; | 839 | break; |
1054 | case OPN_ACPT: | 840 | case OPN_ACPT: |
1055 | case CNF_ACPT: | 841 | case CNF_ACPT: |
1056 | case OPN_RJCT: | 842 | case OPN_RJCT: |
1057 | case CNF_RJCT: | 843 | case CNF_RJCT: |
1058 | llid = sta->llid; | 844 | action = WLAN_SP_MESH_PEERING_CLOSE; |
1059 | reason = sta->reason; | ||
1060 | spin_unlock_bh(&sta->lock); | ||
1061 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
1062 | sta->sta.addr, llid, plid, reason); | ||
1063 | break; | 845 | break; |
1064 | default: | 846 | default: |
1065 | spin_unlock_bh(&sta->lock); | 847 | break; |
1066 | } | 848 | } |
1067 | break; | 849 | break; |
1068 | default: | 850 | default: |
1069 | /* should not get here, PLINK_BLOCKED is dealt with at the | 851 | /* should not get here, PLINK_BLOCKED is dealt with at the |
1070 | * beginning of the function | 852 | * beginning of the function |
1071 | */ | 853 | */ |
1072 | spin_unlock_bh(&sta->lock); | ||
1073 | break; | 854 | break; |
1074 | } | 855 | } |
856 | spin_unlock_bh(&sta->lock); | ||
857 | if (action) { | ||
858 | mesh_plink_frame_tx(sdata, action, sta->sta.addr, | ||
859 | sta->llid, sta->plid, sta->reason); | ||
860 | |||
861 | /* also send confirm in open case */ | ||
862 | if (action == WLAN_SP_MESH_PEERING_OPEN) { | ||
863 | mesh_plink_frame_tx(sdata, | ||
864 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
865 | sta->sta.addr, sta->llid, | ||
866 | sta->plid, 0); | ||
867 | } | ||
868 | } | ||
869 | |||
870 | return changed; | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * mesh_plink_get_event - get correct MPM event | ||
875 | * | ||
876 | * @sdata: interface | ||
877 | * @sta: peer, leave NULL if processing a frame from a new suitable peer | ||
878 | * @elems: peering management IEs | ||
879 | * @ftype: frame type | ||
880 | * @llid: peer's peer link ID | ||
881 | * @plid: peer's local link ID | ||
882 | * | ||
883 | * Return: new peering event for @sta, but PLINK_UNDEFINED should be treated as | ||
884 | * an error. | ||
885 | */ | ||
886 | static enum plink_event | ||
887 | mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, | ||
888 | struct sta_info *sta, | ||
889 | struct ieee802_11_elems *elems, | ||
890 | enum ieee80211_self_protected_actioncode ftype, | ||
891 | u16 llid, u16 plid) | ||
892 | { | ||
893 | enum plink_event event = PLINK_UNDEFINED; | ||
894 | u8 ie_len = elems->peering_len; | ||
895 | bool matches_local; | ||
896 | |||
897 | matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE || | ||
898 | mesh_matches_local(sdata, elems)); | ||
899 | |||
900 | /* deny open request from non-matching peer */ | ||
901 | if (!matches_local && !sta) { | ||
902 | event = OPN_RJCT; | ||
903 | goto out; | ||
904 | } | ||
905 | |||
906 | if (!sta) { | ||
907 | if (ftype != WLAN_SP_MESH_PEERING_OPEN) { | ||
908 | mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n"); | ||
909 | goto out; | ||
910 | } | ||
911 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ | ||
912 | if (!mesh_plink_free_count(sdata)) { | ||
913 | mpl_dbg(sdata, "Mesh plink error: no more free plinks\n"); | ||
914 | goto out; | ||
915 | } | ||
916 | } else { | ||
917 | if (!test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
918 | mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n"); | ||
919 | goto out; | ||
920 | } | ||
921 | if (sta->plink_state == NL80211_PLINK_BLOCKED) | ||
922 | goto out; | ||
923 | } | ||
924 | |||
925 | /* new matching peer */ | ||
926 | if (!sta) { | ||
927 | event = OPN_ACPT; | ||
928 | goto out; | ||
929 | } | ||
930 | |||
931 | switch (ftype) { | ||
932 | case WLAN_SP_MESH_PEERING_OPEN: | ||
933 | if (!matches_local) | ||
934 | event = OPN_RJCT; | ||
935 | if (!mesh_plink_free_count(sdata) || | ||
936 | (sta->plid && sta->plid != plid)) | ||
937 | event = OPN_IGNR; | ||
938 | else | ||
939 | event = OPN_ACPT; | ||
940 | break; | ||
941 | case WLAN_SP_MESH_PEERING_CONFIRM: | ||
942 | if (!matches_local) | ||
943 | event = CNF_RJCT; | ||
944 | if (!mesh_plink_free_count(sdata) || | ||
945 | (sta->llid != llid || sta->plid != plid)) | ||
946 | event = CNF_IGNR; | ||
947 | else | ||
948 | event = CNF_ACPT; | ||
949 | break; | ||
950 | case WLAN_SP_MESH_PEERING_CLOSE: | ||
951 | if (sta->plink_state == NL80211_PLINK_ESTAB) | ||
952 | /* Do not check for llid or plid. This does not | ||
953 | * follow the standard but since multiple plinks | ||
954 | * per sta are not supported, it is necessary in | ||
955 | * order to avoid a livelock when MP A sees an | ||
956 | * establish peer link to MP B but MP B does not | ||
957 | * see it. This can be caused by a timeout in | ||
958 | * B's peer link establishment or B beign | ||
959 | * restarted. | ||
960 | */ | ||
961 | event = CLS_ACPT; | ||
962 | else if (sta->plid != plid) | ||
963 | event = CLS_IGNR; | ||
964 | else if (ie_len == 8 && sta->llid != llid) | ||
965 | event = CLS_IGNR; | ||
966 | else | ||
967 | event = CLS_ACPT; | ||
968 | break; | ||
969 | default: | ||
970 | mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n"); | ||
971 | break; | ||
972 | } | ||
973 | |||
974 | out: | ||
975 | return event; | ||
976 | } | ||
1075 | 977 | ||
978 | static void | ||
979 | mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, | ||
980 | struct ieee80211_mgmt *mgmt, | ||
981 | struct ieee802_11_elems *elems) | ||
982 | { | ||
983 | |||
984 | struct sta_info *sta; | ||
985 | enum plink_event event; | ||
986 | enum ieee80211_self_protected_actioncode ftype; | ||
987 | u32 changed = 0; | ||
988 | u8 ie_len = elems->peering_len; | ||
989 | __le16 _plid, _llid; | ||
990 | u16 plid, llid = 0; | ||
991 | |||
992 | if (!elems->peering) { | ||
993 | mpl_dbg(sdata, | ||
994 | "Mesh plink: missing necessary peer link ie\n"); | ||
995 | return; | ||
996 | } | ||
997 | |||
998 | if (elems->rsn_len && | ||
999 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | ||
1000 | mpl_dbg(sdata, | ||
1001 | "Mesh plink: can't establish link with secure peer\n"); | ||
1002 | return; | ||
1003 | } | ||
1004 | |||
1005 | ftype = mgmt->u.action.u.self_prot.action_code; | ||
1006 | if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || | ||
1007 | (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || | ||
1008 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 | ||
1009 | && ie_len != 8)) { | ||
1010 | mpl_dbg(sdata, | ||
1011 | "Mesh plink: incorrect plink ie length %d %d\n", | ||
1012 | ftype, ie_len); | ||
1013 | return; | ||
1014 | } | ||
1015 | |||
1016 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | ||
1017 | (!elems->mesh_id || !elems->mesh_config)) { | ||
1018 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); | ||
1019 | return; | ||
1020 | } | ||
1021 | /* Note the lines below are correct, the llid in the frame is the plid | ||
1022 | * from the point of view of this host. | ||
1023 | */ | ||
1024 | memcpy(&_plid, PLINK_GET_LLID(elems->peering), sizeof(__le16)); | ||
1025 | plid = le16_to_cpu(_plid); | ||
1026 | if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || | ||
1027 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) { | ||
1028 | memcpy(&_llid, PLINK_GET_PLID(elems->peering), sizeof(__le16)); | ||
1029 | llid = le16_to_cpu(_llid); | ||
1030 | } | ||
1031 | |||
1032 | /* WARNING: Only for sta pointer, is dropped & re-acquired */ | ||
1033 | rcu_read_lock(); | ||
1034 | |||
1035 | sta = sta_info_get(sdata, mgmt->sa); | ||
1036 | |||
1037 | if (ftype == WLAN_SP_MESH_PEERING_OPEN && | ||
1038 | !rssi_threshold_check(sdata, sta)) { | ||
1039 | mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n", | ||
1040 | mgmt->sa); | ||
1041 | goto unlock_rcu; | ||
1042 | } | ||
1043 | |||
1044 | /* Now we will figure out the appropriate event... */ | ||
1045 | event = mesh_plink_get_event(sdata, sta, elems, ftype, llid, plid); | ||
1046 | |||
1047 | if (event == OPN_ACPT) { | ||
1048 | rcu_read_unlock(); | ||
1049 | /* allocate sta entry if necessary and update info */ | ||
1050 | sta = mesh_sta_info_get(sdata, mgmt->sa, elems); | ||
1051 | if (!sta) { | ||
1052 | mpl_dbg(sdata, "Mesh plink: failed to init peer!\n"); | ||
1053 | goto unlock_rcu; | ||
1054 | } | ||
1055 | sta->plid = plid; | ||
1056 | } else if (!sta && event == OPN_RJCT) { | ||
1057 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
1058 | mgmt->sa, 0, plid, | ||
1059 | WLAN_REASON_MESH_CONFIG); | ||
1060 | goto unlock_rcu; | ||
1061 | } else if (!sta || event == PLINK_UNDEFINED) { | ||
1062 | /* something went wrong */ | ||
1063 | goto unlock_rcu; | ||
1064 | } | ||
1065 | |||
1066 | changed |= mesh_plink_fsm(sdata, sta, event); | ||
1067 | |||
1068 | unlock_rcu: | ||
1076 | rcu_read_unlock(); | 1069 | rcu_read_unlock(); |
1077 | 1070 | ||
1078 | if (changed) | 1071 | if (changed) |
1079 | ieee80211_mbss_info_change_notify(sdata, changed); | 1072 | ieee80211_mbss_info_change_notify(sdata, changed); |
1080 | } | 1073 | } |
1074 | |||
1075 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | ||
1076 | struct ieee80211_mgmt *mgmt, size_t len, | ||
1077 | struct ieee80211_rx_status *rx_status) | ||
1078 | { | ||
1079 | struct ieee802_11_elems elems; | ||
1080 | size_t baselen; | ||
1081 | u8 *baseaddr; | ||
1082 | |||
1083 | /* need action_code, aux */ | ||
1084 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | ||
1085 | return; | ||
1086 | |||
1087 | if (sdata->u.mesh.user_mpm) | ||
1088 | /* userspace must register for these */ | ||
1089 | return; | ||
1090 | |||
1091 | if (is_multicast_ether_addr(mgmt->da)) { | ||
1092 | mpl_dbg(sdata, | ||
1093 | "Mesh plink: ignore frame from multicast address\n"); | ||
1094 | return; | ||
1095 | } | ||
1096 | |||
1097 | baseaddr = mgmt->u.action.u.self_prot.variable; | ||
1098 | baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; | ||
1099 | if (mgmt->u.action.u.self_prot.action_code == | ||
1100 | WLAN_SP_MESH_PEERING_CONFIRM) { | ||
1101 | baseaddr += 4; | ||
1102 | baselen += 4; | ||
1103 | } | ||
1104 | ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems); | ||
1105 | mesh_process_plink_frame(sdata, mgmt, &elems); | ||
1106 | } | ||
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c index 0f79b78b5e86..2802f9d9279d 100644 --- a/net/mac80211/mesh_ps.c +++ b/net/mac80211/mesh_ps.c | |||
@@ -576,10 +576,9 @@ void ieee80211_mps_frame_release(struct sta_info *sta, | |||
576 | int ac, buffer_local = 0; | 576 | int ac, buffer_local = 0; |
577 | bool has_buffered = false; | 577 | bool has_buffered = false; |
578 | 578 | ||
579 | /* TIM map only for LLID <= IEEE80211_MAX_AID */ | ||
580 | if (sta->plink_state == NL80211_PLINK_ESTAB) | 579 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
581 | has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, | 580 | has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, |
582 | le16_to_cpu(sta->llid) % IEEE80211_MAX_AID); | 581 | sta->llid); |
583 | 582 | ||
584 | if (has_buffered) | 583 | if (has_buffered) |
585 | mps_dbg(sta->sdata, "%pM indicates buffered frames\n", | 584 | mps_dbg(sta->sdata, "%pM indicates buffered frames\n", |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 05a256b38e24..d1cf2d553499 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -92,12 +92,20 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
92 | if (stype != IEEE80211_STYPE_BEACON) | 92 | if (stype != IEEE80211_STYPE_BEACON) |
93 | return; | 93 | return; |
94 | 94 | ||
95 | /* The current tsf is a first approximation for the timestamp | 95 | /* |
96 | * for the received beacon. Further down we try to get a | 96 | * Get time when timestamp field was received. If we don't |
97 | * better value from the rx_status->mactime field if | 97 | * have rx timestamps, then use current tsf as an approximation. |
98 | * available. Also we have to call drv_get_tsf() before | 98 | * drv_get_tsf() must be called before entering the rcu-read |
99 | * entering the rcu-read section.*/ | 99 | * section. |
100 | t_r = drv_get_tsf(local, sdata); | 100 | */ |
101 | if (ieee80211_have_rx_timestamp(rx_status)) | ||
102 | t_r = ieee80211_calculate_rx_timestamp(local, rx_status, | ||
103 | 24 + 12 + | ||
104 | elems->total_len + | ||
105 | FCS_LEN, | ||
106 | 24); | ||
107 | else | ||
108 | t_r = drv_get_tsf(local, sdata); | ||
101 | 109 | ||
102 | rcu_read_lock(); | 110 | rcu_read_lock(); |
103 | sta = sta_info_get(sdata, mgmt->sa); | 111 | sta = sta_info_get(sdata, mgmt->sa); |
@@ -117,14 +125,6 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
117 | goto no_sync; | 125 | goto no_sync; |
118 | } | 126 | } |
119 | 127 | ||
120 | if (ieee80211_have_rx_timestamp(rx_status)) | ||
121 | /* time when timestamp field was received */ | ||
122 | t_r = ieee80211_calculate_rx_timestamp(local, rx_status, | ||
123 | 24 + 12 + | ||
124 | elems->total_len + | ||
125 | FCS_LEN, | ||
126 | 24); | ||
127 | |||
128 | /* Timing offset calculation (see 13.13.2.2.2) */ | 128 | /* Timing offset calculation (see 13.13.2.2.2) */ |
129 | t_t = le64_to_cpu(mgmt->u.beacon.timestamp); | 129 | t_t = le64_to_cpu(mgmt->u.beacon.timestamp); |
130 | sta->t_offset = t_t - t_r; | 130 | sta->t_offset = t_t - t_r; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b3a3ce316656..900ead344f5b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -330,6 +330,16 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
330 | if (WARN_ON_ONCE(!sta)) | 330 | if (WARN_ON_ONCE(!sta)) |
331 | return -EINVAL; | 331 | return -EINVAL; |
332 | 332 | ||
333 | /* | ||
334 | * if bss configuration changed store the new one - | ||
335 | * this may be applicable even if channel is identical | ||
336 | */ | ||
337 | ht_opmode = le16_to_cpu(ht_oper->operation_mode); | ||
338 | if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | ||
339 | *changed |= BSS_CHANGED_HT; | ||
340 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | ||
341 | } | ||
342 | |||
333 | chan = sdata->vif.bss_conf.chandef.chan; | 343 | chan = sdata->vif.bss_conf.chandef.chan; |
334 | sband = local->hw.wiphy->bands[chan->band]; | 344 | sband = local->hw.wiphy->bands[chan->band]; |
335 | 345 | ||
@@ -416,14 +426,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
416 | IEEE80211_RC_BW_CHANGED); | 426 | IEEE80211_RC_BW_CHANGED); |
417 | } | 427 | } |
418 | 428 | ||
419 | ht_opmode = le16_to_cpu(ht_oper->operation_mode); | ||
420 | |||
421 | /* if bss configuration changed store the new one */ | ||
422 | if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | ||
423 | *changed |= BSS_CHANGED_HT; | ||
424 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | ||
425 | } | ||
426 | |||
427 | return 0; | 429 | return 0; |
428 | } | 430 | } |
429 | 431 | ||
@@ -714,7 +716,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
714 | } | 716 | } |
715 | 717 | ||
716 | /* if present, add any custom IEs that go before HT */ | 718 | /* if present, add any custom IEs that go before HT */ |
717 | if (assoc_data->ie_len && assoc_data->ie) { | 719 | if (assoc_data->ie_len) { |
718 | static const u8 before_ht[] = { | 720 | static const u8 before_ht[] = { |
719 | WLAN_EID_SSID, | 721 | WLAN_EID_SSID, |
720 | WLAN_EID_SUPP_RATES, | 722 | WLAN_EID_SUPP_RATES, |
@@ -748,7 +750,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
748 | &assoc_data->ap_vht_cap); | 750 | &assoc_data->ap_vht_cap); |
749 | 751 | ||
750 | /* if present, add any custom non-vendor IEs that go after HT */ | 752 | /* if present, add any custom non-vendor IEs that go after HT */ |
751 | if (assoc_data->ie_len && assoc_data->ie) { | 753 | if (assoc_data->ie_len) { |
752 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, | 754 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, |
753 | assoc_data->ie_len, | 755 | assoc_data->ie_len, |
754 | offset); | 756 | offset); |
@@ -779,7 +781,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
779 | } | 781 | } |
780 | 782 | ||
781 | /* add any remaining custom (i.e. vendor specific here) IEs */ | 783 | /* add any remaining custom (i.e. vendor specific here) IEs */ |
782 | if (assoc_data->ie_len && assoc_data->ie) { | 784 | if (assoc_data->ie_len) { |
783 | noffset = assoc_data->ie_len; | 785 | noffset = assoc_data->ie_len; |
784 | pos = skb_put(skb, noffset - offset); | 786 | pos = skb_put(skb, noffset - offset); |
785 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | 787 | memcpy(pos, assoc_data->ie + offset, noffset - offset); |
@@ -886,8 +888,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
886 | if (!ifmgd->associated) | 888 | if (!ifmgd->associated) |
887 | goto out; | 889 | goto out; |
888 | 890 | ||
889 | ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef, | 891 | ret = ieee80211_vif_change_channel(sdata, &changed); |
890 | &changed); | ||
891 | if (ret) { | 892 | if (ret) { |
892 | sdata_info(sdata, | 893 | sdata_info(sdata, |
893 | "vif channel switch failed, disconnecting\n"); | 894 | "vif channel switch failed, disconnecting\n"); |
@@ -897,7 +898,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
897 | } | 898 | } |
898 | 899 | ||
899 | if (!local->use_chanctx) { | 900 | if (!local->use_chanctx) { |
900 | local->_oper_chandef = local->csa_chandef; | 901 | local->_oper_chandef = sdata->csa_chandef; |
901 | /* Call "hw_config" only if doing sw channel switch. | 902 | /* Call "hw_config" only if doing sw channel switch. |
902 | * Otherwise update the channel directly | 903 | * Otherwise update the channel directly |
903 | */ | 904 | */ |
@@ -908,7 +909,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
908 | } | 909 | } |
909 | 910 | ||
910 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 911 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
911 | ifmgd->associated->channel = local->csa_chandef.chan; | 912 | ifmgd->associated->channel = sdata->csa_chandef.chan; |
912 | 913 | ||
913 | /* XXX: wait for a beacon first? */ | 914 | /* XXX: wait for a beacon first? */ |
914 | ieee80211_wake_queues_by_reason(&local->hw, | 915 | ieee80211_wake_queues_by_reason(&local->hw, |
@@ -1035,7 +1036,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1035 | } | 1036 | } |
1036 | mutex_unlock(&local->chanctx_mtx); | 1037 | mutex_unlock(&local->chanctx_mtx); |
1037 | 1038 | ||
1038 | local->csa_chandef = csa_ie.chandef; | 1039 | sdata->csa_chandef = csa_ie.chandef; |
1039 | 1040 | ||
1040 | if (csa_ie.mode) | 1041 | if (csa_ie.mode) |
1041 | ieee80211_stop_queues_by_reason(&local->hw, | 1042 | ieee80211_stop_queues_by_reason(&local->hw, |
@@ -1398,10 +1399,12 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work) | |||
1398 | struct ieee80211_sub_if_data *sdata = | 1399 | struct ieee80211_sub_if_data *sdata = |
1399 | container_of(delayed_work, struct ieee80211_sub_if_data, | 1400 | container_of(delayed_work, struct ieee80211_sub_if_data, |
1400 | dfs_cac_timer_work); | 1401 | dfs_cac_timer_work); |
1402 | struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; | ||
1401 | 1403 | ||
1402 | ieee80211_vif_release_channel(sdata); | 1404 | ieee80211_vif_release_channel(sdata); |
1403 | 1405 | cfg80211_cac_event(sdata->dev, &chandef, | |
1404 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); | 1406 | NL80211_RADAR_CAC_FINISHED, |
1407 | GFP_KERNEL); | ||
1405 | } | 1408 | } |
1406 | 1409 | ||
1407 | /* MLME */ | 1410 | /* MLME */ |
@@ -1745,6 +1748,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1745 | 1748 | ||
1746 | ifmgd->flags = 0; | 1749 | ifmgd->flags = 0; |
1747 | ieee80211_vif_release_channel(sdata); | 1750 | ieee80211_vif_release_channel(sdata); |
1751 | |||
1752 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
1748 | } | 1753 | } |
1749 | 1754 | ||
1750 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1755 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -4191,6 +4196,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4191 | 4196 | ||
4192 | sdata->control_port_protocol = req->crypto.control_port_ethertype; | 4197 | sdata->control_port_protocol = req->crypto.control_port_ethertype; |
4193 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; | 4198 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; |
4199 | sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto, | ||
4200 | sdata->vif.type); | ||
4194 | 4201 | ||
4195 | /* kick off associate process */ | 4202 | /* kick off associate process */ |
4196 | 4203 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 505bc0dea074..b95e16c07081 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -54,6 +54,8 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
54 | struct ieee80211_supported_band *sband; | 54 | struct ieee80211_supported_band *sband; |
55 | struct ieee80211_chanctx_conf *chanctx_conf; | 55 | struct ieee80211_chanctx_conf *chanctx_conf; |
56 | 56 | ||
57 | ieee80211_sta_set_rx_nss(sta); | ||
58 | |||
57 | if (!ref) | 59 | if (!ref) |
58 | return; | 60 | return; |
59 | 61 | ||
@@ -67,8 +69,6 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
67 | 69 | ||
68 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; | 70 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; |
69 | 71 | ||
70 | ieee80211_sta_set_rx_nss(sta); | ||
71 | |||
72 | ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, | 72 | ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, |
73 | priv_sta); | 73 | priv_sta); |
74 | rcu_read_unlock(); | 74 | rcu_read_unlock(); |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 7fa1b36e6202..d2f19f7e7091 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -422,10 +422,9 @@ init_sample_table(struct minstrel_sta_info *mi) | |||
422 | memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); | 422 | memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); |
423 | 423 | ||
424 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | 424 | for (col = 0; col < SAMPLE_COLUMNS; col++) { |
425 | prandom_bytes(rnd, sizeof(rnd)); | ||
425 | for (i = 0; i < mi->n_rates; i++) { | 426 | for (i = 0; i < mi->n_rates; i++) { |
426 | get_random_bytes(rnd, sizeof(rnd)); | ||
427 | new_idx = (i + rnd[i & 7]) % mi->n_rates; | 427 | new_idx = (i + rnd[i & 7]) % mi->n_rates; |
428 | |||
429 | while (SAMPLE_TBL(mi, new_idx, col) != 0xff) | 428 | while (SAMPLE_TBL(mi, new_idx, col) != 0xff) |
430 | new_idx = (new_idx + 1) % mi->n_rates; | 429 | new_idx = (new_idx + 1) % mi->n_rates; |
431 | 430 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 4096ff6cc24f..d2ed18d82fe1 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -135,7 +135,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); | |||
135 | static int | 135 | static int |
136 | minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) | 136 | minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) |
137 | { | 137 | { |
138 | return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1, | 138 | return GROUP_IDX((rate->idx / 8) + 1, |
139 | !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), | 139 | !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), |
140 | !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); | 140 | !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); |
141 | } | 141 | } |
@@ -148,7 +148,7 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
148 | 148 | ||
149 | if (rate->flags & IEEE80211_TX_RC_MCS) { | 149 | if (rate->flags & IEEE80211_TX_RC_MCS) { |
150 | group = minstrel_ht_get_group_idx(rate); | 150 | group = minstrel_ht_get_group_idx(rate); |
151 | idx = rate->idx % MCS_GROUP_RATES; | 151 | idx = rate->idx % 8; |
152 | } else { | 152 | } else { |
153 | group = MINSTREL_CCK_GROUP; | 153 | group = MINSTREL_CCK_GROUP; |
154 | 154 | ||
@@ -637,8 +637,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
637 | idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; | 637 | idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; |
638 | flags = 0; | 638 | flags = 0; |
639 | } else { | 639 | } else { |
640 | idx = index % MCS_GROUP_RATES + | 640 | idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8; |
641 | (group->streams - 1) * MCS_GROUP_RATES; | ||
642 | flags = IEEE80211_TX_RC_MCS | group->flags; | 641 | flags = IEEE80211_TX_RC_MCS | group->flags; |
643 | } | 642 | } |
644 | 643 | ||
@@ -702,12 +701,16 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
702 | if (!mi->sample_tries) | 701 | if (!mi->sample_tries) |
703 | return -1; | 702 | return -1; |
704 | 703 | ||
705 | mg = &mi->groups[mi->sample_group]; | 704 | sample_group = mi->sample_group; |
705 | mg = &mi->groups[sample_group]; | ||
706 | sample_idx = sample_table[mg->column][mg->index]; | 706 | sample_idx = sample_table[mg->column][mg->index]; |
707 | minstrel_next_sample_idx(mi); | ||
708 | |||
709 | if (!(mg->supported & BIT(sample_idx))) | ||
710 | return -1; | ||
711 | |||
707 | mr = &mg->rates[sample_idx]; | 712 | mr = &mg->rates[sample_idx]; |
708 | sample_group = mi->sample_group; | ||
709 | sample_idx += sample_group * MCS_GROUP_RATES; | 713 | sample_idx += sample_group * MCS_GROUP_RATES; |
710 | minstrel_next_sample_idx(mi); | ||
711 | 714 | ||
712 | /* | 715 | /* |
713 | * Sampling might add some overhead (RTS, no aggregation) | 716 | * Sampling might add some overhead (RTS, no aggregation) |
@@ -818,7 +821,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
818 | } | 821 | } |
819 | 822 | ||
820 | rate->idx = sample_idx % MCS_GROUP_RATES + | 823 | rate->idx = sample_idx % MCS_GROUP_RATES + |
821 | (sample_group->streams - 1) * MCS_GROUP_RATES; | 824 | (sample_group->streams - 1) * 8; |
822 | rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags; | 825 | rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags; |
823 | } | 826 | } |
824 | 827 | ||
@@ -1053,10 +1056,9 @@ init_sample_table(void) | |||
1053 | 1056 | ||
1054 | memset(sample_table, 0xff, sizeof(sample_table)); | 1057 | memset(sample_table, 0xff, sizeof(sample_table)); |
1055 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | 1058 | for (col = 0; col < SAMPLE_COLUMNS; col++) { |
1059 | prandom_bytes(rnd, sizeof(rnd)); | ||
1056 | for (i = 0; i < MCS_GROUP_RATES; i++) { | 1060 | for (i = 0; i < MCS_GROUP_RATES; i++) { |
1057 | get_random_bytes(rnd, sizeof(rnd)); | ||
1058 | new_idx = (i + rnd[i]) % MCS_GROUP_RATES; | 1061 | new_idx = (i + rnd[i]) % MCS_GROUP_RATES; |
1059 | |||
1060 | while (sample_table[col][new_idx] != 0xff) | 1062 | while (sample_table[col][new_idx] != 0xff) |
1061 | new_idx = (new_idx + 1) % MCS_GROUP_RATES; | 1063 | new_idx = (new_idx + 1) % MCS_GROUP_RATES; |
1062 | 1064 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index df44a5ad8270..3e7d793de0c3 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c | |||
@@ -54,8 +54,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) | |||
54 | int r = bitrates[j % 4]; | 54 | int r = bitrates[j % 4]; |
55 | p += sprintf(p, " %2u.%1uM", r / 10, r % 10); | 55 | p += sprintf(p, " %2u.%1uM", r / 10, r % 10); |
56 | } else { | 56 | } else { |
57 | p += sprintf(p, " MCS%-2u", (mg->streams - 1) * | 57 | p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j); |
58 | MCS_GROUP_RATES + j); | ||
59 | } | 58 | } |
60 | 59 | ||
61 | tp = mr->cur_tp / 10; | 60 | tp = mr->cur_tp / 10; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2b0debb0422b..2dfa75522733 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -638,6 +638,27 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
638 | return le16_to_cpu(mmie->key_id); | 638 | return le16_to_cpu(mmie->key_id); |
639 | } | 639 | } |
640 | 640 | ||
641 | static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, | ||
642 | struct sk_buff *skb) | ||
643 | { | ||
644 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
645 | __le16 fc; | ||
646 | int hdrlen; | ||
647 | u8 keyid; | ||
648 | |||
649 | fc = hdr->frame_control; | ||
650 | hdrlen = ieee80211_hdrlen(fc); | ||
651 | |||
652 | if (skb->len < hdrlen + cs->hdr_len) | ||
653 | return -EINVAL; | ||
654 | |||
655 | skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1); | ||
656 | keyid &= cs->key_idx_mask; | ||
657 | keyid >>= cs->key_idx_shift; | ||
658 | |||
659 | return keyid; | ||
660 | } | ||
661 | |||
641 | static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 662 | static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
642 | { | 663 | { |
643 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 664 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
@@ -729,9 +750,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
729 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 750 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
730 | 751 | ||
731 | while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 752 | while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
732 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, | 753 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
733 | tid_agg_rx->ssn) % | ||
734 | tid_agg_rx->buf_size; | ||
735 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 754 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
736 | frames); | 755 | frames); |
737 | } | 756 | } |
@@ -757,8 +776,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
757 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 776 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
758 | 777 | ||
759 | /* release the buffer until next missing frame */ | 778 | /* release the buffer until next missing frame */ |
760 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, | 779 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
761 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
762 | if (!tid_agg_rx->reorder_buf[index] && | 780 | if (!tid_agg_rx->reorder_buf[index] && |
763 | tid_agg_rx->stored_mpdu_num) { | 781 | tid_agg_rx->stored_mpdu_num) { |
764 | /* | 782 | /* |
@@ -793,15 +811,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
793 | } else while (tid_agg_rx->reorder_buf[index]) { | 811 | } else while (tid_agg_rx->reorder_buf[index]) { |
794 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 812 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
795 | frames); | 813 | frames); |
796 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, | 814 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
797 | tid_agg_rx->ssn) % | ||
798 | tid_agg_rx->buf_size; | ||
799 | } | 815 | } |
800 | 816 | ||
801 | if (tid_agg_rx->stored_mpdu_num) { | 817 | if (tid_agg_rx->stored_mpdu_num) { |
802 | j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, | 818 | j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
803 | tid_agg_rx->ssn) % | ||
804 | tid_agg_rx->buf_size; | ||
805 | 819 | ||
806 | for (; j != (index - 1) % tid_agg_rx->buf_size; | 820 | for (; j != (index - 1) % tid_agg_rx->buf_size; |
807 | j = (j + 1) % tid_agg_rx->buf_size) { | 821 | j = (j + 1) % tid_agg_rx->buf_size) { |
@@ -861,8 +875,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
861 | 875 | ||
862 | /* Now the new frame is always in the range of the reordering buffer */ | 876 | /* Now the new frame is always in the range of the reordering buffer */ |
863 | 877 | ||
864 | index = ieee80211_sn_sub(mpdu_seq_num, | 878 | index = mpdu_seq_num % tid_agg_rx->buf_size; |
865 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
866 | 879 | ||
867 | /* check if we already stored this frame */ | 880 | /* check if we already stored this frame */ |
868 | if (tid_agg_rx->reorder_buf[index]) { | 881 | if (tid_agg_rx->reorder_buf[index]) { |
@@ -1369,6 +1382,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1369 | struct ieee80211_key *sta_ptk = NULL; | 1382 | struct ieee80211_key *sta_ptk = NULL; |
1370 | int mmie_keyidx = -1; | 1383 | int mmie_keyidx = -1; |
1371 | __le16 fc; | 1384 | __le16 fc; |
1385 | const struct ieee80211_cipher_scheme *cs = NULL; | ||
1372 | 1386 | ||
1373 | /* | 1387 | /* |
1374 | * Key selection 101 | 1388 | * Key selection 101 |
@@ -1406,11 +1420,19 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1406 | 1420 | ||
1407 | /* start without a key */ | 1421 | /* start without a key */ |
1408 | rx->key = NULL; | 1422 | rx->key = NULL; |
1423 | fc = hdr->frame_control; | ||
1409 | 1424 | ||
1410 | if (rx->sta) | 1425 | if (rx->sta) { |
1411 | sta_ptk = rcu_dereference(rx->sta->ptk); | 1426 | int keyid = rx->sta->ptk_idx; |
1412 | 1427 | ||
1413 | fc = hdr->frame_control; | 1428 | if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) { |
1429 | cs = rx->sta->cipher_scheme; | ||
1430 | keyid = iwl80211_get_cs_keyid(cs, rx->skb); | ||
1431 | if (unlikely(keyid < 0)) | ||
1432 | return RX_DROP_UNUSABLE; | ||
1433 | } | ||
1434 | sta_ptk = rcu_dereference(rx->sta->ptk[keyid]); | ||
1435 | } | ||
1414 | 1436 | ||
1415 | if (!ieee80211_has_protected(fc)) | 1437 | if (!ieee80211_has_protected(fc)) |
1416 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | 1438 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); |
@@ -1472,6 +1494,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1472 | return RX_CONTINUE; | 1494 | return RX_CONTINUE; |
1473 | } else { | 1495 | } else { |
1474 | u8 keyid; | 1496 | u8 keyid; |
1497 | |||
1475 | /* | 1498 | /* |
1476 | * The device doesn't give us the IV so we won't be | 1499 | * The device doesn't give us the IV so we won't be |
1477 | * able to look up the key. That's ok though, we | 1500 | * able to look up the key. That's ok though, we |
@@ -1487,15 +1510,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1487 | 1510 | ||
1488 | hdrlen = ieee80211_hdrlen(fc); | 1511 | hdrlen = ieee80211_hdrlen(fc); |
1489 | 1512 | ||
1490 | if (rx->skb->len < 8 + hdrlen) | 1513 | if (cs) { |
1491 | return RX_DROP_UNUSABLE; /* TODO: count this? */ | 1514 | keyidx = iwl80211_get_cs_keyid(cs, rx->skb); |
1492 | 1515 | ||
1493 | /* | 1516 | if (unlikely(keyidx < 0)) |
1494 | * no need to call ieee80211_wep_get_keyidx, | 1517 | return RX_DROP_UNUSABLE; |
1495 | * it verifies a bunch of things we've done already | 1518 | } else { |
1496 | */ | 1519 | if (rx->skb->len < 8 + hdrlen) |
1497 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | 1520 | return RX_DROP_UNUSABLE; /* TODO: count this? */ |
1498 | keyidx = keyid >> 6; | 1521 | /* |
1522 | * no need to call ieee80211_wep_get_keyidx, | ||
1523 | * it verifies a bunch of things we've done already | ||
1524 | */ | ||
1525 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | ||
1526 | keyidx = keyid >> 6; | ||
1527 | } | ||
1499 | 1528 | ||
1500 | /* check per-station GTK first, if multicast packet */ | 1529 | /* check per-station GTK first, if multicast packet */ |
1501 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) | 1530 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) |
@@ -1543,11 +1572,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
1543 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | 1572 | result = ieee80211_crypto_aes_cmac_decrypt(rx); |
1544 | break; | 1573 | break; |
1545 | default: | 1574 | default: |
1546 | /* | 1575 | result = ieee80211_crypto_hw_decrypt(rx); |
1547 | * We can reach here only with HW-only algorithms | ||
1548 | * but why didn't it decrypt the frame?! | ||
1549 | */ | ||
1550 | return RX_DROP_UNUSABLE; | ||
1551 | } | 1576 | } |
1552 | 1577 | ||
1553 | /* the hdr variable is invalid after the decrypt handlers */ | 1578 | /* the hdr variable is invalid after the decrypt handlers */ |
@@ -2057,7 +2082,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2057 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2082 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
2058 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2083 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
2059 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 2084 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
2060 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); | ||
2061 | u16 q, hdrlen; | 2085 | u16 q, hdrlen; |
2062 | 2086 | ||
2063 | hdr = (struct ieee80211_hdr *) skb->data; | 2087 | hdr = (struct ieee80211_hdr *) skb->data; |
@@ -2165,7 +2189,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2165 | } else { | 2189 | } else { |
2166 | /* unable to resolve next hop */ | 2190 | /* unable to resolve next hop */ |
2167 | mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, | 2191 | mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, |
2168 | fwd_hdr->addr3, 0, reason, fwd_hdr->addr2); | 2192 | fwd_hdr->addr3, 0, |
2193 | WLAN_REASON_MESH_PATH_NOFORWARD, | ||
2194 | fwd_hdr->addr2); | ||
2169 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | 2195 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); |
2170 | kfree_skb(fwd_skb); | 2196 | kfree_skb(fwd_skb); |
2171 | return RX_DROP_MONITOR; | 2197 | return RX_DROP_MONITOR; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index bcc4833d7542..4d73c46df862 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -526,7 +526,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
526 | ieee80211_hw_config(local, 0); | 526 | ieee80211_hw_config(local, 0); |
527 | 527 | ||
528 | if ((req->channels[0]->flags & | 528 | if ((req->channels[0]->flags & |
529 | IEEE80211_CHAN_PASSIVE_SCAN) || | 529 | IEEE80211_CHAN_NO_IR) || |
530 | !local->scan_req->n_ssids) { | 530 | !local->scan_req->n_ssids) { |
531 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 531 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
532 | } else { | 532 | } else { |
@@ -572,7 +572,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | |||
572 | * TODO: channel switching also consumes quite some time, | 572 | * TODO: channel switching also consumes quite some time, |
573 | * add that delay as well to get a better estimation | 573 | * add that delay as well to get a better estimation |
574 | */ | 574 | */ |
575 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 575 | if (chan->flags & IEEE80211_CHAN_NO_IR) |
576 | return IEEE80211_PASSIVE_CHANNEL_TIME; | 576 | return IEEE80211_PASSIVE_CHANNEL_TIME; |
577 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | 577 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; |
578 | } | 578 | } |
@@ -696,7 +696,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
696 | * | 696 | * |
697 | * In any case, it is not necessary for a passive scan. | 697 | * In any case, it is not necessary for a passive scan. |
698 | */ | 698 | */ |
699 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | 699 | if (chan->flags & IEEE80211_CHAN_NO_IR || |
700 | !local->scan_req->n_ssids) { | 700 | !local->scan_req->n_ssids) { |
701 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 701 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
702 | local->next_scan_state = SCAN_DECISION; | 702 | local->next_scan_state = SCAN_DECISION; |
@@ -881,7 +881,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
881 | struct ieee80211_channel *tmp_ch = | 881 | struct ieee80211_channel *tmp_ch = |
882 | &local->hw.wiphy->bands[band]->channels[i]; | 882 | &local->hw.wiphy->bands[band]->channels[i]; |
883 | 883 | ||
884 | if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | | 884 | if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR | |
885 | IEEE80211_CHAN_DISABLED)) | 885 | IEEE80211_CHAN_DISABLED)) |
886 | continue; | 886 | continue; |
887 | 887 | ||
@@ -895,7 +895,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
895 | 895 | ||
896 | local->int_scan_req->n_channels = n_ch; | 896 | local->int_scan_req->n_channels = n_ch; |
897 | } else { | 897 | } else { |
898 | if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | | 898 | if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR | |
899 | IEEE80211_CHAN_DISABLED))) | 899 | IEEE80211_CHAN_DISABLED))) |
900 | goto unlock; | 900 | goto unlock; |
901 | 901 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 1eb66e26e49d..8ed97f76c3cf 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -266,9 +266,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, | |||
266 | */ | 266 | */ |
267 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) | 267 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) |
268 | { | 268 | { |
269 | int i; | ||
270 | |||
269 | if (sta->rate_ctrl) | 271 | if (sta->rate_ctrl) |
270 | rate_control_free_sta(sta); | 272 | rate_control_free_sta(sta); |
271 | 273 | ||
274 | if (sta->tx_lat) { | ||
275 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) | ||
276 | kfree(sta->tx_lat[i].bins); | ||
277 | kfree(sta->tx_lat); | ||
278 | } | ||
279 | |||
272 | sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); | 280 | sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); |
273 | 281 | ||
274 | kfree(sta); | 282 | kfree(sta); |
@@ -333,6 +341,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
333 | struct ieee80211_local *local = sdata->local; | 341 | struct ieee80211_local *local = sdata->local; |
334 | struct sta_info *sta; | 342 | struct sta_info *sta; |
335 | struct timespec uptime; | 343 | struct timespec uptime; |
344 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
336 | int i; | 345 | int i; |
337 | 346 | ||
338 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); | 347 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); |
@@ -410,6 +419,31 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
410 | } | 419 | } |
411 | } | 420 | } |
412 | 421 | ||
422 | rcu_read_lock(); | ||
423 | |||
424 | tx_latency = rcu_dereference(local->tx_latency); | ||
425 | /* init stations Tx latency statistics && TID bins */ | ||
426 | if (tx_latency) | ||
427 | sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS * | ||
428 | sizeof(struct ieee80211_tx_latency_stat), | ||
429 | GFP_ATOMIC); | ||
430 | |||
431 | /* | ||
432 | * if Tx latency and bins are enabled and the previous allocation | ||
433 | * succeeded | ||
434 | */ | ||
435 | if (tx_latency && tx_latency->n_ranges && sta->tx_lat) | ||
436 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | ||
437 | /* size of bins is size of the ranges +1 */ | ||
438 | sta->tx_lat[i].bin_count = | ||
439 | tx_latency->n_ranges + 1; | ||
440 | sta->tx_lat[i].bins = kcalloc(sta->tx_lat[i].bin_count, | ||
441 | sizeof(u32), | ||
442 | GFP_ATOMIC); | ||
443 | } | ||
444 | |||
445 | rcu_read_unlock(); | ||
446 | |||
413 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); | 447 | sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); |
414 | 448 | ||
415 | return sta; | 449 | return sta; |
@@ -507,6 +541,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
507 | 541 | ||
508 | set_sta_flag(sta, WLAN_STA_INSERTED); | 542 | set_sta_flag(sta, WLAN_STA_INSERTED); |
509 | 543 | ||
544 | ieee80211_recalc_min_chandef(sdata); | ||
510 | ieee80211_sta_debugfs_add(sta); | 545 | ieee80211_sta_debugfs_add(sta); |
511 | rate_control_add_sta_debugfs(sta); | 546 | rate_control_add_sta_debugfs(sta); |
512 | 547 | ||
@@ -630,8 +665,8 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
630 | #ifdef CONFIG_MAC80211_MESH | 665 | #ifdef CONFIG_MAC80211_MESH |
631 | } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { | 666 | } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { |
632 | ps = &sta->sdata->u.mesh.ps; | 667 | ps = &sta->sdata->u.mesh.ps; |
633 | /* TIM map only for PLID <= IEEE80211_MAX_AID */ | 668 | /* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */ |
634 | id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID; | 669 | id = sta->plid % (IEEE80211_MAX_AID + 1); |
635 | #endif | 670 | #endif |
636 | } else { | 671 | } else { |
637 | return; | 672 | return; |
@@ -869,6 +904,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
869 | 904 | ||
870 | rate_control_remove_sta_debugfs(sta); | 905 | rate_control_remove_sta_debugfs(sta); |
871 | ieee80211_sta_debugfs_remove(sta); | 906 | ieee80211_sta_debugfs_remove(sta); |
907 | ieee80211_recalc_min_chandef(sdata); | ||
872 | 908 | ||
873 | call_rcu(&sta->rcu_head, free_sta_rcu); | 909 | call_rcu(&sta->rcu_head, free_sta_rcu); |
874 | 910 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 3ef06a26b9cb..0218caf5c14a 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -220,6 +220,25 @@ struct sta_ampdu_mlme { | |||
220 | u8 dialog_token_allocator; | 220 | u8 dialog_token_allocator; |
221 | }; | 221 | }; |
222 | 222 | ||
223 | /* | ||
224 | * struct ieee80211_tx_latency_stat - Tx latency statistics | ||
225 | * | ||
226 | * Measures TX latency and jitter for a station per TID. | ||
227 | * | ||
228 | * @max: worst case latency | ||
229 | * @sum: sum of all latencies | ||
230 | * @counter: amount of Tx frames sent from interface | ||
231 | * @bins: each bin counts how many frames transmitted within a certain | ||
232 | * latency range. when disabled it is NULL. | ||
233 | * @bin_count: amount of bins. | ||
234 | */ | ||
235 | struct ieee80211_tx_latency_stat { | ||
236 | u32 max; | ||
237 | u32 sum; | ||
238 | u32 counter; | ||
239 | u32 *bins; | ||
240 | u32 bin_count; | ||
241 | }; | ||
223 | 242 | ||
224 | /** | 243 | /** |
225 | * struct sta_info - STA information | 244 | * struct sta_info - STA information |
@@ -231,8 +250,10 @@ struct sta_ampdu_mlme { | |||
231 | * @hnext: hash table linked list pointer | 250 | * @hnext: hash table linked list pointer |
232 | * @local: pointer to the global information | 251 | * @local: pointer to the global information |
233 | * @sdata: virtual interface this station belongs to | 252 | * @sdata: virtual interface this station belongs to |
234 | * @ptk: peer key negotiated with this station, if any | 253 | * @ptk: peer keys negotiated with this station, if any |
254 | * @ptk_idx: last installed peer key index | ||
235 | * @gtk: group keys negotiated with this station, if any | 255 | * @gtk: group keys negotiated with this station, if any |
256 | * @gtk_idx: last installed group key index | ||
236 | * @rate_ctrl: rate control algorithm reference | 257 | * @rate_ctrl: rate control algorithm reference |
237 | * @rate_ctrl_priv: rate control private per-STA pointer | 258 | * @rate_ctrl_priv: rate control private per-STA pointer |
238 | * @last_tx_rate: rate used for last transmit, to report to userspace as | 259 | * @last_tx_rate: rate used for last transmit, to report to userspace as |
@@ -274,6 +295,7 @@ struct sta_ampdu_mlme { | |||
274 | * @tid_seq: per-TID sequence numbers for sending to this STA | 295 | * @tid_seq: per-TID sequence numbers for sending to this STA |
275 | * @ampdu_mlme: A-MPDU state machine state | 296 | * @ampdu_mlme: A-MPDU state machine state |
276 | * @timer_to_tid: identity mapping to ID timers | 297 | * @timer_to_tid: identity mapping to ID timers |
298 | * @tx_lat: Tx latency statistics | ||
277 | * @llid: Local link ID | 299 | * @llid: Local link ID |
278 | * @plid: Peer link ID | 300 | * @plid: Peer link ID |
279 | * @reason: Cancel reason on PLINK_HOLDING state | 301 | * @reason: Cancel reason on PLINK_HOLDING state |
@@ -303,6 +325,7 @@ struct sta_ampdu_mlme { | |||
303 | * @chain_signal_avg: signal average (per chain) | 325 | * @chain_signal_avg: signal average (per chain) |
304 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for | 326 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for |
305 | * AP only. | 327 | * AP only. |
328 | * @cipher_scheme: optional cipher scheme for this station | ||
306 | */ | 329 | */ |
307 | struct sta_info { | 330 | struct sta_info { |
308 | /* General information, mostly static */ | 331 | /* General information, mostly static */ |
@@ -312,7 +335,9 @@ struct sta_info { | |||
312 | struct ieee80211_local *local; | 335 | struct ieee80211_local *local; |
313 | struct ieee80211_sub_if_data *sdata; | 336 | struct ieee80211_sub_if_data *sdata; |
314 | struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 337 | struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
315 | struct ieee80211_key __rcu *ptk; | 338 | struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS]; |
339 | u8 gtk_idx; | ||
340 | u8 ptk_idx; | ||
316 | struct rate_control_ref *rate_ctrl; | 341 | struct rate_control_ref *rate_ctrl; |
317 | void *rate_ctrl_priv; | 342 | void *rate_ctrl_priv; |
318 | spinlock_t lock; | 343 | spinlock_t lock; |
@@ -380,14 +405,16 @@ struct sta_info { | |||
380 | struct sta_ampdu_mlme ampdu_mlme; | 405 | struct sta_ampdu_mlme ampdu_mlme; |
381 | u8 timer_to_tid[IEEE80211_NUM_TIDS]; | 406 | u8 timer_to_tid[IEEE80211_NUM_TIDS]; |
382 | 407 | ||
408 | struct ieee80211_tx_latency_stat *tx_lat; | ||
409 | |||
383 | #ifdef CONFIG_MAC80211_MESH | 410 | #ifdef CONFIG_MAC80211_MESH |
384 | /* | 411 | /* |
385 | * Mesh peer link attributes | 412 | * Mesh peer link attributes |
386 | * TODO: move to a sub-structure that is referenced with pointer? | 413 | * TODO: move to a sub-structure that is referenced with pointer? |
387 | */ | 414 | */ |
388 | __le16 llid; | 415 | u16 llid; |
389 | __le16 plid; | 416 | u16 plid; |
390 | __le16 reason; | 417 | u16 reason; |
391 | u8 plink_retries; | 418 | u8 plink_retries; |
392 | bool ignore_plink_timer; | 419 | bool ignore_plink_timer; |
393 | enum nl80211_plink_state plink_state; | 420 | enum nl80211_plink_state plink_state; |
@@ -414,6 +441,7 @@ struct sta_info { | |||
414 | unsigned int beacon_loss_count; | 441 | unsigned int beacon_loss_count; |
415 | 442 | ||
416 | enum ieee80211_smps_mode known_smps_mode; | 443 | enum ieee80211_smps_mode known_smps_mode; |
444 | const struct ieee80211_cipher_scheme *cipher_scheme; | ||
417 | 445 | ||
418 | /* keep last! */ | 446 | /* keep last! */ |
419 | struct ieee80211_sta sta; | 447 | struct ieee80211_sta sta; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 52a152b01b06..1ee85c402439 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/etherdevice.h> | 13 | #include <linux/etherdevice.h> |
14 | #include <linux/time.h> | ||
14 | #include <net/mac80211.h> | 15 | #include <net/mac80211.h> |
15 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
16 | #include "ieee80211_i.h" | 17 | #include "ieee80211_i.h" |
@@ -463,6 +464,77 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, | |||
463 | } | 464 | } |
464 | 465 | ||
465 | /* | 466 | /* |
467 | * Measure Tx frame completion and removal time for Tx latency statistics | ||
468 | * calculation. A single Tx frame latency should be measured from when it | ||
469 | * is entering the Kernel until we receive Tx complete confirmation indication | ||
470 | * and remove the skb. | ||
471 | */ | ||
472 | static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | ||
473 | struct sk_buff *skb, | ||
474 | struct sta_info *sta, | ||
475 | struct ieee80211_hdr *hdr) | ||
476 | { | ||
477 | ktime_t skb_dprt; | ||
478 | struct timespec dprt_time; | ||
479 | u32 msrmnt; | ||
480 | u16 tid; | ||
481 | u8 *qc; | ||
482 | int i, bin_range_count, bin_count; | ||
483 | u32 *bin_ranges; | ||
484 | __le16 fc; | ||
485 | struct ieee80211_tx_latency_stat *tx_lat; | ||
486 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
487 | ktime_t skb_arv = skb->tstamp; | ||
488 | |||
489 | tx_latency = rcu_dereference(local->tx_latency); | ||
490 | |||
491 | /* assert Tx latency stats are enabled & frame arrived when enabled */ | ||
492 | if (!tx_latency || !ktime_to_ns(skb_arv)) | ||
493 | return; | ||
494 | |||
495 | fc = hdr->frame_control; | ||
496 | |||
497 | if (!ieee80211_is_data(fc)) /* make sure it is a data frame */ | ||
498 | return; | ||
499 | |||
500 | /* get frame tid */ | ||
501 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
502 | qc = ieee80211_get_qos_ctl(hdr); | ||
503 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
504 | } else { | ||
505 | tid = 0; | ||
506 | } | ||
507 | |||
508 | tx_lat = &sta->tx_lat[tid]; | ||
509 | |||
510 | ktime_get_ts(&dprt_time); /* time stamp completion time */ | ||
511 | skb_dprt = ktime_set(dprt_time.tv_sec, dprt_time.tv_nsec); | ||
512 | msrmnt = ktime_to_ms(ktime_sub(skb_dprt, skb_arv)); | ||
513 | |||
514 | if (tx_lat->max < msrmnt) /* update stats */ | ||
515 | tx_lat->max = msrmnt; | ||
516 | tx_lat->counter++; | ||
517 | tx_lat->sum += msrmnt; | ||
518 | |||
519 | if (!tx_lat->bins) /* bins not activated */ | ||
520 | return; | ||
521 | |||
522 | /* count how many Tx frames transmitted with the appropriate latency */ | ||
523 | bin_range_count = tx_latency->n_ranges; | ||
524 | bin_ranges = tx_latency->ranges; | ||
525 | bin_count = tx_lat->bin_count; | ||
526 | |||
527 | for (i = 0; i < bin_range_count; i++) { | ||
528 | if (msrmnt <= bin_ranges[i]) { | ||
529 | tx_lat->bins[i]++; | ||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | if (i == bin_range_count) /* msrmnt is bigger than the biggest range */ | ||
534 | tx_lat->bins[i]++; | ||
535 | } | ||
536 | |||
537 | /* | ||
466 | * Use a static threshold for now, best value to be determined | 538 | * Use a static threshold for now, best value to be determined |
467 | * by testing ... | 539 | * by testing ... |
468 | * Should it depend on: | 540 | * Should it depend on: |
@@ -620,6 +692,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
620 | 692 | ||
621 | if (acked) | 693 | if (acked) |
622 | sta->last_ack_signal = info->status.ack_signal; | 694 | sta->last_ack_signal = info->status.ack_signal; |
695 | |||
696 | /* | ||
697 | * Measure frame removal for tx latency | ||
698 | * statistics calculation | ||
699 | */ | ||
700 | ieee80211_tx_latency_end_msrmnt(local, skb, sta, hdr); | ||
623 | } | 701 | } |
624 | 702 | ||
625 | rcu_read_unlock(); | 703 | rcu_read_unlock(); |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index d4cee98533fd..e9ccf22f6dd9 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -41,14 +41,31 @@ | |||
41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ | 41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ |
42 | __entry->center_freq1, __entry->center_freq2 | 42 | __entry->center_freq1, __entry->center_freq2 |
43 | 43 | ||
44 | #define MIN_CHANDEF_ENTRY \ | ||
45 | __field(u32, min_control_freq) \ | ||
46 | __field(u32, min_chan_width) \ | ||
47 | __field(u32, min_center_freq1) \ | ||
48 | __field(u32, min_center_freq2) | ||
49 | |||
50 | #define MIN_CHANDEF_ASSIGN(c) \ | ||
51 | __entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \ | ||
52 | __entry->min_chan_width = (c)->width; \ | ||
53 | __entry->min_center_freq1 = (c)->center_freq1; \ | ||
54 | __entry->min_center_freq2 = (c)->center_freq2; | ||
55 | #define MIN_CHANDEF_PR_FMT " min_control:%d MHz min_width:%d min_center: %d/%d MHz" | ||
56 | #define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_chan_width, \ | ||
57 | __entry->min_center_freq1, __entry->min_center_freq2 | ||
58 | |||
44 | #define CHANCTX_ENTRY CHANDEF_ENTRY \ | 59 | #define CHANCTX_ENTRY CHANDEF_ENTRY \ |
60 | MIN_CHANDEF_ENTRY \ | ||
45 | __field(u8, rx_chains_static) \ | 61 | __field(u8, rx_chains_static) \ |
46 | __field(u8, rx_chains_dynamic) | 62 | __field(u8, rx_chains_dynamic) |
47 | #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \ | 63 | #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \ |
64 | MIN_CHANDEF_ASSIGN(&ctx->conf.min_def) \ | ||
48 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ | 65 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ |
49 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic | 66 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic |
50 | #define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d" | 67 | #define CHANCTX_PR_FMT CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT " chains:%d/%d" |
51 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, \ | 68 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG, \ |
52 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 69 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
53 | 70 | ||
54 | 71 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c558b246ef00..6d59e21cdb9f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/bitmap.h> | 19 | #include <linux/bitmap.h> |
20 | #include <linux/rcupdate.h> | 20 | #include <linux/rcupdate.h> |
21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <linux/time.h> | ||
22 | #include <net/net_namespace.h> | 23 | #include <net/net_namespace.h> |
23 | #include <net/ieee80211_radiotap.h> | 24 | #include <net/ieee80211_radiotap.h> |
24 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
@@ -557,7 +558,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
557 | 558 | ||
558 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) | 559 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) |
559 | tx->key = NULL; | 560 | tx->key = NULL; |
560 | else if (tx->sta && (key = rcu_dereference(tx->sta->ptk))) | 561 | else if (tx->sta && |
562 | (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) | ||
561 | tx->key = key; | 563 | tx->key = key; |
562 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 564 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
563 | is_multicast_ether_addr(hdr->addr1) && | 565 | is_multicast_ether_addr(hdr->addr1) && |
@@ -840,15 +842,16 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, | |||
840 | rem -= fraglen; | 842 | rem -= fraglen; |
841 | tmp = dev_alloc_skb(local->tx_headroom + | 843 | tmp = dev_alloc_skb(local->tx_headroom + |
842 | frag_threshold + | 844 | frag_threshold + |
843 | IEEE80211_ENCRYPT_HEADROOM + | 845 | tx->sdata->encrypt_headroom + |
844 | IEEE80211_ENCRYPT_TAILROOM); | 846 | IEEE80211_ENCRYPT_TAILROOM); |
845 | if (!tmp) | 847 | if (!tmp) |
846 | return -ENOMEM; | 848 | return -ENOMEM; |
847 | 849 | ||
848 | __skb_queue_tail(&tx->skbs, tmp); | 850 | __skb_queue_tail(&tx->skbs, tmp); |
849 | 851 | ||
850 | skb_reserve(tmp, local->tx_headroom + | 852 | skb_reserve(tmp, |
851 | IEEE80211_ENCRYPT_HEADROOM); | 853 | local->tx_headroom + tx->sdata->encrypt_headroom); |
854 | |||
852 | /* copy control information */ | 855 | /* copy control information */ |
853 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); | 856 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); |
854 | 857 | ||
@@ -1485,7 +1488,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
1485 | 1488 | ||
1486 | headroom = local->tx_headroom; | 1489 | headroom = local->tx_headroom; |
1487 | if (may_encrypt) | 1490 | if (may_encrypt) |
1488 | headroom += IEEE80211_ENCRYPT_HEADROOM; | 1491 | headroom += sdata->encrypt_headroom; |
1489 | headroom -= skb_headroom(skb); | 1492 | headroom -= skb_headroom(skb); |
1490 | headroom = max_t(int, 0, headroom); | 1493 | headroom = max_t(int, 0, headroom); |
1491 | 1494 | ||
@@ -1724,8 +1727,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1724 | * radar detection by itself. We can do that later by adding a | 1727 | * radar detection by itself. We can do that later by adding a |
1725 | * monitor flag interfaces used for AP support. | 1728 | * monitor flag interfaces used for AP support. |
1726 | */ | 1729 | */ |
1727 | if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | | 1730 | if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))) |
1728 | IEEE80211_CHAN_PASSIVE_SCAN))) | ||
1729 | goto fail_rcu; | 1731 | goto fail_rcu; |
1730 | 1732 | ||
1731 | ieee80211_xmit(sdata, skb, chan->band); | 1733 | ieee80211_xmit(sdata, skb, chan->band); |
@@ -1740,6 +1742,26 @@ fail: | |||
1740 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ | 1742 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ |
1741 | } | 1743 | } |
1742 | 1744 | ||
1745 | /* | ||
1746 | * Measure Tx frame arrival time for Tx latency statistics calculation | ||
1747 | * A single Tx frame latency should be measured from when it is entering the | ||
1748 | * Kernel until we receive Tx complete confirmation indication and the skb is | ||
1749 | * freed. | ||
1750 | */ | ||
1751 | static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local, | ||
1752 | struct sk_buff *skb) | ||
1753 | { | ||
1754 | struct timespec skb_arv; | ||
1755 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | ||
1756 | |||
1757 | tx_latency = rcu_dereference(local->tx_latency); | ||
1758 | if (!tx_latency) | ||
1759 | return; | ||
1760 | |||
1761 | ktime_get_ts(&skb_arv); | ||
1762 | skb->tstamp = ktime_set(skb_arv.tv_sec, skb_arv.tv_nsec); | ||
1763 | } | ||
1764 | |||
1743 | /** | 1765 | /** |
1744 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1766 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type |
1745 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1767 | * subinterfaces (wlan#, WDS, and VLAN interfaces) |
@@ -1790,6 +1812,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1790 | 1812 | ||
1791 | rcu_read_lock(); | 1813 | rcu_read_lock(); |
1792 | 1814 | ||
1815 | /* Measure frame arrival for Tx latency statistics calculation */ | ||
1816 | ieee80211_tx_latency_start_msrmnt(local, skb); | ||
1817 | |||
1793 | switch (sdata->vif.type) { | 1818 | switch (sdata->vif.type) { |
1794 | case NL80211_IFTYPE_AP_VLAN: | 1819 | case NL80211_IFTYPE_AP_VLAN: |
1795 | sta = rcu_dereference(sdata->u.vlan.sta); | 1820 | sta = rcu_dereference(sdata->u.vlan.sta); |
@@ -2109,7 +2134,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2109 | */ | 2134 | */ |
2110 | 2135 | ||
2111 | if (head_need > 0 || skb_cloned(skb)) { | 2136 | if (head_need > 0 || skb_cloned(skb)) { |
2112 | head_need += IEEE80211_ENCRYPT_HEADROOM; | 2137 | head_need += sdata->encrypt_headroom; |
2113 | head_need += local->tx_headroom; | 2138 | head_need += local->tx_headroom; |
2114 | head_need = max_t(int, 0, head_need); | 2139 | head_need = max_t(int, 0, head_need); |
2115 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { | 2140 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9f9b9bd3fd44..875e172c001c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1804,6 +1804,26 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata) | |||
1804 | mutex_unlock(&local->chanctx_mtx); | 1804 | mutex_unlock(&local->chanctx_mtx); |
1805 | } | 1805 | } |
1806 | 1806 | ||
1807 | void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata) | ||
1808 | { | ||
1809 | struct ieee80211_local *local = sdata->local; | ||
1810 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1811 | struct ieee80211_chanctx *chanctx; | ||
1812 | |||
1813 | mutex_lock(&local->chanctx_mtx); | ||
1814 | |||
1815 | chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1816 | lockdep_is_held(&local->chanctx_mtx)); | ||
1817 | |||
1818 | if (WARN_ON_ONCE(!chanctx_conf)) | ||
1819 | goto unlock; | ||
1820 | |||
1821 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
1822 | ieee80211_recalc_chanctx_min_def(local, chanctx); | ||
1823 | unlock: | ||
1824 | mutex_unlock(&local->chanctx_mtx); | ||
1825 | } | ||
1826 | |||
1807 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | 1827 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) |
1808 | { | 1828 | { |
1809 | int i; | 1829 | int i; |
@@ -2259,14 +2279,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2259 | void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) | 2279 | void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) |
2260 | { | 2280 | { |
2261 | struct ieee80211_sub_if_data *sdata; | 2281 | struct ieee80211_sub_if_data *sdata; |
2282 | struct cfg80211_chan_def chandef; | ||
2262 | 2283 | ||
2263 | mutex_lock(&local->iflist_mtx); | 2284 | mutex_lock(&local->iflist_mtx); |
2264 | list_for_each_entry(sdata, &local->interfaces, list) { | 2285 | list_for_each_entry(sdata, &local->interfaces, list) { |
2265 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 2286 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
2266 | 2287 | ||
2267 | if (sdata->wdev.cac_started) { | 2288 | if (sdata->wdev.cac_started) { |
2289 | chandef = sdata->vif.bss_conf.chandef; | ||
2268 | ieee80211_vif_release_channel(sdata); | 2290 | ieee80211_vif_release_channel(sdata); |
2269 | cfg80211_cac_event(sdata->dev, | 2291 | cfg80211_cac_event(sdata->dev, |
2292 | &chandef, | ||
2270 | NL80211_RADAR_CAC_ABORTED, | 2293 | NL80211_RADAR_CAC_ABORTED, |
2271 | GFP_KERNEL); | 2294 | GFP_KERNEL); |
2272 | } | 2295 | } |
@@ -2445,7 +2468,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | |||
2445 | 2468 | ||
2446 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2469 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2447 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 2470 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
2448 | __le16 pre_value; | ||
2449 | 2471 | ||
2450 | skb_put(skb, 8); | 2472 | skb_put(skb, 8); |
2451 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */ | 2473 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */ |
@@ -2457,11 +2479,78 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | |||
2457 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; | 2479 | WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00; |
2458 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */ | 2480 | put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */ |
2459 | pos += 2; | 2481 | pos += 2; |
2460 | pre_value = cpu_to_le16(ifmsh->pre_value); | 2482 | put_unaligned_le16(ifmsh->pre_value, pos);/* Precedence Value */ |
2461 | memcpy(pos, &pre_value, 2); /* Precedence Value */ | ||
2462 | pos += 2; | 2483 | pos += 2; |
2463 | } | 2484 | } |
2464 | 2485 | ||
2465 | ieee80211_tx_skb(sdata, skb); | 2486 | ieee80211_tx_skb(sdata, skb); |
2466 | return 0; | 2487 | return 0; |
2467 | } | 2488 | } |
2489 | |||
2490 | bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs) | ||
2491 | { | ||
2492 | return !(cs == NULL || cs->cipher == 0 || | ||
2493 | cs->hdr_len < cs->pn_len + cs->pn_off || | ||
2494 | cs->hdr_len <= cs->key_idx_off || | ||
2495 | cs->key_idx_shift > 7 || | ||
2496 | cs->key_idx_mask == 0); | ||
2497 | } | ||
2498 | |||
2499 | bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n) | ||
2500 | { | ||
2501 | int i; | ||
2502 | |||
2503 | /* Ensure we have enough iftype bitmap space for all iftype values */ | ||
2504 | WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype)); | ||
2505 | |||
2506 | for (i = 0; i < n; i++) | ||
2507 | if (!ieee80211_cs_valid(&cs[i])) | ||
2508 | return false; | ||
2509 | |||
2510 | return true; | ||
2511 | } | ||
2512 | |||
2513 | const struct ieee80211_cipher_scheme * | ||
2514 | ieee80211_cs_get(struct ieee80211_local *local, u32 cipher, | ||
2515 | enum nl80211_iftype iftype) | ||
2516 | { | ||
2517 | const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes; | ||
2518 | int n = local->hw.n_cipher_schemes; | ||
2519 | int i; | ||
2520 | const struct ieee80211_cipher_scheme *cs = NULL; | ||
2521 | |||
2522 | for (i = 0; i < n; i++) { | ||
2523 | if (l[i].cipher == cipher) { | ||
2524 | cs = &l[i]; | ||
2525 | break; | ||
2526 | } | ||
2527 | } | ||
2528 | |||
2529 | if (!cs || !(cs->iftype & BIT(iftype))) | ||
2530 | return NULL; | ||
2531 | |||
2532 | return cs; | ||
2533 | } | ||
2534 | |||
2535 | int ieee80211_cs_headroom(struct ieee80211_local *local, | ||
2536 | struct cfg80211_crypto_settings *crypto, | ||
2537 | enum nl80211_iftype iftype) | ||
2538 | { | ||
2539 | const struct ieee80211_cipher_scheme *cs; | ||
2540 | int headroom = IEEE80211_ENCRYPT_HEADROOM; | ||
2541 | int i; | ||
2542 | |||
2543 | for (i = 0; i < crypto->n_ciphers_pairwise; i++) { | ||
2544 | cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i], | ||
2545 | iftype); | ||
2546 | |||
2547 | if (cs && headroom < cs->hdr_len) | ||
2548 | headroom = cs->hdr_len; | ||
2549 | } | ||
2550 | |||
2551 | cs = ieee80211_cs_get(local, crypto->cipher_group, iftype); | ||
2552 | if (cs && headroom < cs->hdr_len) | ||
2553 | headroom = cs->hdr_len; | ||
2554 | |||
2555 | return headroom; | ||
2556 | } | ||
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index de0112785aae..d75f35c6e1a0 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -182,16 +182,15 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
182 | IEEE80211_VHT_CAP_SHORT_GI_160); | 182 | IEEE80211_VHT_CAP_SHORT_GI_160); |
183 | 183 | ||
184 | /* remaining ones */ | 184 | /* remaining ones */ |
185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { | 185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) |
186 | vht_cap->cap |= cap_info & | 186 | vht_cap->cap |= cap_info & |
187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | 187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | |
188 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); | 188 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK); |
189 | } | ||
190 | 189 | ||
191 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) | 190 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) |
192 | vht_cap->cap |= cap_info & | 191 | vht_cap->cap |= cap_info & |
193 | (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | 192 | (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
194 | IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX); | 193 | IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK); |
195 | 194 | ||
196 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) | 195 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) |
197 | vht_cap->cap |= cap_info & | 196 | vht_cap->cap |= cap_info & |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index d65728220763..7313d379c0d3 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -545,6 +545,106 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
545 | return RX_CONTINUE; | 545 | return RX_CONTINUE; |
546 | } | 546 | } |
547 | 547 | ||
548 | static ieee80211_tx_result | ||
549 | ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, | ||
550 | struct sk_buff *skb) | ||
551 | { | ||
552 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
553 | struct ieee80211_key *key = tx->key; | ||
554 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
555 | const struct ieee80211_cipher_scheme *cs = key->sta->cipher_scheme; | ||
556 | int hdrlen; | ||
557 | u8 *pos; | ||
558 | |||
559 | if (info->control.hw_key && | ||
560 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { | ||
561 | /* hwaccel has no need for preallocated head room */ | ||
562 | return TX_CONTINUE; | ||
563 | } | ||
564 | |||
565 | if (unlikely(skb_headroom(skb) < cs->hdr_len && | ||
566 | pskb_expand_head(skb, cs->hdr_len, 0, GFP_ATOMIC))) | ||
567 | return TX_DROP; | ||
568 | |||
569 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
570 | |||
571 | pos = skb_push(skb, cs->hdr_len); | ||
572 | memmove(pos, pos + cs->hdr_len, hdrlen); | ||
573 | skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len); | ||
574 | |||
575 | return TX_CONTINUE; | ||
576 | } | ||
577 | |||
578 | static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len) | ||
579 | { | ||
580 | int i; | ||
581 | |||
582 | /* pn is little endian */ | ||
583 | for (i = len - 1; i >= 0; i--) { | ||
584 | if (pn1[i] < pn2[i]) | ||
585 | return -1; | ||
586 | else if (pn1[i] > pn2[i]) | ||
587 | return 1; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static ieee80211_rx_result | ||
594 | ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx) | ||
595 | { | ||
596 | struct ieee80211_key *key = rx->key; | ||
597 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
598 | const struct ieee80211_cipher_scheme *cs = NULL; | ||
599 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
600 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
601 | int data_len; | ||
602 | u8 *rx_pn; | ||
603 | u8 *skb_pn; | ||
604 | u8 qos_tid; | ||
605 | |||
606 | if (!rx->sta || !rx->sta->cipher_scheme || | ||
607 | !(status->flag & RX_FLAG_DECRYPTED)) | ||
608 | return RX_DROP_UNUSABLE; | ||
609 | |||
610 | if (!ieee80211_is_data(hdr->frame_control)) | ||
611 | return RX_CONTINUE; | ||
612 | |||
613 | cs = rx->sta->cipher_scheme; | ||
614 | |||
615 | data_len = rx->skb->len - hdrlen - cs->hdr_len; | ||
616 | |||
617 | if (data_len < 0) | ||
618 | return RX_DROP_UNUSABLE; | ||
619 | |||
620 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
621 | qos_tid = *ieee80211_get_qos_ctl(hdr) & | ||
622 | IEEE80211_QOS_CTL_TID_MASK; | ||
623 | else | ||
624 | qos_tid = 0; | ||
625 | |||
626 | if (skb_linearize(rx->skb)) | ||
627 | return RX_DROP_UNUSABLE; | ||
628 | |||
629 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
630 | |||
631 | rx_pn = key->u.gen.rx_pn[qos_tid]; | ||
632 | skb_pn = rx->skb->data + hdrlen + cs->pn_off; | ||
633 | |||
634 | if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0) | ||
635 | return RX_DROP_UNUSABLE; | ||
636 | |||
637 | memcpy(rx_pn, skb_pn, cs->pn_len); | ||
638 | |||
639 | /* remove security header and MIC */ | ||
640 | if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len)) | ||
641 | return RX_DROP_UNUSABLE; | ||
642 | |||
643 | memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen); | ||
644 | skb_pull(rx->skb, cs->hdr_len); | ||
645 | |||
646 | return RX_CONTINUE; | ||
647 | } | ||
548 | 648 | ||
549 | static void bip_aad(struct sk_buff *skb, u8 *aad) | 649 | static void bip_aad(struct sk_buff *skb, u8 *aad) |
550 | { | 650 | { |
@@ -685,6 +785,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) | |||
685 | { | 785 | { |
686 | struct sk_buff *skb; | 786 | struct sk_buff *skb; |
687 | struct ieee80211_tx_info *info = NULL; | 787 | struct ieee80211_tx_info *info = NULL; |
788 | ieee80211_tx_result res; | ||
688 | 789 | ||
689 | skb_queue_walk(&tx->skbs, skb) { | 790 | skb_queue_walk(&tx->skbs, skb) { |
690 | info = IEEE80211_SKB_CB(skb); | 791 | info = IEEE80211_SKB_CB(skb); |
@@ -692,9 +793,24 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) | |||
692 | /* handle hw-only algorithm */ | 793 | /* handle hw-only algorithm */ |
693 | if (!info->control.hw_key) | 794 | if (!info->control.hw_key) |
694 | return TX_DROP; | 795 | return TX_DROP; |
796 | |||
797 | if (tx->key->sta->cipher_scheme) { | ||
798 | res = ieee80211_crypto_cs_encrypt(tx, skb); | ||
799 | if (res != TX_CONTINUE) | ||
800 | return res; | ||
801 | } | ||
695 | } | 802 | } |
696 | 803 | ||
697 | ieee80211_tx_set_protected(tx); | 804 | ieee80211_tx_set_protected(tx); |
698 | 805 | ||
699 | return TX_CONTINUE; | 806 | return TX_CONTINUE; |
700 | } | 807 | } |
808 | |||
809 | ieee80211_rx_result | ||
810 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) | ||
811 | { | ||
812 | if (rx->sta->cipher_scheme) | ||
813 | return ieee80211_crypto_cs_decrypt(rx); | ||
814 | |||
815 | return RX_DROP_UNUSABLE; | ||
816 | } | ||
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h index 07e33f899c71..62e5a12dfe0a 100644 --- a/net/mac80211/wpa.h +++ b/net/mac80211/wpa.h | |||
@@ -34,5 +34,7 @@ ieee80211_rx_result | |||
34 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); | 34 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); |
35 | ieee80211_tx_result | 35 | ieee80211_tx_result |
36 | ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); | 36 | ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); |
37 | ieee80211_rx_result | ||
38 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); | ||
37 | 39 | ||
38 | #endif /* WPA_H */ | 40 | #endif /* WPA_H */ |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 9b8cc877eb19..78559b5bbd1f 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, | |||
277 | width, dfs_state); | 277 | width, dfs_state); |
278 | } | 278 | } |
279 | 279 | ||
280 | static u32 cfg80211_get_start_freq(u32 center_freq, | ||
281 | u32 bandwidth) | ||
282 | { | ||
283 | u32 start_freq; | ||
284 | |||
285 | if (bandwidth <= 20) | ||
286 | start_freq = center_freq; | ||
287 | else | ||
288 | start_freq = center_freq - bandwidth/2 + 10; | ||
289 | |||
290 | return start_freq; | ||
291 | } | ||
292 | |||
293 | static u32 cfg80211_get_end_freq(u32 center_freq, | ||
294 | u32 bandwidth) | ||
295 | { | ||
296 | u32 end_freq; | ||
297 | |||
298 | if (bandwidth <= 20) | ||
299 | end_freq = center_freq; | ||
300 | else | ||
301 | end_freq = center_freq + bandwidth/2 - 10; | ||
302 | |||
303 | return end_freq; | ||
304 | } | ||
305 | |||
280 | static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, | 306 | static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, |
281 | u32 center_freq, | 307 | u32 center_freq, |
282 | u32 bandwidth) | 308 | u32 bandwidth) |
@@ -284,13 +310,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, | |||
284 | struct ieee80211_channel *c; | 310 | struct ieee80211_channel *c; |
285 | u32 freq, start_freq, end_freq; | 311 | u32 freq, start_freq, end_freq; |
286 | 312 | ||
287 | if (bandwidth <= 20) { | 313 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); |
288 | start_freq = center_freq; | 314 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); |
289 | end_freq = center_freq; | ||
290 | } else { | ||
291 | start_freq = center_freq - bandwidth/2 + 10; | ||
292 | end_freq = center_freq + bandwidth/2 - 10; | ||
293 | } | ||
294 | 315 | ||
295 | for (freq = start_freq; freq <= end_freq; freq += 20) { | 316 | for (freq = start_freq; freq <= end_freq; freq += 20) { |
296 | c = ieee80211_get_channel(wiphy, freq); | 317 | c = ieee80211_get_channel(wiphy, freq); |
@@ -330,33 +351,159 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | |||
330 | } | 351 | } |
331 | EXPORT_SYMBOL(cfg80211_chandef_dfs_required); | 352 | EXPORT_SYMBOL(cfg80211_chandef_dfs_required); |
332 | 353 | ||
333 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 354 | static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy, |
334 | u32 center_freq, u32 bandwidth, | 355 | u32 center_freq, |
335 | u32 prohibited_flags) | 356 | u32 bandwidth) |
336 | { | 357 | { |
337 | struct ieee80211_channel *c; | 358 | struct ieee80211_channel *c; |
338 | u32 freq, start_freq, end_freq; | 359 | u32 freq, start_freq, end_freq; |
360 | int count = 0; | ||
339 | 361 | ||
340 | if (bandwidth <= 20) { | 362 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); |
341 | start_freq = center_freq; | 363 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); |
342 | end_freq = center_freq; | 364 | |
343 | } else { | 365 | /* |
344 | start_freq = center_freq - bandwidth/2 + 10; | 366 | * Check entire range of channels for the bandwidth. |
345 | end_freq = center_freq + bandwidth/2 - 10; | 367 | * Check all channels are DFS channels (DFS_USABLE or |
368 | * DFS_AVAILABLE). Return number of usable channels | ||
369 | * (require CAC). Allow DFS and non-DFS channel mix. | ||
370 | */ | ||
371 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
372 | c = ieee80211_get_channel(wiphy, freq); | ||
373 | if (!c) | ||
374 | return -EINVAL; | ||
375 | |||
376 | if (c->flags & IEEE80211_CHAN_DISABLED) | ||
377 | return -EINVAL; | ||
378 | |||
379 | if (c->flags & IEEE80211_CHAN_RADAR) { | ||
380 | if (c->dfs_state == NL80211_DFS_UNAVAILABLE) | ||
381 | return -EINVAL; | ||
382 | |||
383 | if (c->dfs_state == NL80211_DFS_USABLE) | ||
384 | count++; | ||
385 | } | ||
346 | } | 386 | } |
347 | 387 | ||
388 | return count; | ||
389 | } | ||
390 | |||
391 | bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, | ||
392 | const struct cfg80211_chan_def *chandef) | ||
393 | { | ||
394 | int width; | ||
395 | int r1, r2 = 0; | ||
396 | |||
397 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
398 | return false; | ||
399 | |||
400 | width = cfg80211_chandef_get_width(chandef); | ||
401 | if (width < 0) | ||
402 | return false; | ||
403 | |||
404 | r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1, | ||
405 | width); | ||
406 | |||
407 | if (r1 < 0) | ||
408 | return false; | ||
409 | |||
410 | switch (chandef->width) { | ||
411 | case NL80211_CHAN_WIDTH_80P80: | ||
412 | WARN_ON(!chandef->center_freq2); | ||
413 | r2 = cfg80211_get_chans_dfs_usable(wiphy, | ||
414 | chandef->center_freq2, | ||
415 | width); | ||
416 | if (r2 < 0) | ||
417 | return false; | ||
418 | break; | ||
419 | default: | ||
420 | WARN_ON(chandef->center_freq2); | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | return (r1 + r2 > 0); | ||
425 | } | ||
426 | |||
427 | |||
428 | static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, | ||
429 | u32 center_freq, | ||
430 | u32 bandwidth) | ||
431 | { | ||
432 | struct ieee80211_channel *c; | ||
433 | u32 freq, start_freq, end_freq; | ||
434 | |||
435 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | ||
436 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | ||
437 | |||
438 | /* | ||
439 | * Check entire range of channels for the bandwidth. | ||
440 | * If any channel in between is disabled or has not | ||
441 | * had gone through CAC return false | ||
442 | */ | ||
348 | for (freq = start_freq; freq <= end_freq; freq += 20) { | 443 | for (freq = start_freq; freq <= end_freq; freq += 20) { |
349 | c = ieee80211_get_channel(wiphy, freq); | 444 | c = ieee80211_get_channel(wiphy, freq); |
350 | if (!c) | 445 | if (!c) |
351 | return false; | 446 | return false; |
352 | 447 | ||
353 | /* check for radar flags */ | 448 | if (c->flags & IEEE80211_CHAN_DISABLED) |
354 | if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) && | 449 | return false; |
450 | |||
451 | if ((c->flags & IEEE80211_CHAN_RADAR) && | ||
355 | (c->dfs_state != NL80211_DFS_AVAILABLE)) | 452 | (c->dfs_state != NL80211_DFS_AVAILABLE)) |
356 | return false; | 453 | return false; |
454 | } | ||
455 | |||
456 | return true; | ||
457 | } | ||
458 | |||
459 | static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, | ||
460 | const struct cfg80211_chan_def *chandef) | ||
461 | { | ||
462 | int width; | ||
463 | int r; | ||
464 | |||
465 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
466 | return false; | ||
467 | |||
468 | width = cfg80211_chandef_get_width(chandef); | ||
469 | if (width < 0) | ||
470 | return false; | ||
471 | |||
472 | r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1, | ||
473 | width); | ||
474 | |||
475 | /* If any of channels unavailable for cf1 just return */ | ||
476 | if (!r) | ||
477 | return r; | ||
478 | |||
479 | switch (chandef->width) { | ||
480 | case NL80211_CHAN_WIDTH_80P80: | ||
481 | WARN_ON(!chandef->center_freq2); | ||
482 | r = cfg80211_get_chans_dfs_available(wiphy, | ||
483 | chandef->center_freq2, | ||
484 | width); | ||
485 | default: | ||
486 | WARN_ON(chandef->center_freq2); | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | return r; | ||
491 | } | ||
357 | 492 | ||
358 | /* check for the other flags */ | 493 | |
359 | if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR) | 494 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
495 | u32 center_freq, u32 bandwidth, | ||
496 | u32 prohibited_flags) | ||
497 | { | ||
498 | struct ieee80211_channel *c; | ||
499 | u32 freq, start_freq, end_freq; | ||
500 | |||
501 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | ||
502 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | ||
503 | |||
504 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
505 | c = ieee80211_get_channel(wiphy, freq); | ||
506 | if (!c || c->flags & prohibited_flags) | ||
360 | return false; | 507 | return false; |
361 | } | 508 | } |
362 | 509 | ||
@@ -462,14 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
462 | struct cfg80211_chan_def *chandef) | 609 | struct cfg80211_chan_def *chandef) |
463 | { | 610 | { |
464 | bool res; | 611 | bool res; |
612 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | | ||
613 | IEEE80211_CHAN_NO_IR | | ||
614 | IEEE80211_CHAN_RADAR; | ||
465 | 615 | ||
466 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | 616 | trace_cfg80211_reg_can_beacon(wiphy, chandef); |
467 | 617 | ||
468 | res = cfg80211_chandef_usable(wiphy, chandef, | 618 | if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 && |
469 | IEEE80211_CHAN_DISABLED | | 619 | cfg80211_chandef_dfs_available(wiphy, chandef)) { |
470 | IEEE80211_CHAN_PASSIVE_SCAN | | 620 | /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ |
471 | IEEE80211_CHAN_NO_IBSS | | 621 | prohibited_flags = IEEE80211_CHAN_DISABLED; |
472 | IEEE80211_CHAN_RADAR); | 622 | } |
623 | |||
624 | res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags); | ||
473 | 625 | ||
474 | trace_cfg80211_return_bool(res); | 626 | trace_cfg80211_return_bool(res); |
475 | return res; | 627 | return res; |
@@ -510,6 +662,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
510 | : CHAN_MODE_EXCLUSIVE; | 662 | : CHAN_MODE_EXCLUSIVE; |
511 | return; | 663 | return; |
512 | } | 664 | } |
665 | break; | ||
513 | case NL80211_IFTYPE_STATION: | 666 | case NL80211_IFTYPE_STATION: |
514 | case NL80211_IFTYPE_P2P_CLIENT: | 667 | case NL80211_IFTYPE_P2P_CLIENT: |
515 | if (wdev->current_bss) { | 668 | if (wdev->current_bss) { |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 52b865fb7351..06db6eb5258a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -357,8 +357,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
357 | rdev->wiphy.rts_threshold = (u32) -1; | 357 | rdev->wiphy.rts_threshold = (u32) -1; |
358 | rdev->wiphy.coverage_class = 0; | 358 | rdev->wiphy.coverage_class = 0; |
359 | 359 | ||
360 | rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH; | ||
361 | |||
362 | return &rdev->wiphy; | 360 | return &rdev->wiphy; |
363 | } | 361 | } |
364 | EXPORT_SYMBOL(wiphy_new); | 362 | EXPORT_SYMBOL(wiphy_new); |
@@ -575,6 +573,8 @@ int wiphy_register(struct wiphy *wiphy) | |||
575 | /* check and set up bitrates */ | 573 | /* check and set up bitrates */ |
576 | ieee80211_set_bitrate_flags(wiphy); | 574 | ieee80211_set_bitrate_flags(wiphy); |
577 | 575 | ||
576 | rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH; | ||
577 | |||
578 | rtnl_lock(); | 578 | rtnl_lock(); |
579 | res = device_add(&rdev->wiphy.dev); | 579 | res = device_add(&rdev->wiphy.dev); |
580 | if (res) { | 580 | if (res) { |
@@ -595,7 +595,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
595 | if (IS_ERR(rdev->wiphy.debugfsdir)) | 595 | if (IS_ERR(rdev->wiphy.debugfsdir)) |
596 | rdev->wiphy.debugfsdir = NULL; | 596 | rdev->wiphy.debugfsdir = NULL; |
597 | 597 | ||
598 | if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { | 598 | if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { |
599 | struct regulatory_request request; | 599 | struct regulatory_request request; |
600 | 600 | ||
601 | request.wiphy_idx = get_wiphy_idx(wiphy); | 601 | request.wiphy_idx = get_wiphy_idx(wiphy); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index af10e59af2d8..0a277c33bb02 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -317,9 +317,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); | |||
317 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); | 317 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); |
318 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 318 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
319 | struct wireless_dev *wdev, | 319 | struct wireless_dev *wdev, |
320 | struct ieee80211_channel *chan, bool offchan, | 320 | struct cfg80211_mgmt_tx_params *params, |
321 | unsigned int wait, const u8 *buf, size_t len, | 321 | u64 *cookie); |
322 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); | ||
323 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | 322 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, |
324 | const struct ieee80211_ht_cap *ht_capa_mask); | 323 | const struct ieee80211_ht_cap *ht_capa_mask); |
325 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | 324 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, |
@@ -382,6 +381,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
382 | enum cfg80211_chan_mode chanmode, | 381 | enum cfg80211_chan_mode chanmode, |
383 | u8 radar_detect); | 382 | u8 radar_detect); |
384 | 383 | ||
384 | /** | ||
385 | * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable | ||
386 | * @wiphy: the wiphy to validate against | ||
387 | * @chandef: the channel definition to check | ||
388 | * | ||
389 | * Checks if chandef is usable and we can/need start CAC on such channel. | ||
390 | * | ||
391 | * Return: Return true if all channels available and at least | ||
392 | * one channel require CAC (NL80211_DFS_USABLE) | ||
393 | */ | ||
394 | bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, | ||
395 | const struct cfg80211_chan_def *chandef); | ||
396 | |||
385 | void cfg80211_set_dfs_state(struct wiphy *wiphy, | 397 | void cfg80211_set_dfs_state(struct wiphy *wiphy, |
386 | const struct cfg80211_chan_def *chandef, | 398 | const struct cfg80211_chan_def *chandef, |
387 | enum nl80211_dfs_state dfs_state); | 399 | enum nl80211_dfs_state dfs_state); |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 42ed274e81f4..9a8217d2a908 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -33,15 +33,7 @@ BEGIN { | |||
33 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" | 33 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" |
34 | } | 34 | } |
35 | 35 | ||
36 | /^[ \t]*#/ { | 36 | function parse_country_head() { |
37 | # Ignore | ||
38 | } | ||
39 | |||
40 | !active && /^[ \t]*$/ { | ||
41 | # Ignore | ||
42 | } | ||
43 | |||
44 | !active && /country/ { | ||
45 | country=$2 | 37 | country=$2 |
46 | sub(/:/, "", country) | 38 | sub(/:/, "", country) |
47 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country | 39 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country |
@@ -57,7 +49,8 @@ BEGIN { | |||
57 | regdb = regdb "\t®dom_" country ",\n" | 49 | regdb = regdb "\t®dom_" country ",\n" |
58 | } | 50 | } |
59 | 51 | ||
60 | active && /^[ \t]*\(/ { | 52 | function parse_reg_rule() |
53 | { | ||
61 | start = $1 | 54 | start = $1 |
62 | sub(/\(/, "", start) | 55 | sub(/\(/, "", start) |
63 | end = $3 | 56 | end = $3 |
@@ -107,17 +100,21 @@ active && /^[ \t]*\(/ { | |||
107 | } else if (flagarray[arg] == "PTMP-ONLY") { | 100 | } else if (flagarray[arg] == "PTMP-ONLY") { |
108 | flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " | 101 | flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " |
109 | } else if (flagarray[arg] == "PASSIVE-SCAN") { | 102 | } else if (flagarray[arg] == "PASSIVE-SCAN") { |
110 | flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " | 103 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " |
111 | } else if (flagarray[arg] == "NO-IBSS") { | 104 | } else if (flagarray[arg] == "NO-IBSS") { |
112 | flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " | 105 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " |
106 | } else if (flagarray[arg] == "NO-IR") { | ||
107 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | ||
113 | } | 108 | } |
109 | |||
114 | } | 110 | } |
115 | flags = flags "0" | 111 | flags = flags "0" |
116 | printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags | 112 | printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags |
117 | rules++ | 113 | rules++ |
118 | } | 114 | } |
119 | 115 | ||
120 | active && /^[ \t]*$/ { | 116 | function print_tail_country() |
117 | { | ||
121 | active = 0 | 118 | active = 0 |
122 | printf "\t},\n" | 119 | printf "\t},\n" |
123 | printf "\t.n_reg_rules = %d\n", rules | 120 | printf "\t.n_reg_rules = %d\n", rules |
@@ -125,7 +122,29 @@ active && /^[ \t]*$/ { | |||
125 | rules = 0; | 122 | rules = 0; |
126 | } | 123 | } |
127 | 124 | ||
125 | /^[ \t]*#/ { | ||
126 | # Ignore | ||
127 | } | ||
128 | |||
129 | !active && /^[ \t]*$/ { | ||
130 | # Ignore | ||
131 | } | ||
132 | |||
133 | !active && /country/ { | ||
134 | parse_country_head() | ||
135 | } | ||
136 | |||
137 | active && /^[ \t]*\(/ { | ||
138 | parse_reg_rule() | ||
139 | } | ||
140 | |||
141 | active && /^[ \t]*$/ { | ||
142 | print_tail_country() | ||
143 | } | ||
144 | |||
128 | END { | 145 | END { |
146 | if (active) | ||
147 | print_tail_country() | ||
129 | print regdb "};" | 148 | print regdb "};" |
130 | print "" | 149 | print "" |
131 | print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" | 150 | print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 89737ee2669a..730147ed8e65 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -274,7 +274,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
274 | 274 | ||
275 | for (i = 0; i < sband->n_channels; i++) { | 275 | for (i = 0; i < sband->n_channels; i++) { |
276 | chan = &sband->channels[i]; | 276 | chan = &sband->channels[i]; |
277 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) | 277 | if (chan->flags & IEEE80211_CHAN_NO_IR) |
278 | continue; | 278 | continue; |
279 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 279 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
280 | continue; | 280 | continue; |
@@ -346,7 +346,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
346 | chan = ieee80211_get_channel(wdev->wiphy, freq); | 346 | chan = ieee80211_get_channel(wdev->wiphy, freq); |
347 | if (!chan) | 347 | if (!chan) |
348 | return -EINVAL; | 348 | return -EINVAL; |
349 | if (chan->flags & IEEE80211_CHAN_NO_IBSS || | 349 | if (chan->flags & IEEE80211_CHAN_NO_IR || |
350 | chan->flags & IEEE80211_CHAN_DISABLED) | 350 | chan->flags & IEEE80211_CHAN_DISABLED) |
351 | return -EINVAL; | 351 | return -EINVAL; |
352 | } | 352 | } |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0553fd4d85ae..b0e1869de7de 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
141 | 141 | ||
142 | for (i = 0; i < sband->n_channels; i++) { | 142 | for (i = 0; i < sband->n_channels; i++) { |
143 | chan = &sband->channels[i]; | 143 | chan = &sband->channels[i]; |
144 | if (chan->flags & (IEEE80211_CHAN_NO_IBSS | | 144 | if (chan->flags & (IEEE80211_CHAN_NO_IR | |
145 | IEEE80211_CHAN_PASSIVE_SCAN | | ||
146 | IEEE80211_CHAN_DISABLED | | 145 | IEEE80211_CHAN_DISABLED | |
147 | IEEE80211_CHAN_RADAR)) | 146 | IEEE80211_CHAN_RADAR)) |
148 | continue; | 147 | continue; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 6a6b1c8e907d..52cca05044a8 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -520,9 +520,7 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) | |||
520 | 520 | ||
521 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 521 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
522 | struct wireless_dev *wdev, | 522 | struct wireless_dev *wdev, |
523 | struct ieee80211_channel *chan, bool offchan, | 523 | struct cfg80211_mgmt_tx_params *params, u64 *cookie) |
524 | unsigned int wait, const u8 *buf, size_t len, | ||
525 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
526 | { | 524 | { |
527 | const struct ieee80211_mgmt *mgmt; | 525 | const struct ieee80211_mgmt *mgmt; |
528 | u16 stype; | 526 | u16 stype; |
@@ -533,10 +531,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
533 | if (!rdev->ops->mgmt_tx) | 531 | if (!rdev->ops->mgmt_tx) |
534 | return -EOPNOTSUPP; | 532 | return -EOPNOTSUPP; |
535 | 533 | ||
536 | if (len < 24 + 1) | 534 | if (params->len < 24 + 1) |
537 | return -EINVAL; | 535 | return -EINVAL; |
538 | 536 | ||
539 | mgmt = (const struct ieee80211_mgmt *) buf; | 537 | mgmt = (const struct ieee80211_mgmt *)params->buf; |
540 | 538 | ||
541 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | 539 | if (!ieee80211_is_mgmt(mgmt->frame_control)) |
542 | return -EINVAL; | 540 | return -EINVAL; |
@@ -615,9 +613,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
615 | return -EINVAL; | 613 | return -EINVAL; |
616 | 614 | ||
617 | /* Transmit the Action frame as requested by user space */ | 615 | /* Transmit the Action frame as requested by user space */ |
618 | return rdev_mgmt_tx(rdev, wdev, chan, offchan, | 616 | return rdev_mgmt_tx(rdev, wdev, params, cookie); |
619 | wait, buf, len, no_cck, dont_wait_for_ack, | ||
620 | cookie); | ||
621 | } | 617 | } |
622 | 618 | ||
623 | bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, | 619 | bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, |
@@ -763,12 +759,12 @@ void cfg80211_radar_event(struct wiphy *wiphy, | |||
763 | EXPORT_SYMBOL(cfg80211_radar_event); | 759 | EXPORT_SYMBOL(cfg80211_radar_event); |
764 | 760 | ||
765 | void cfg80211_cac_event(struct net_device *netdev, | 761 | void cfg80211_cac_event(struct net_device *netdev, |
762 | const struct cfg80211_chan_def *chandef, | ||
766 | enum nl80211_radar_event event, gfp_t gfp) | 763 | enum nl80211_radar_event event, gfp_t gfp) |
767 | { | 764 | { |
768 | struct wireless_dev *wdev = netdev->ieee80211_ptr; | 765 | struct wireless_dev *wdev = netdev->ieee80211_ptr; |
769 | struct wiphy *wiphy = wdev->wiphy; | 766 | struct wiphy *wiphy = wdev->wiphy; |
770 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 767 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
771 | struct cfg80211_chan_def chandef; | ||
772 | unsigned long timeout; | 768 | unsigned long timeout; |
773 | 769 | ||
774 | trace_cfg80211_cac_event(netdev, event); | 770 | trace_cfg80211_cac_event(netdev, event); |
@@ -779,14 +775,12 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
779 | if (WARN_ON(!wdev->channel)) | 775 | if (WARN_ON(!wdev->channel)) |
780 | return; | 776 | return; |
781 | 777 | ||
782 | cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT); | ||
783 | |||
784 | switch (event) { | 778 | switch (event) { |
785 | case NL80211_RADAR_CAC_FINISHED: | 779 | case NL80211_RADAR_CAC_FINISHED: |
786 | timeout = wdev->cac_start_time + | 780 | timeout = wdev->cac_start_time + |
787 | msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | 781 | msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); |
788 | WARN_ON(!time_after_eq(jiffies, timeout)); | 782 | WARN_ON(!time_after_eq(jiffies, timeout)); |
789 | cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE); | 783 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); |
790 | break; | 784 | break; |
791 | case NL80211_RADAR_CAC_ABORTED: | 785 | case NL80211_RADAR_CAC_ABORTED: |
792 | break; | 786 | break; |
@@ -796,6 +790,6 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
796 | } | 790 | } |
797 | wdev->cac_started = false; | 791 | wdev->cac_started = false; |
798 | 792 | ||
799 | nl80211_radar_notify(rdev, &chandef, event, netdev, gfp); | 793 | nl80211_radar_notify(rdev, chandef, event, netdev, gfp); |
800 | } | 794 | } |
801 | EXPORT_SYMBOL(cfg80211_cac_event); | 795 | EXPORT_SYMBOL(cfg80211_cac_event); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 138dc3bb8b67..a693f86e5970 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -564,12 +564,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
564 | if ((chan->flags & IEEE80211_CHAN_DISABLED) && | 564 | if ((chan->flags & IEEE80211_CHAN_DISABLED) && |
565 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) | 565 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) |
566 | goto nla_put_failure; | 566 | goto nla_put_failure; |
567 | if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 567 | if (chan->flags & IEEE80211_CHAN_NO_IR) { |
568 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) | 568 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR)) |
569 | goto nla_put_failure; | 569 | goto nla_put_failure; |
570 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 570 | if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS)) |
571 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) | 571 | goto nla_put_failure; |
572 | goto nla_put_failure; | 572 | } |
573 | if (chan->flags & IEEE80211_CHAN_RADAR) { | 573 | if (chan->flags & IEEE80211_CHAN_RADAR) { |
574 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) | 574 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) |
575 | goto nla_put_failure; | 575 | goto nla_put_failure; |
@@ -1247,10 +1247,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1247 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | 1247 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && |
1248 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | 1248 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) |
1249 | goto nla_put_failure; | 1249 | goto nla_put_failure; |
1250 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && | ||
1251 | nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) | ||
1252 | goto nla_put_failure; | ||
1253 | |||
1254 | state->split_start++; | 1250 | state->split_start++; |
1255 | if (state->split) | 1251 | if (state->split) |
1256 | break; | 1252 | break; |
@@ -1579,6 +1575,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1579 | if (nl80211_send_coalesce(msg, dev)) | 1575 | if (nl80211_send_coalesce(msg, dev)) |
1580 | goto nla_put_failure; | 1576 | goto nla_put_failure; |
1581 | 1577 | ||
1578 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && | ||
1579 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || | ||
1580 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) | ||
1581 | goto nla_put_failure; | ||
1582 | |||
1582 | /* done */ | 1583 | /* done */ |
1583 | state->split_start = 0; | 1584 | state->split_start = 0; |
1584 | break; | 1585 | break; |
@@ -2187,7 +2188,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev) | |||
2187 | } | 2188 | } |
2188 | 2189 | ||
2189 | static int nl80211_send_chandef(struct sk_buff *msg, | 2190 | static int nl80211_send_chandef(struct sk_buff *msg, |
2190 | struct cfg80211_chan_def *chandef) | 2191 | const struct cfg80211_chan_def *chandef) |
2191 | { | 2192 | { |
2192 | WARN_ON(!cfg80211_chandef_valid(chandef)); | 2193 | WARN_ON(!cfg80211_chandef_valid(chandef)); |
2193 | 2194 | ||
@@ -3236,6 +3237,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3236 | return PTR_ERR(params.acl); | 3237 | return PTR_ERR(params.acl); |
3237 | } | 3238 | } |
3238 | 3239 | ||
3240 | wdev_lock(wdev); | ||
3239 | err = rdev_start_ap(rdev, dev, ¶ms); | 3241 | err = rdev_start_ap(rdev, dev, ¶ms); |
3240 | if (!err) { | 3242 | if (!err) { |
3241 | wdev->preset_chandef = params.chandef; | 3243 | wdev->preset_chandef = params.chandef; |
@@ -3244,6 +3246,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3244 | wdev->ssid_len = params.ssid_len; | 3246 | wdev->ssid_len = params.ssid_len; |
3245 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | 3247 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); |
3246 | } | 3248 | } |
3249 | wdev_unlock(wdev); | ||
3247 | 3250 | ||
3248 | kfree(params.acl); | 3251 | kfree(params.acl); |
3249 | 3252 | ||
@@ -3272,7 +3275,11 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) | |||
3272 | if (err) | 3275 | if (err) |
3273 | return err; | 3276 | return err; |
3274 | 3277 | ||
3275 | return rdev_change_beacon(rdev, dev, ¶ms); | 3278 | wdev_lock(wdev); |
3279 | err = rdev_change_beacon(rdev, dev, ¶ms); | ||
3280 | wdev_unlock(wdev); | ||
3281 | |||
3282 | return err; | ||
3276 | } | 3283 | } |
3277 | 3284 | ||
3278 | static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) | 3285 | static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) |
@@ -4478,7 +4485,9 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
4478 | { | 4485 | { |
4479 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4486 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4480 | struct net_device *dev = info->user_ptr[1]; | 4487 | struct net_device *dev = info->user_ptr[1]; |
4488 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
4481 | struct bss_parameters params; | 4489 | struct bss_parameters params; |
4490 | int err; | ||
4482 | 4491 | ||
4483 | memset(¶ms, 0, sizeof(params)); | 4492 | memset(¶ms, 0, sizeof(params)); |
4484 | /* default to not changing parameters */ | 4493 | /* default to not changing parameters */ |
@@ -4544,7 +4553,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
4544 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4553 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4545 | return -EOPNOTSUPP; | 4554 | return -EOPNOTSUPP; |
4546 | 4555 | ||
4547 | return rdev_change_bss(rdev, dev, ¶ms); | 4556 | wdev_lock(wdev); |
4557 | err = rdev_change_bss(rdev, dev, ¶ms); | ||
4558 | wdev_unlock(wdev); | ||
4559 | |||
4560 | return err; | ||
4548 | } | 4561 | } |
4549 | 4562 | ||
4550 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | 4563 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { |
@@ -5098,7 +5111,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5098 | char *alpha2 = NULL; | 5111 | char *alpha2 = NULL; |
5099 | int rem_reg_rules = 0, r = 0; | 5112 | int rem_reg_rules = 0, r = 0; |
5100 | u32 num_rules = 0, rule_idx = 0, size_of_regd; | 5113 | u32 num_rules = 0, rule_idx = 0, size_of_regd; |
5101 | u8 dfs_region = 0; | 5114 | enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET; |
5102 | struct ieee80211_regdomain *rd = NULL; | 5115 | struct ieee80211_regdomain *rd = NULL; |
5103 | 5116 | ||
5104 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) | 5117 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) |
@@ -5119,6 +5132,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5119 | return -EINVAL; | 5132 | return -EINVAL; |
5120 | } | 5133 | } |
5121 | 5134 | ||
5135 | if (!reg_is_valid_request(alpha2)) | ||
5136 | return -EINVAL; | ||
5137 | |||
5122 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 5138 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
5123 | num_rules * sizeof(struct ieee80211_reg_rule); | 5139 | num_rules * sizeof(struct ieee80211_reg_rule); |
5124 | 5140 | ||
@@ -5365,10 +5381,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5365 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { | 5381 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { |
5366 | request->flags = nla_get_u32( | 5382 | request->flags = nla_get_u32( |
5367 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); | 5383 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); |
5368 | if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | 5384 | if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && |
5369 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || | 5385 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { |
5370 | ((request->flags & NL80211_SCAN_FLAG_FLUSH) && | ||
5371 | !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) { | ||
5372 | err = -EOPNOTSUPP; | 5386 | err = -EOPNOTSUPP; |
5373 | goto out_free; | 5387 | goto out_free; |
5374 | } | 5388 | } |
@@ -5608,10 +5622,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5608 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { | 5622 | if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { |
5609 | request->flags = nla_get_u32( | 5623 | request->flags = nla_get_u32( |
5610 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); | 5624 | info->attrs[NL80211_ATTR_SCAN_FLAGS]); |
5611 | if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | 5625 | if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && |
5612 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) || | 5626 | !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) { |
5613 | ((request->flags & NL80211_SCAN_FLAG_FLUSH) && | ||
5614 | !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) { | ||
5615 | err = -EOPNOTSUPP; | 5627 | err = -EOPNOTSUPP; |
5616 | goto out_free; | 5628 | goto out_free; |
5617 | } | 5629 | } |
@@ -5674,7 +5686,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5674 | if (err == 0) | 5686 | if (err == 0) |
5675 | return -EINVAL; | 5687 | return -EINVAL; |
5676 | 5688 | ||
5677 | if (chandef.chan->dfs_state != NL80211_DFS_USABLE) | 5689 | if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef)) |
5678 | return -EINVAL; | 5690 | return -EINVAL; |
5679 | 5691 | ||
5680 | if (!rdev->ops->start_radar_detection) | 5692 | if (!rdev->ops->start_radar_detection) |
@@ -5814,7 +5826,11 @@ skip_beacons: | |||
5814 | if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) | 5826 | if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) |
5815 | params.block_tx = true; | 5827 | params.block_tx = true; |
5816 | 5828 | ||
5817 | return rdev_channel_switch(rdev, dev, ¶ms); | 5829 | wdev_lock(wdev); |
5830 | err = rdev_channel_switch(rdev, dev, ¶ms); | ||
5831 | wdev_unlock(wdev); | ||
5832 | |||
5833 | return err; | ||
5818 | } | 5834 | } |
5819 | 5835 | ||
5820 | static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | 5836 | static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, |
@@ -7447,10 +7463,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7447 | void *hdr = NULL; | 7463 | void *hdr = NULL; |
7448 | u64 cookie; | 7464 | u64 cookie; |
7449 | struct sk_buff *msg = NULL; | 7465 | struct sk_buff *msg = NULL; |
7450 | unsigned int wait = 0; | 7466 | struct cfg80211_mgmt_tx_params params = { |
7451 | bool offchan, no_cck, dont_wait_for_ack; | 7467 | .dont_wait_for_ack = |
7452 | 7468 | info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK], | |
7453 | dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK]; | 7469 | }; |
7454 | 7470 | ||
7455 | if (!info->attrs[NL80211_ATTR_FRAME]) | 7471 | if (!info->attrs[NL80211_ATTR_FRAME]) |
7456 | return -EINVAL; | 7472 | return -EINVAL; |
@@ -7477,24 +7493,24 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7477 | if (info->attrs[NL80211_ATTR_DURATION]) { | 7493 | if (info->attrs[NL80211_ATTR_DURATION]) { |
7478 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 7494 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
7479 | return -EINVAL; | 7495 | return -EINVAL; |
7480 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 7496 | params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
7481 | 7497 | ||
7482 | /* | 7498 | /* |
7483 | * We should wait on the channel for at least a minimum amount | 7499 | * We should wait on the channel for at least a minimum amount |
7484 | * of time (10ms) but no longer than the driver supports. | 7500 | * of time (10ms) but no longer than the driver supports. |
7485 | */ | 7501 | */ |
7486 | if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || | 7502 | if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || |
7487 | wait > rdev->wiphy.max_remain_on_channel_duration) | 7503 | params.wait > rdev->wiphy.max_remain_on_channel_duration) |
7488 | return -EINVAL; | 7504 | return -EINVAL; |
7489 | 7505 | ||
7490 | } | 7506 | } |
7491 | 7507 | ||
7492 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | 7508 | params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; |
7493 | 7509 | ||
7494 | if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 7510 | if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
7495 | return -EINVAL; | 7511 | return -EINVAL; |
7496 | 7512 | ||
7497 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | 7513 | params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); |
7498 | 7514 | ||
7499 | /* get the channel if any has been specified, otherwise pass NULL to | 7515 | /* get the channel if any has been specified, otherwise pass NULL to |
7500 | * the driver. The latter will use the current one | 7516 | * the driver. The latter will use the current one |
@@ -7506,10 +7522,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7506 | return err; | 7522 | return err; |
7507 | } | 7523 | } |
7508 | 7524 | ||
7509 | if (!chandef.chan && offchan) | 7525 | if (!chandef.chan && params.offchan) |
7510 | return -EINVAL; | 7526 | return -EINVAL; |
7511 | 7527 | ||
7512 | if (!dont_wait_for_ack) { | 7528 | if (!params.dont_wait_for_ack) { |
7513 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 7529 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
7514 | if (!msg) | 7530 | if (!msg) |
7515 | return -ENOMEM; | 7531 | return -ENOMEM; |
@@ -7522,10 +7538,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7522 | } | 7538 | } |
7523 | } | 7539 | } |
7524 | 7540 | ||
7525 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait, | 7541 | params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); |
7526 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 7542 | params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); |
7527 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 7543 | params.chan = chandef.chan; |
7528 | no_cck, dont_wait_for_ack, &cookie); | 7544 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); |
7529 | if (err) | 7545 | if (err) |
7530 | goto free_msg; | 7546 | goto free_msg; |
7531 | 7547 | ||
@@ -10810,21 +10826,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
10810 | struct wiphy *wiphy = wdev->wiphy; | 10826 | struct wiphy *wiphy = wdev->wiphy; |
10811 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 10827 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
10812 | 10828 | ||
10813 | trace_cfg80211_ch_switch_notify(dev, chandef); | 10829 | ASSERT_WDEV_LOCK(wdev); |
10814 | 10830 | ||
10815 | wdev_lock(wdev); | 10831 | trace_cfg80211_ch_switch_notify(dev, chandef); |
10816 | 10832 | ||
10817 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | 10833 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && |
10818 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | 10834 | wdev->iftype != NL80211_IFTYPE_P2P_GO && |
10819 | wdev->iftype != NL80211_IFTYPE_ADHOC && | 10835 | wdev->iftype != NL80211_IFTYPE_ADHOC && |
10820 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | 10836 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) |
10821 | goto out; | 10837 | return; |
10822 | 10838 | ||
10823 | wdev->channel = chandef->chan; | 10839 | wdev->channel = chandef->chan; |
10824 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | 10840 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); |
10825 | out: | ||
10826 | wdev_unlock(wdev); | ||
10827 | return; | ||
10828 | } | 10841 | } |
10829 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | 10842 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); |
10830 | 10843 | ||
@@ -10883,7 +10896,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify); | |||
10883 | 10896 | ||
10884 | void | 10897 | void |
10885 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 10898 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
10886 | struct cfg80211_chan_def *chandef, | 10899 | const struct cfg80211_chan_def *chandef, |
10887 | enum nl80211_radar_event event, | 10900 | enum nl80211_radar_event event, |
10888 | struct net_device *netdev, gfp_t gfp) | 10901 | struct net_device *netdev, gfp_t gfp) |
10889 | { | 10902 | { |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 2c0f2b3c07cb..b1b231324e10 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -70,7 +70,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
70 | 70 | ||
71 | void | 71 | void |
72 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 72 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
73 | struct cfg80211_chan_def *chandef, | 73 | const struct cfg80211_chan_def *chandef, |
74 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
75 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
76 | 76 | ||
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 37ce9fdfe934..a6c03ab14a0d 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -624,16 +624,12 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev, | |||
624 | 624 | ||
625 | static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, | 625 | static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev, |
626 | struct wireless_dev *wdev, | 626 | struct wireless_dev *wdev, |
627 | struct ieee80211_channel *chan, bool offchan, | 627 | struct cfg80211_mgmt_tx_params *params, |
628 | unsigned int wait, const u8 *buf, size_t len, | 628 | u64 *cookie) |
629 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
630 | { | 629 | { |
631 | int ret; | 630 | int ret; |
632 | trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan, | 631 | trace_rdev_mgmt_tx(&rdev->wiphy, wdev, params); |
633 | wait, no_cck, dont_wait_for_ack); | 632 | ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, params, cookie); |
634 | ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan, | ||
635 | wait, buf, len, no_cck, | ||
636 | dont_wait_for_ack, cookie); | ||
637 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); | 633 | trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie); |
638 | return ret; | 634 | return ret; |
639 | } | 635 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7da67fd0b418..ec54e1aac8e2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -120,6 +120,21 @@ static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) | |||
120 | return rtnl_dereference(wiphy->regd); | 120 | return rtnl_dereference(wiphy->regd); |
121 | } | 121 | } |
122 | 122 | ||
123 | static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region) | ||
124 | { | ||
125 | switch (dfs_region) { | ||
126 | case NL80211_DFS_UNSET: | ||
127 | return "unset"; | ||
128 | case NL80211_DFS_FCC: | ||
129 | return "FCC"; | ||
130 | case NL80211_DFS_ETSI: | ||
131 | return "ETSI"; | ||
132 | case NL80211_DFS_JP: | ||
133 | return "JP"; | ||
134 | } | ||
135 | return "Unknown"; | ||
136 | } | ||
137 | |||
123 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) | 138 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) |
124 | { | 139 | { |
125 | if (!r) | 140 | if (!r) |
@@ -163,35 +178,29 @@ static const struct ieee80211_regdomain world_regdom = { | |||
163 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), | 178 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), |
164 | /* IEEE 802.11b/g, channels 12..13. */ | 179 | /* IEEE 802.11b/g, channels 12..13. */ |
165 | REG_RULE(2467-10, 2472+10, 40, 6, 20, | 180 | REG_RULE(2467-10, 2472+10, 40, 6, 20, |
166 | NL80211_RRF_PASSIVE_SCAN | | 181 | NL80211_RRF_NO_IR), |
167 | NL80211_RRF_NO_IBSS), | ||
168 | /* IEEE 802.11 channel 14 - Only JP enables | 182 | /* IEEE 802.11 channel 14 - Only JP enables |
169 | * this and for 802.11b only */ | 183 | * this and for 802.11b only */ |
170 | REG_RULE(2484-10, 2484+10, 20, 6, 20, | 184 | REG_RULE(2484-10, 2484+10, 20, 6, 20, |
171 | NL80211_RRF_PASSIVE_SCAN | | 185 | NL80211_RRF_NO_IR | |
172 | NL80211_RRF_NO_IBSS | | ||
173 | NL80211_RRF_NO_OFDM), | 186 | NL80211_RRF_NO_OFDM), |
174 | /* IEEE 802.11a, channel 36..48 */ | 187 | /* IEEE 802.11a, channel 36..48 */ |
175 | REG_RULE(5180-10, 5240+10, 160, 6, 20, | 188 | REG_RULE(5180-10, 5240+10, 160, 6, 20, |
176 | NL80211_RRF_PASSIVE_SCAN | | 189 | NL80211_RRF_NO_IR), |
177 | NL80211_RRF_NO_IBSS), | ||
178 | 190 | ||
179 | /* IEEE 802.11a, channel 52..64 - DFS required */ | 191 | /* IEEE 802.11a, channel 52..64 - DFS required */ |
180 | REG_RULE(5260-10, 5320+10, 160, 6, 20, | 192 | REG_RULE(5260-10, 5320+10, 160, 6, 20, |
181 | NL80211_RRF_PASSIVE_SCAN | | 193 | NL80211_RRF_NO_IR | |
182 | NL80211_RRF_NO_IBSS | | ||
183 | NL80211_RRF_DFS), | 194 | NL80211_RRF_DFS), |
184 | 195 | ||
185 | /* IEEE 802.11a, channel 100..144 - DFS required */ | 196 | /* IEEE 802.11a, channel 100..144 - DFS required */ |
186 | REG_RULE(5500-10, 5720+10, 160, 6, 20, | 197 | REG_RULE(5500-10, 5720+10, 160, 6, 20, |
187 | NL80211_RRF_PASSIVE_SCAN | | 198 | NL80211_RRF_NO_IR | |
188 | NL80211_RRF_NO_IBSS | | ||
189 | NL80211_RRF_DFS), | 199 | NL80211_RRF_DFS), |
190 | 200 | ||
191 | /* IEEE 802.11a, channel 149..165 */ | 201 | /* IEEE 802.11a, channel 149..165 */ |
192 | REG_RULE(5745-10, 5825+10, 80, 6, 20, | 202 | REG_RULE(5745-10, 5825+10, 80, 6, 20, |
193 | NL80211_RRF_PASSIVE_SCAN | | 203 | NL80211_RRF_NO_IR), |
194 | NL80211_RRF_NO_IBSS), | ||
195 | 204 | ||
196 | /* IEEE 802.11ad (60gHz), channels 1..3 */ | 205 | /* IEEE 802.11ad (60gHz), channels 1..3 */ |
197 | REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), | 206 | REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), |
@@ -208,11 +217,26 @@ static char user_alpha2[2]; | |||
208 | module_param(ieee80211_regdom, charp, 0444); | 217 | module_param(ieee80211_regdom, charp, 0444); |
209 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 218 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
210 | 219 | ||
220 | static void reg_kfree_last_request(void) | ||
221 | { | ||
222 | struct regulatory_request *lr; | ||
223 | |||
224 | lr = get_last_request(); | ||
225 | |||
226 | if (lr != &core_request_world && lr) | ||
227 | kfree_rcu(lr, rcu_head); | ||
228 | } | ||
229 | |||
230 | static void reg_update_last_request(struct regulatory_request *request) | ||
231 | { | ||
232 | reg_kfree_last_request(); | ||
233 | rcu_assign_pointer(last_request, request); | ||
234 | } | ||
235 | |||
211 | static void reset_regdomains(bool full_reset, | 236 | static void reset_regdomains(bool full_reset, |
212 | const struct ieee80211_regdomain *new_regdom) | 237 | const struct ieee80211_regdomain *new_regdom) |
213 | { | 238 | { |
214 | const struct ieee80211_regdomain *r; | 239 | const struct ieee80211_regdomain *r; |
215 | struct regulatory_request *lr; | ||
216 | 240 | ||
217 | ASSERT_RTNL(); | 241 | ASSERT_RTNL(); |
218 | 242 | ||
@@ -235,10 +259,7 @@ static void reset_regdomains(bool full_reset, | |||
235 | if (!full_reset) | 259 | if (!full_reset) |
236 | return; | 260 | return; |
237 | 261 | ||
238 | lr = get_last_request(); | 262 | reg_update_last_request(&core_request_world); |
239 | if (lr != &core_request_world && lr) | ||
240 | kfree_rcu(lr, rcu_head); | ||
241 | rcu_assign_pointer(last_request, &core_request_world); | ||
242 | } | 263 | } |
243 | 264 | ||
244 | /* | 265 | /* |
@@ -456,7 +477,15 @@ static int call_crda(const char *alpha2) | |||
456 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); | 477 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); |
457 | } | 478 | } |
458 | 479 | ||
459 | static bool reg_is_valid_request(const char *alpha2) | 480 | static enum reg_request_treatment |
481 | reg_call_crda(struct regulatory_request *request) | ||
482 | { | ||
483 | if (call_crda(request->alpha2)) | ||
484 | return REG_REQ_IGNORE; | ||
485 | return REG_REQ_OK; | ||
486 | } | ||
487 | |||
488 | bool reg_is_valid_request(const char *alpha2) | ||
460 | { | 489 | { |
461 | struct regulatory_request *lr = get_last_request(); | 490 | struct regulatory_request *lr = get_last_request(); |
462 | 491 | ||
@@ -557,6 +586,20 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, | |||
557 | } | 586 | } |
558 | 587 | ||
559 | /* | 588 | /* |
589 | * Later on we can perhaps use the more restrictive DFS | ||
590 | * region but we don't have information for that yet so | ||
591 | * for now simply disallow conflicts. | ||
592 | */ | ||
593 | static enum nl80211_dfs_regions | ||
594 | reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1, | ||
595 | const enum nl80211_dfs_regions dfs_region2) | ||
596 | { | ||
597 | if (dfs_region1 != dfs_region2) | ||
598 | return NL80211_DFS_UNSET; | ||
599 | return dfs_region1; | ||
600 | } | ||
601 | |||
602 | /* | ||
560 | * Helper for regdom_intersect(), this does the real | 603 | * Helper for regdom_intersect(), this does the real |
561 | * mathematical intersection fun | 604 | * mathematical intersection fun |
562 | */ | 605 | */ |
@@ -687,6 +730,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
687 | rd->n_reg_rules = num_rules; | 730 | rd->n_reg_rules = num_rules; |
688 | rd->alpha2[0] = '9'; | 731 | rd->alpha2[0] = '9'; |
689 | rd->alpha2[1] = '8'; | 732 | rd->alpha2[1] = '8'; |
733 | rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region, | ||
734 | rd2->dfs_region); | ||
690 | 735 | ||
691 | return rd; | 736 | return rd; |
692 | } | 737 | } |
@@ -698,10 +743,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
698 | static u32 map_regdom_flags(u32 rd_flags) | 743 | static u32 map_regdom_flags(u32 rd_flags) |
699 | { | 744 | { |
700 | u32 channel_flags = 0; | 745 | u32 channel_flags = 0; |
701 | if (rd_flags & NL80211_RRF_PASSIVE_SCAN) | 746 | if (rd_flags & NL80211_RRF_NO_IR_ALL) |
702 | channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN; | 747 | channel_flags |= IEEE80211_CHAN_NO_IR; |
703 | if (rd_flags & NL80211_RRF_NO_IBSS) | ||
704 | channel_flags |= IEEE80211_CHAN_NO_IBSS; | ||
705 | if (rd_flags & NL80211_RRF_DFS) | 748 | if (rd_flags & NL80211_RRF_DFS) |
706 | channel_flags |= IEEE80211_CHAN_RADAR; | 749 | channel_flags |= IEEE80211_CHAN_RADAR; |
707 | if (rd_flags & NL80211_RRF_NO_OFDM) | 750 | if (rd_flags & NL80211_RRF_NO_OFDM) |
@@ -854,8 +897,18 @@ static void handle_channel(struct wiphy *wiphy, | |||
854 | PTR_ERR(reg_rule) == -ERANGE) | 897 | PTR_ERR(reg_rule) == -ERANGE) |
855 | return; | 898 | return; |
856 | 899 | ||
857 | REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); | 900 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
858 | chan->flags |= IEEE80211_CHAN_DISABLED; | 901 | request_wiphy && request_wiphy == wiphy && |
902 | request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) { | ||
903 | REG_DBG_PRINT("Disabling freq %d MHz for good\n", | ||
904 | chan->center_freq); | ||
905 | chan->orig_flags |= IEEE80211_CHAN_DISABLED; | ||
906 | chan->flags = chan->orig_flags; | ||
907 | } else { | ||
908 | REG_DBG_PRINT("Disabling freq %d MHz\n", | ||
909 | chan->center_freq); | ||
910 | chan->flags |= IEEE80211_CHAN_DISABLED; | ||
911 | } | ||
859 | return; | 912 | return; |
860 | } | 913 | } |
861 | 914 | ||
@@ -873,7 +926,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
873 | 926 | ||
874 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 927 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
875 | request_wiphy && request_wiphy == wiphy && | 928 | request_wiphy && request_wiphy == wiphy && |
876 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 929 | request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) { |
877 | /* | 930 | /* |
878 | * This guarantees the driver's requested regulatory domain | 931 | * This guarantees the driver's requested regulatory domain |
879 | * will always be used as a base for further regulatory | 932 | * will always be used as a base for further regulatory |
@@ -899,13 +952,11 @@ static void handle_channel(struct wiphy *wiphy, | |||
899 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 952 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
900 | if (chan->orig_mpwr) { | 953 | if (chan->orig_mpwr) { |
901 | /* | 954 | /* |
902 | * Devices that have their own custom regulatory domain | 955 | * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER |
903 | * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the | 956 | * will always follow the passed country IE power settings. |
904 | * passed country IE power settings. | ||
905 | */ | 957 | */ |
906 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | 958 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && |
907 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | 959 | wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER) |
908 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | ||
909 | chan->max_power = chan->max_reg_power; | 960 | chan->max_power = chan->max_reg_power; |
910 | else | 961 | else |
911 | chan->max_power = min(chan->orig_mpwr, | 962 | chan->max_power = min(chan->orig_mpwr, |
@@ -975,8 +1026,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) | |||
975 | 1026 | ||
976 | static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy) | 1027 | static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy) |
977 | { | 1028 | { |
978 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && | 1029 | if (wiphy->regulatory_flags & REGULATORY_STRICT_REG && |
979 | !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)) | 1030 | !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)) |
980 | return true; | 1031 | return true; |
981 | return false; | 1032 | return false; |
982 | } | 1033 | } |
@@ -994,7 +1045,7 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
994 | } | 1045 | } |
995 | 1046 | ||
996 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 1047 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
997 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { | 1048 | wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { |
998 | REG_DBG_PRINT("Ignoring regulatory request set by %s " | 1049 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
999 | "since the driver uses its own custom " | 1050 | "since the driver uses its own custom " |
1000 | "regulatory domain\n", | 1051 | "regulatory domain\n", |
@@ -1032,7 +1083,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) | |||
1032 | return true; | 1083 | return true; |
1033 | 1084 | ||
1034 | if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1085 | if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1035 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) | 1086 | wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) |
1036 | return true; | 1087 | return true; |
1037 | 1088 | ||
1038 | return false; | 1089 | return false; |
@@ -1060,19 +1111,14 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, | |||
1060 | if (!reg_is_world_roaming(wiphy)) | 1111 | if (!reg_is_world_roaming(wiphy)) |
1061 | return; | 1112 | return; |
1062 | 1113 | ||
1063 | if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) | 1114 | if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS) |
1064 | return; | 1115 | return; |
1065 | 1116 | ||
1066 | chan_before.center_freq = chan->center_freq; | 1117 | chan_before.center_freq = chan->center_freq; |
1067 | chan_before.flags = chan->flags; | 1118 | chan_before.flags = chan->flags; |
1068 | 1119 | ||
1069 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { | 1120 | if (chan->flags & IEEE80211_CHAN_NO_IR) { |
1070 | chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 1121 | chan->flags &= ~IEEE80211_CHAN_NO_IR; |
1071 | channel_changed = true; | ||
1072 | } | ||
1073 | |||
1074 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
1075 | chan->flags &= ~IEEE80211_CHAN_NO_IBSS; | ||
1076 | channel_changed = true; | 1122 | channel_changed = true; |
1077 | } | 1123 | } |
1078 | 1124 | ||
@@ -1205,14 +1251,30 @@ static void reg_process_ht_flags(struct wiphy *wiphy) | |||
1205 | reg_process_ht_flags_band(wiphy, wiphy->bands[band]); | 1251 | reg_process_ht_flags_band(wiphy, wiphy->bands[band]); |
1206 | } | 1252 | } |
1207 | 1253 | ||
1254 | static void reg_call_notifier(struct wiphy *wiphy, | ||
1255 | struct regulatory_request *request) | ||
1256 | { | ||
1257 | if (wiphy->reg_notifier) | ||
1258 | wiphy->reg_notifier(wiphy, request); | ||
1259 | } | ||
1260 | |||
1208 | static void wiphy_update_regulatory(struct wiphy *wiphy, | 1261 | static void wiphy_update_regulatory(struct wiphy *wiphy, |
1209 | enum nl80211_reg_initiator initiator) | 1262 | enum nl80211_reg_initiator initiator) |
1210 | { | 1263 | { |
1211 | enum ieee80211_band band; | 1264 | enum ieee80211_band band; |
1212 | struct regulatory_request *lr = get_last_request(); | 1265 | struct regulatory_request *lr = get_last_request(); |
1213 | 1266 | ||
1214 | if (ignore_reg_update(wiphy, initiator)) | 1267 | if (ignore_reg_update(wiphy, initiator)) { |
1268 | /* | ||
1269 | * Regulatory updates set by CORE are ignored for custom | ||
1270 | * regulatory cards. Let us notify the changes to the driver, | ||
1271 | * as some drivers used this to restore its orig_* reg domain. | ||
1272 | */ | ||
1273 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | ||
1274 | wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) | ||
1275 | reg_call_notifier(wiphy, lr); | ||
1215 | return; | 1276 | return; |
1277 | } | ||
1216 | 1278 | ||
1217 | lr->dfs_region = get_cfg80211_regdom()->dfs_region; | 1279 | lr->dfs_region = get_cfg80211_regdom()->dfs_region; |
1218 | 1280 | ||
@@ -1221,9 +1283,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, | |||
1221 | 1283 | ||
1222 | reg_process_beacons(wiphy); | 1284 | reg_process_beacons(wiphy); |
1223 | reg_process_ht_flags(wiphy); | 1285 | reg_process_ht_flags(wiphy); |
1224 | 1286 | reg_call_notifier(wiphy, lr); | |
1225 | if (wiphy->reg_notifier) | ||
1226 | wiphy->reg_notifier(wiphy, lr); | ||
1227 | } | 1287 | } |
1228 | 1288 | ||
1229 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | 1289 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
@@ -1236,15 +1296,6 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | |||
1236 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 1296 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1237 | wiphy = &rdev->wiphy; | 1297 | wiphy = &rdev->wiphy; |
1238 | wiphy_update_regulatory(wiphy, initiator); | 1298 | wiphy_update_regulatory(wiphy, initiator); |
1239 | /* | ||
1240 | * Regulatory updates set by CORE are ignored for custom | ||
1241 | * regulatory cards. Let us notify the changes to the driver, | ||
1242 | * as some drivers used this to restore its orig_* reg domain. | ||
1243 | */ | ||
1244 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | ||
1245 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | ||
1246 | wiphy->reg_notifier) | ||
1247 | wiphy->reg_notifier(wiphy, get_last_request()); | ||
1248 | } | 1299 | } |
1249 | } | 1300 | } |
1250 | 1301 | ||
@@ -1263,7 +1314,8 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1263 | if (IS_ERR(reg_rule)) { | 1314 | if (IS_ERR(reg_rule)) { |
1264 | REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", | 1315 | REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", |
1265 | chan->center_freq); | 1316 | chan->center_freq); |
1266 | chan->flags = IEEE80211_CHAN_DISABLED; | 1317 | chan->orig_flags |= IEEE80211_CHAN_DISABLED; |
1318 | chan->flags = chan->orig_flags; | ||
1267 | return; | 1319 | return; |
1268 | } | 1320 | } |
1269 | 1321 | ||
@@ -1305,6 +1357,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
1305 | enum ieee80211_band band; | 1357 | enum ieee80211_band band; |
1306 | unsigned int bands_set = 0; | 1358 | unsigned int bands_set = 0; |
1307 | 1359 | ||
1360 | WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG), | ||
1361 | "wiphy should have REGULATORY_CUSTOM_REG\n"); | ||
1362 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
1363 | |||
1308 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1364 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1309 | if (!wiphy->bands[band]) | 1365 | if (!wiphy->bands[band]) |
1310 | continue; | 1366 | continue; |
@@ -1320,225 +1376,285 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
1320 | } | 1376 | } |
1321 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); | 1377 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); |
1322 | 1378 | ||
1323 | /* This has the logic which determines when a new request | 1379 | static void reg_set_request_processed(void) |
1324 | * should be ignored. */ | ||
1325 | static enum reg_request_treatment | ||
1326 | get_reg_request_treatment(struct wiphy *wiphy, | ||
1327 | struct regulatory_request *pending_request) | ||
1328 | { | 1380 | { |
1329 | struct wiphy *last_wiphy = NULL; | 1381 | bool need_more_processing = false; |
1330 | struct regulatory_request *lr = get_last_request(); | 1382 | struct regulatory_request *lr = get_last_request(); |
1331 | 1383 | ||
1332 | /* All initial requests are respected */ | 1384 | lr->processed = true; |
1333 | if (!lr) | ||
1334 | return REG_REQ_OK; | ||
1335 | 1385 | ||
1336 | switch (pending_request->initiator) { | 1386 | spin_lock(®_requests_lock); |
1337 | case NL80211_REGDOM_SET_BY_CORE: | 1387 | if (!list_empty(®_requests_list)) |
1338 | return REG_REQ_OK; | 1388 | need_more_processing = true; |
1339 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1389 | spin_unlock(®_requests_lock); |
1340 | if (reg_request_cell_base(lr)) { | ||
1341 | /* Trust a Cell base station over the AP's country IE */ | ||
1342 | if (regdom_changes(pending_request->alpha2)) | ||
1343 | return REG_REQ_IGNORE; | ||
1344 | return REG_REQ_ALREADY_SET; | ||
1345 | } | ||
1346 | 1390 | ||
1347 | last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 1391 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) |
1392 | cancel_delayed_work(®_timeout); | ||
1348 | 1393 | ||
1349 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) | 1394 | if (need_more_processing) |
1350 | return -EINVAL; | 1395 | schedule_work(®_work); |
1351 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 1396 | } |
1352 | if (last_wiphy != wiphy) { | ||
1353 | /* | ||
1354 | * Two cards with two APs claiming different | ||
1355 | * Country IE alpha2s. We could | ||
1356 | * intersect them, but that seems unlikely | ||
1357 | * to be correct. Reject second one for now. | ||
1358 | */ | ||
1359 | if (regdom_changes(pending_request->alpha2)) | ||
1360 | return REG_REQ_IGNORE; | ||
1361 | return REG_REQ_ALREADY_SET; | ||
1362 | } | ||
1363 | /* | ||
1364 | * Two consecutive Country IE hints on the same wiphy. | ||
1365 | * This should be picked up early by the driver/stack | ||
1366 | */ | ||
1367 | if (WARN_ON(regdom_changes(pending_request->alpha2))) | ||
1368 | return REG_REQ_OK; | ||
1369 | return REG_REQ_ALREADY_SET; | ||
1370 | } | ||
1371 | return REG_REQ_OK; | ||
1372 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
1373 | if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { | ||
1374 | if (regdom_changes(pending_request->alpha2)) | ||
1375 | return REG_REQ_OK; | ||
1376 | return REG_REQ_ALREADY_SET; | ||
1377 | } | ||
1378 | 1397 | ||
1379 | /* | 1398 | /** |
1380 | * This would happen if you unplug and plug your card | 1399 | * reg_process_hint_core - process core regulatory requests |
1381 | * back in or if you add a new device for which the previously | 1400 | * @pending_request: a pending core regulatory request |
1382 | * loaded card also agrees on the regulatory domain. | 1401 | * |
1383 | */ | 1402 | * The wireless subsystem can use this function to process |
1384 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1403 | * a regulatory request issued by the regulatory core. |
1385 | !regdom_changes(pending_request->alpha2)) | 1404 | * |
1386 | return REG_REQ_ALREADY_SET; | 1405 | * Returns one of the different reg request treatment values. |
1406 | */ | ||
1407 | static enum reg_request_treatment | ||
1408 | reg_process_hint_core(struct regulatory_request *core_request) | ||
1409 | { | ||
1410 | |||
1411 | core_request->intersect = false; | ||
1412 | core_request->processed = false; | ||
1413 | |||
1414 | reg_update_last_request(core_request); | ||
1387 | 1415 | ||
1416 | return reg_call_crda(core_request); | ||
1417 | } | ||
1418 | |||
1419 | static enum reg_request_treatment | ||
1420 | __reg_process_hint_user(struct regulatory_request *user_request) | ||
1421 | { | ||
1422 | struct regulatory_request *lr = get_last_request(); | ||
1423 | |||
1424 | if (reg_request_cell_base(user_request)) | ||
1425 | return reg_ignore_cell_hint(user_request); | ||
1426 | |||
1427 | if (reg_request_cell_base(lr)) | ||
1428 | return REG_REQ_IGNORE; | ||
1429 | |||
1430 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
1388 | return REG_REQ_INTERSECT; | 1431 | return REG_REQ_INTERSECT; |
1389 | case NL80211_REGDOM_SET_BY_USER: | 1432 | /* |
1390 | if (reg_request_cell_base(pending_request)) | 1433 | * If the user knows better the user should set the regdom |
1391 | return reg_ignore_cell_hint(pending_request); | 1434 | * to their country before the IE is picked up |
1435 | */ | ||
1436 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER && | ||
1437 | lr->intersect) | ||
1438 | return REG_REQ_IGNORE; | ||
1439 | /* | ||
1440 | * Process user requests only after previous user/driver/core | ||
1441 | * requests have been processed | ||
1442 | */ | ||
1443 | if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || | ||
1444 | lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || | ||
1445 | lr->initiator == NL80211_REGDOM_SET_BY_USER) && | ||
1446 | regdom_changes(lr->alpha2)) | ||
1447 | return REG_REQ_IGNORE; | ||
1392 | 1448 | ||
1393 | if (reg_request_cell_base(lr)) | 1449 | if (!regdom_changes(user_request->alpha2)) |
1394 | return REG_REQ_IGNORE; | 1450 | return REG_REQ_ALREADY_SET; |
1395 | 1451 | ||
1396 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | 1452 | return REG_REQ_OK; |
1397 | return REG_REQ_INTERSECT; | 1453 | } |
1398 | /* | ||
1399 | * If the user knows better the user should set the regdom | ||
1400 | * to their country before the IE is picked up | ||
1401 | */ | ||
1402 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER && | ||
1403 | lr->intersect) | ||
1404 | return REG_REQ_IGNORE; | ||
1405 | /* | ||
1406 | * Process user requests only after previous user/driver/core | ||
1407 | * requests have been processed | ||
1408 | */ | ||
1409 | if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || | ||
1410 | lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || | ||
1411 | lr->initiator == NL80211_REGDOM_SET_BY_USER) && | ||
1412 | regdom_changes(lr->alpha2)) | ||
1413 | return REG_REQ_IGNORE; | ||
1414 | 1454 | ||
1415 | if (!regdom_changes(pending_request->alpha2)) | 1455 | /** |
1416 | return REG_REQ_ALREADY_SET; | 1456 | * reg_process_hint_user - process user regulatory requests |
1457 | * @user_request: a pending user regulatory request | ||
1458 | * | ||
1459 | * The wireless subsystem can use this function to process | ||
1460 | * a regulatory request initiated by userspace. | ||
1461 | * | ||
1462 | * Returns one of the different reg request treatment values. | ||
1463 | */ | ||
1464 | static enum reg_request_treatment | ||
1465 | reg_process_hint_user(struct regulatory_request *user_request) | ||
1466 | { | ||
1467 | enum reg_request_treatment treatment; | ||
1417 | 1468 | ||
1418 | return REG_REQ_OK; | 1469 | treatment = __reg_process_hint_user(user_request); |
1470 | if (treatment == REG_REQ_IGNORE || | ||
1471 | treatment == REG_REQ_ALREADY_SET) { | ||
1472 | kfree(user_request); | ||
1473 | return treatment; | ||
1419 | } | 1474 | } |
1420 | 1475 | ||
1421 | return REG_REQ_IGNORE; | 1476 | user_request->intersect = treatment == REG_REQ_INTERSECT; |
1477 | user_request->processed = false; | ||
1478 | |||
1479 | reg_update_last_request(user_request); | ||
1480 | |||
1481 | user_alpha2[0] = user_request->alpha2[0]; | ||
1482 | user_alpha2[1] = user_request->alpha2[1]; | ||
1483 | |||
1484 | return reg_call_crda(user_request); | ||
1422 | } | 1485 | } |
1423 | 1486 | ||
1424 | static void reg_set_request_processed(void) | 1487 | static enum reg_request_treatment |
1488 | __reg_process_hint_driver(struct regulatory_request *driver_request) | ||
1425 | { | 1489 | { |
1426 | bool need_more_processing = false; | ||
1427 | struct regulatory_request *lr = get_last_request(); | 1490 | struct regulatory_request *lr = get_last_request(); |
1428 | 1491 | ||
1429 | lr->processed = true; | 1492 | if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1430 | 1493 | if (regdom_changes(driver_request->alpha2)) | |
1431 | spin_lock(®_requests_lock); | 1494 | return REG_REQ_OK; |
1432 | if (!list_empty(®_requests_list)) | 1495 | return REG_REQ_ALREADY_SET; |
1433 | need_more_processing = true; | 1496 | } |
1434 | spin_unlock(®_requests_lock); | ||
1435 | 1497 | ||
1436 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) | 1498 | /* |
1437 | cancel_delayed_work(®_timeout); | 1499 | * This would happen if you unplug and plug your card |
1500 | * back in or if you add a new device for which the previously | ||
1501 | * loaded card also agrees on the regulatory domain. | ||
1502 | */ | ||
1503 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | ||
1504 | !regdom_changes(driver_request->alpha2)) | ||
1505 | return REG_REQ_ALREADY_SET; | ||
1438 | 1506 | ||
1439 | if (need_more_processing) | 1507 | return REG_REQ_INTERSECT; |
1440 | schedule_work(®_work); | ||
1441 | } | 1508 | } |
1442 | 1509 | ||
1443 | /** | 1510 | /** |
1444 | * __regulatory_hint - hint to the wireless core a regulatory domain | 1511 | * reg_process_hint_driver - process driver regulatory requests |
1445 | * @wiphy: if the hint comes from country information from an AP, this | 1512 | * @driver_request: a pending driver regulatory request |
1446 | * is required to be set to the wiphy that received the information | ||
1447 | * @pending_request: the regulatory request currently being processed | ||
1448 | * | 1513 | * |
1449 | * The Wireless subsystem can use this function to hint to the wireless core | 1514 | * The wireless subsystem can use this function to process |
1450 | * what it believes should be the current regulatory domain. | 1515 | * a regulatory request issued by an 802.11 driver. |
1451 | * | 1516 | * |
1452 | * Returns one of the different reg request treatment values. | 1517 | * Returns one of the different reg request treatment values. |
1453 | */ | 1518 | */ |
1454 | static enum reg_request_treatment | 1519 | static enum reg_request_treatment |
1455 | __regulatory_hint(struct wiphy *wiphy, | 1520 | reg_process_hint_driver(struct wiphy *wiphy, |
1456 | struct regulatory_request *pending_request) | 1521 | struct regulatory_request *driver_request) |
1457 | { | 1522 | { |
1458 | const struct ieee80211_regdomain *regd; | 1523 | const struct ieee80211_regdomain *regd; |
1459 | bool intersect = false; | ||
1460 | enum reg_request_treatment treatment; | 1524 | enum reg_request_treatment treatment; |
1461 | struct regulatory_request *lr; | ||
1462 | 1525 | ||
1463 | treatment = get_reg_request_treatment(wiphy, pending_request); | 1526 | treatment = __reg_process_hint_driver(driver_request); |
1464 | 1527 | ||
1465 | switch (treatment) { | 1528 | switch (treatment) { |
1466 | case REG_REQ_INTERSECT: | ||
1467 | if (pending_request->initiator == | ||
1468 | NL80211_REGDOM_SET_BY_DRIVER) { | ||
1469 | regd = reg_copy_regd(get_cfg80211_regdom()); | ||
1470 | if (IS_ERR(regd)) { | ||
1471 | kfree(pending_request); | ||
1472 | return PTR_ERR(regd); | ||
1473 | } | ||
1474 | rcu_assign_pointer(wiphy->regd, regd); | ||
1475 | } | ||
1476 | intersect = true; | ||
1477 | break; | ||
1478 | case REG_REQ_OK: | 1529 | case REG_REQ_OK: |
1479 | break; | 1530 | break; |
1480 | default: | 1531 | case REG_REQ_IGNORE: |
1481 | /* | 1532 | kfree(driver_request); |
1482 | * If the regulatory domain being requested by the | ||
1483 | * driver has already been set just copy it to the | ||
1484 | * wiphy | ||
1485 | */ | ||
1486 | if (treatment == REG_REQ_ALREADY_SET && | ||
1487 | pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) { | ||
1488 | regd = reg_copy_regd(get_cfg80211_regdom()); | ||
1489 | if (IS_ERR(regd)) { | ||
1490 | kfree(pending_request); | ||
1491 | return REG_REQ_IGNORE; | ||
1492 | } | ||
1493 | treatment = REG_REQ_ALREADY_SET; | ||
1494 | rcu_assign_pointer(wiphy->regd, regd); | ||
1495 | goto new_request; | ||
1496 | } | ||
1497 | kfree(pending_request); | ||
1498 | return treatment; | 1533 | return treatment; |
1534 | case REG_REQ_INTERSECT: | ||
1535 | /* fall through */ | ||
1536 | case REG_REQ_ALREADY_SET: | ||
1537 | regd = reg_copy_regd(get_cfg80211_regdom()); | ||
1538 | if (IS_ERR(regd)) { | ||
1539 | kfree(driver_request); | ||
1540 | return REG_REQ_IGNORE; | ||
1541 | } | ||
1542 | rcu_assign_pointer(wiphy->regd, regd); | ||
1499 | } | 1543 | } |
1500 | 1544 | ||
1501 | new_request: | ||
1502 | lr = get_last_request(); | ||
1503 | if (lr != &core_request_world && lr) | ||
1504 | kfree_rcu(lr, rcu_head); | ||
1505 | 1545 | ||
1506 | pending_request->intersect = intersect; | 1546 | driver_request->intersect = treatment == REG_REQ_INTERSECT; |
1507 | pending_request->processed = false; | 1547 | driver_request->processed = false; |
1508 | rcu_assign_pointer(last_request, pending_request); | ||
1509 | lr = pending_request; | ||
1510 | 1548 | ||
1511 | pending_request = NULL; | 1549 | reg_update_last_request(driver_request); |
1512 | 1550 | ||
1513 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) { | 1551 | /* |
1514 | user_alpha2[0] = lr->alpha2[0]; | 1552 | * Since CRDA will not be called in this case as we already |
1515 | user_alpha2[1] = lr->alpha2[1]; | 1553 | * have applied the requested regulatory domain before we just |
1554 | * inform userspace we have processed the request | ||
1555 | */ | ||
1556 | if (treatment == REG_REQ_ALREADY_SET) { | ||
1557 | nl80211_send_reg_change_event(driver_request); | ||
1558 | reg_set_request_processed(); | ||
1559 | return treatment; | ||
1516 | } | 1560 | } |
1517 | 1561 | ||
1518 | /* When r == REG_REQ_INTERSECT we do need to call CRDA */ | 1562 | return reg_call_crda(driver_request); |
1519 | if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) { | 1563 | } |
1564 | |||
1565 | static enum reg_request_treatment | ||
1566 | __reg_process_hint_country_ie(struct wiphy *wiphy, | ||
1567 | struct regulatory_request *country_ie_request) | ||
1568 | { | ||
1569 | struct wiphy *last_wiphy = NULL; | ||
1570 | struct regulatory_request *lr = get_last_request(); | ||
1571 | |||
1572 | if (reg_request_cell_base(lr)) { | ||
1573 | /* Trust a Cell base station over the AP's country IE */ | ||
1574 | if (regdom_changes(country_ie_request->alpha2)) | ||
1575 | return REG_REQ_IGNORE; | ||
1576 | return REG_REQ_ALREADY_SET; | ||
1577 | } else { | ||
1578 | if (wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_IGNORE) | ||
1579 | return REG_REQ_IGNORE; | ||
1580 | } | ||
1581 | |||
1582 | if (unlikely(!is_an_alpha2(country_ie_request->alpha2))) | ||
1583 | return -EINVAL; | ||
1584 | |||
1585 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
1586 | return REG_REQ_OK; | ||
1587 | |||
1588 | last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | ||
1589 | |||
1590 | if (last_wiphy != wiphy) { | ||
1520 | /* | 1591 | /* |
1521 | * Since CRDA will not be called in this case as we already | 1592 | * Two cards with two APs claiming different |
1522 | * have applied the requested regulatory domain before we just | 1593 | * Country IE alpha2s. We could |
1523 | * inform userspace we have processed the request | 1594 | * intersect them, but that seems unlikely |
1595 | * to be correct. Reject second one for now. | ||
1524 | */ | 1596 | */ |
1525 | if (treatment == REG_REQ_ALREADY_SET) { | 1597 | if (regdom_changes(country_ie_request->alpha2)) |
1526 | nl80211_send_reg_change_event(lr); | 1598 | return REG_REQ_IGNORE; |
1527 | reg_set_request_processed(); | 1599 | return REG_REQ_ALREADY_SET; |
1528 | } | ||
1529 | return treatment; | ||
1530 | } | 1600 | } |
1601 | /* | ||
1602 | * Two consecutive Country IE hints on the same wiphy. | ||
1603 | * This should be picked up early by the driver/stack | ||
1604 | */ | ||
1605 | if (WARN_ON(regdom_changes(country_ie_request->alpha2))) | ||
1606 | return REG_REQ_OK; | ||
1607 | return REG_REQ_ALREADY_SET; | ||
1608 | } | ||
1609 | |||
1610 | /** | ||
1611 | * reg_process_hint_country_ie - process regulatory requests from country IEs | ||
1612 | * @country_ie_request: a regulatory request from a country IE | ||
1613 | * | ||
1614 | * The wireless subsystem can use this function to process | ||
1615 | * a regulatory request issued by a country Information Element. | ||
1616 | * | ||
1617 | * Returns one of the different reg request treatment values. | ||
1618 | */ | ||
1619 | static enum reg_request_treatment | ||
1620 | reg_process_hint_country_ie(struct wiphy *wiphy, | ||
1621 | struct regulatory_request *country_ie_request) | ||
1622 | { | ||
1623 | enum reg_request_treatment treatment; | ||
1624 | |||
1625 | treatment = __reg_process_hint_country_ie(wiphy, country_ie_request); | ||
1531 | 1626 | ||
1532 | if (call_crda(lr->alpha2)) | 1627 | switch (treatment) { |
1628 | case REG_REQ_OK: | ||
1629 | break; | ||
1630 | case REG_REQ_IGNORE: | ||
1631 | /* fall through */ | ||
1632 | case REG_REQ_ALREADY_SET: | ||
1633 | kfree(country_ie_request); | ||
1634 | return treatment; | ||
1635 | case REG_REQ_INTERSECT: | ||
1636 | kfree(country_ie_request); | ||
1637 | /* | ||
1638 | * This doesn't happen yet, not sure we | ||
1639 | * ever want to support it for this case. | ||
1640 | */ | ||
1641 | WARN_ONCE(1, "Unexpected intersection for country IEs"); | ||
1533 | return REG_REQ_IGNORE; | 1642 | return REG_REQ_IGNORE; |
1534 | return REG_REQ_OK; | 1643 | } |
1644 | |||
1645 | country_ie_request->intersect = false; | ||
1646 | country_ie_request->processed = false; | ||
1647 | |||
1648 | reg_update_last_request(country_ie_request); | ||
1649 | |||
1650 | return reg_call_crda(country_ie_request); | ||
1535 | } | 1651 | } |
1536 | 1652 | ||
1537 | /* This processes *all* regulatory hints */ | 1653 | /* This processes *all* regulatory hints */ |
1538 | static void reg_process_hint(struct regulatory_request *reg_request, | 1654 | static void reg_process_hint(struct regulatory_request *reg_request) |
1539 | enum nl80211_reg_initiator reg_initiator) | ||
1540 | { | 1655 | { |
1541 | struct wiphy *wiphy = NULL; | 1656 | struct wiphy *wiphy = NULL; |
1657 | enum reg_request_treatment treatment; | ||
1542 | 1658 | ||
1543 | if (WARN_ON(!reg_request->alpha2)) | 1659 | if (WARN_ON(!reg_request->alpha2)) |
1544 | return; | 1660 | return; |
@@ -1546,23 +1662,37 @@ static void reg_process_hint(struct regulatory_request *reg_request, | |||
1546 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) | 1662 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) |
1547 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1663 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1548 | 1664 | ||
1549 | if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { | 1665 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { |
1550 | kfree(reg_request); | 1666 | kfree(reg_request); |
1551 | return; | 1667 | return; |
1552 | } | 1668 | } |
1553 | 1669 | ||
1554 | switch (__regulatory_hint(wiphy, reg_request)) { | 1670 | switch (reg_request->initiator) { |
1555 | case REG_REQ_ALREADY_SET: | 1671 | case NL80211_REGDOM_SET_BY_CORE: |
1556 | /* This is required so that the orig_* parameters are saved */ | 1672 | reg_process_hint_core(reg_request); |
1557 | if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | 1673 | return; |
1558 | wiphy_update_regulatory(wiphy, reg_initiator); | 1674 | case NL80211_REGDOM_SET_BY_USER: |
1675 | treatment = reg_process_hint_user(reg_request); | ||
1676 | if (treatment == REG_REQ_OK || | ||
1677 | treatment == REG_REQ_ALREADY_SET) | ||
1678 | return; | ||
1679 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | ||
1680 | return; | ||
1681 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
1682 | treatment = reg_process_hint_driver(wiphy, reg_request); | ||
1559 | break; | 1683 | break; |
1560 | default: | 1684 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1561 | if (reg_initiator == NL80211_REGDOM_SET_BY_USER) | 1685 | treatment = reg_process_hint_country_ie(wiphy, reg_request); |
1562 | schedule_delayed_work(®_timeout, | ||
1563 | msecs_to_jiffies(3142)); | ||
1564 | break; | 1686 | break; |
1687 | default: | ||
1688 | WARN(1, "invalid initiator %d\n", reg_request->initiator); | ||
1689 | return; | ||
1565 | } | 1690 | } |
1691 | |||
1692 | /* This is required so that the orig_* parameters are saved */ | ||
1693 | if (treatment == REG_REQ_ALREADY_SET && wiphy && | ||
1694 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) | ||
1695 | wiphy_update_regulatory(wiphy, reg_request->initiator); | ||
1566 | } | 1696 | } |
1567 | 1697 | ||
1568 | /* | 1698 | /* |
@@ -1596,7 +1726,7 @@ static void reg_process_pending_hints(void) | |||
1596 | 1726 | ||
1597 | spin_unlock(®_requests_lock); | 1727 | spin_unlock(®_requests_lock); |
1598 | 1728 | ||
1599 | reg_process_hint(reg_request, reg_request->initiator); | 1729 | reg_process_hint(reg_request); |
1600 | } | 1730 | } |
1601 | 1731 | ||
1602 | /* Processes beacon hints -- this has nothing to do with country IEs */ | 1732 | /* Processes beacon hints -- this has nothing to do with country IEs */ |
@@ -1888,7 +2018,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
1888 | world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; | 2018 | world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; |
1889 | 2019 | ||
1890 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 2020 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1891 | if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) | 2021 | if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG) |
1892 | restore_custom_reg_settings(&rdev->wiphy); | 2022 | restore_custom_reg_settings(&rdev->wiphy); |
1893 | } | 2023 | } |
1894 | 2024 | ||
@@ -2016,7 +2146,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2016 | } | 2146 | } |
2017 | } | 2147 | } |
2018 | 2148 | ||
2019 | bool reg_supported_dfs_region(u8 dfs_region) | 2149 | bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region) |
2020 | { | 2150 | { |
2021 | switch (dfs_region) { | 2151 | switch (dfs_region) { |
2022 | case NL80211_DFS_UNSET: | 2152 | case NL80211_DFS_UNSET: |
@@ -2031,27 +2161,6 @@ bool reg_supported_dfs_region(u8 dfs_region) | |||
2031 | } | 2161 | } |
2032 | } | 2162 | } |
2033 | 2163 | ||
2034 | static void print_dfs_region(u8 dfs_region) | ||
2035 | { | ||
2036 | if (!dfs_region) | ||
2037 | return; | ||
2038 | |||
2039 | switch (dfs_region) { | ||
2040 | case NL80211_DFS_FCC: | ||
2041 | pr_info(" DFS Master region FCC"); | ||
2042 | break; | ||
2043 | case NL80211_DFS_ETSI: | ||
2044 | pr_info(" DFS Master region ETSI"); | ||
2045 | break; | ||
2046 | case NL80211_DFS_JP: | ||
2047 | pr_info(" DFS Master region JP"); | ||
2048 | break; | ||
2049 | default: | ||
2050 | pr_info(" DFS Master region Unknown"); | ||
2051 | break; | ||
2052 | } | ||
2053 | } | ||
2054 | |||
2055 | static void print_regdomain(const struct ieee80211_regdomain *rd) | 2164 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
2056 | { | 2165 | { |
2057 | struct regulatory_request *lr = get_last_request(); | 2166 | struct regulatory_request *lr = get_last_request(); |
@@ -2083,7 +2192,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2083 | } | 2192 | } |
2084 | } | 2193 | } |
2085 | 2194 | ||
2086 | print_dfs_region(rd->dfs_region); | 2195 | pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region)); |
2087 | print_rd_rules(rd); | 2196 | print_rd_rules(rd); |
2088 | } | 2197 | } |
2089 | 2198 | ||
@@ -2093,48 +2202,60 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) | |||
2093 | print_rd_rules(rd); | 2202 | print_rd_rules(rd); |
2094 | } | 2203 | } |
2095 | 2204 | ||
2096 | /* Takes ownership of rd only if it doesn't fail */ | 2205 | static int reg_set_rd_core(const struct ieee80211_regdomain *rd) |
2097 | static int __set_regdom(const struct ieee80211_regdomain *rd) | 2206 | { |
2207 | if (!is_world_regdom(rd->alpha2)) | ||
2208 | return -EINVAL; | ||
2209 | update_world_regdomain(rd); | ||
2210 | return 0; | ||
2211 | } | ||
2212 | |||
2213 | static int reg_set_rd_user(const struct ieee80211_regdomain *rd, | ||
2214 | struct regulatory_request *user_request) | ||
2098 | { | 2215 | { |
2099 | const struct ieee80211_regdomain *regd; | ||
2100 | const struct ieee80211_regdomain *intersected_rd = NULL; | 2216 | const struct ieee80211_regdomain *intersected_rd = NULL; |
2101 | struct wiphy *request_wiphy; | ||
2102 | struct regulatory_request *lr = get_last_request(); | ||
2103 | 2217 | ||
2104 | /* Some basic sanity checks first */ | 2218 | if (is_world_regdom(rd->alpha2)) |
2219 | return -EINVAL; | ||
2220 | |||
2221 | if (!regdom_changes(rd->alpha2)) | ||
2222 | return -EALREADY; | ||
2105 | 2223 | ||
2106 | if (!reg_is_valid_request(rd->alpha2)) | 2224 | if (!is_valid_rd(rd)) { |
2225 | pr_err("Invalid regulatory domain detected:\n"); | ||
2226 | print_regdomain_info(rd); | ||
2107 | return -EINVAL; | 2227 | return -EINVAL; |
2228 | } | ||
2108 | 2229 | ||
2109 | if (is_world_regdom(rd->alpha2)) { | 2230 | if (!user_request->intersect) { |
2110 | update_world_regdomain(rd); | 2231 | reset_regdomains(false, rd); |
2111 | return 0; | 2232 | return 0; |
2112 | } | 2233 | } |
2113 | 2234 | ||
2114 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 2235 | intersected_rd = regdom_intersect(rd, get_cfg80211_regdom()); |
2115 | !is_unknown_alpha2(rd->alpha2)) | 2236 | if (!intersected_rd) |
2116 | return -EINVAL; | 2237 | return -EINVAL; |
2117 | 2238 | ||
2118 | /* | 2239 | kfree(rd); |
2119 | * Lets only bother proceeding on the same alpha2 if the current | 2240 | rd = NULL; |
2120 | * rd is non static (it means CRDA was present and was used last) | 2241 | reset_regdomains(false, intersected_rd); |
2121 | * and the pending request came in from a country IE | ||
2122 | */ | ||
2123 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
2124 | /* | ||
2125 | * If someone else asked us to change the rd lets only bother | ||
2126 | * checking if the alpha2 changes if CRDA was already called | ||
2127 | */ | ||
2128 | if (!regdom_changes(rd->alpha2)) | ||
2129 | return -EALREADY; | ||
2130 | } | ||
2131 | 2242 | ||
2132 | /* | 2243 | return 0; |
2133 | * Now lets set the regulatory domain, update all driver channels | 2244 | } |
2134 | * and finally inform them of what we have done, in case they want | 2245 | |
2135 | * to review or adjust their own settings based on their own | 2246 | static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, |
2136 | * internal EEPROM data | 2247 | struct regulatory_request *driver_request) |
2137 | */ | 2248 | { |
2249 | const struct ieee80211_regdomain *regd; | ||
2250 | const struct ieee80211_regdomain *intersected_rd = NULL; | ||
2251 | const struct ieee80211_regdomain *tmp; | ||
2252 | struct wiphy *request_wiphy; | ||
2253 | |||
2254 | if (is_world_regdom(rd->alpha2)) | ||
2255 | return -EINVAL; | ||
2256 | |||
2257 | if (!regdom_changes(rd->alpha2)) | ||
2258 | return -EALREADY; | ||
2138 | 2259 | ||
2139 | if (!is_valid_rd(rd)) { | 2260 | if (!is_valid_rd(rd)) { |
2140 | pr_err("Invalid regulatory domain detected:\n"); | 2261 | pr_err("Invalid regulatory domain detected:\n"); |
@@ -2142,29 +2263,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2142 | return -EINVAL; | 2263 | return -EINVAL; |
2143 | } | 2264 | } |
2144 | 2265 | ||
2145 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 2266 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); |
2146 | if (!request_wiphy && | 2267 | if (!request_wiphy) { |
2147 | (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || | ||
2148 | lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { | ||
2149 | schedule_delayed_work(®_timeout, 0); | 2268 | schedule_delayed_work(®_timeout, 0); |
2150 | return -ENODEV; | 2269 | return -ENODEV; |
2151 | } | 2270 | } |
2152 | 2271 | ||
2153 | if (!lr->intersect) { | 2272 | if (!driver_request->intersect) { |
2154 | if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) { | ||
2155 | reset_regdomains(false, rd); | ||
2156 | return 0; | ||
2157 | } | ||
2158 | |||
2159 | /* | ||
2160 | * For a driver hint, lets copy the regulatory domain the | ||
2161 | * driver wanted to the wiphy to deal with conflicts | ||
2162 | */ | ||
2163 | |||
2164 | /* | ||
2165 | * Userspace could have sent two replies with only | ||
2166 | * one kernel request. | ||
2167 | */ | ||
2168 | if (request_wiphy->regd) | 2273 | if (request_wiphy->regd) |
2169 | return -EALREADY; | 2274 | return -EALREADY; |
2170 | 2275 | ||
@@ -2177,38 +2282,59 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2177 | return 0; | 2282 | return 0; |
2178 | } | 2283 | } |
2179 | 2284 | ||
2180 | /* Intersection requires a bit more work */ | 2285 | intersected_rd = regdom_intersect(rd, get_cfg80211_regdom()); |
2286 | if (!intersected_rd) | ||
2287 | return -EINVAL; | ||
2181 | 2288 | ||
2182 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 2289 | /* |
2183 | intersected_rd = regdom_intersect(rd, get_cfg80211_regdom()); | 2290 | * We can trash what CRDA provided now. |
2184 | if (!intersected_rd) | 2291 | * However if a driver requested this specific regulatory |
2185 | return -EINVAL; | 2292 | * domain we keep it for its private use |
2293 | */ | ||
2294 | tmp = get_wiphy_regdom(request_wiphy); | ||
2295 | rcu_assign_pointer(request_wiphy->regd, rd); | ||
2296 | rcu_free_regdom(tmp); | ||
2186 | 2297 | ||
2187 | /* | 2298 | rd = NULL; |
2188 | * We can trash what CRDA provided now. | ||
2189 | * However if a driver requested this specific regulatory | ||
2190 | * domain we keep it for its private use | ||
2191 | */ | ||
2192 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) { | ||
2193 | const struct ieee80211_regdomain *tmp; | ||
2194 | 2299 | ||
2195 | tmp = get_wiphy_regdom(request_wiphy); | 2300 | reset_regdomains(false, intersected_rd); |
2196 | rcu_assign_pointer(request_wiphy->regd, rd); | ||
2197 | rcu_free_regdom(tmp); | ||
2198 | } else { | ||
2199 | kfree(rd); | ||
2200 | } | ||
2201 | 2301 | ||
2202 | rd = NULL; | 2302 | return 0; |
2303 | } | ||
2203 | 2304 | ||
2204 | reset_regdomains(false, intersected_rd); | 2305 | static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, |
2306 | struct regulatory_request *country_ie_request) | ||
2307 | { | ||
2308 | struct wiphy *request_wiphy; | ||
2205 | 2309 | ||
2206 | return 0; | 2310 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
2311 | !is_unknown_alpha2(rd->alpha2)) | ||
2312 | return -EINVAL; | ||
2313 | |||
2314 | /* | ||
2315 | * Lets only bother proceeding on the same alpha2 if the current | ||
2316 | * rd is non static (it means CRDA was present and was used last) | ||
2317 | * and the pending request came in from a country IE | ||
2318 | */ | ||
2319 | |||
2320 | if (!is_valid_rd(rd)) { | ||
2321 | pr_err("Invalid regulatory domain detected:\n"); | ||
2322 | print_regdomain_info(rd); | ||
2323 | return -EINVAL; | ||
2207 | } | 2324 | } |
2208 | 2325 | ||
2209 | return -EINVAL; | 2326 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); |
2210 | } | 2327 | if (!request_wiphy) { |
2328 | schedule_delayed_work(®_timeout, 0); | ||
2329 | return -ENODEV; | ||
2330 | } | ||
2331 | |||
2332 | if (country_ie_request->intersect) | ||
2333 | return -EINVAL; | ||
2211 | 2334 | ||
2335 | reset_regdomains(false, rd); | ||
2336 | return 0; | ||
2337 | } | ||
2212 | 2338 | ||
2213 | /* | 2339 | /* |
2214 | * Use this call to set the current regulatory domain. Conflicts with | 2340 | * Use this call to set the current regulatory domain. Conflicts with |
@@ -2220,10 +2346,32 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2220 | struct regulatory_request *lr; | 2346 | struct regulatory_request *lr; |
2221 | int r; | 2347 | int r; |
2222 | 2348 | ||
2349 | if (!reg_is_valid_request(rd->alpha2)) { | ||
2350 | kfree(rd); | ||
2351 | return -EINVAL; | ||
2352 | } | ||
2353 | |||
2223 | lr = get_last_request(); | 2354 | lr = get_last_request(); |
2224 | 2355 | ||
2225 | /* Note that this doesn't update the wiphys, this is done below */ | 2356 | /* Note that this doesn't update the wiphys, this is done below */ |
2226 | r = __set_regdom(rd); | 2357 | switch (lr->initiator) { |
2358 | case NL80211_REGDOM_SET_BY_CORE: | ||
2359 | r = reg_set_rd_core(rd); | ||
2360 | break; | ||
2361 | case NL80211_REGDOM_SET_BY_USER: | ||
2362 | r = reg_set_rd_user(rd, lr); | ||
2363 | break; | ||
2364 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
2365 | r = reg_set_rd_driver(rd, lr); | ||
2366 | break; | ||
2367 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | ||
2368 | r = reg_set_rd_country_ie(rd, lr); | ||
2369 | break; | ||
2370 | default: | ||
2371 | WARN(1, "invalid initiator %d\n", lr->initiator); | ||
2372 | return -EINVAL; | ||
2373 | } | ||
2374 | |||
2227 | if (r) { | 2375 | if (r) { |
2228 | if (r == -EALREADY) | 2376 | if (r == -EALREADY) |
2229 | reg_set_request_processed(); | 2377 | reg_set_request_processed(); |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 9677e3c13da9..cc4c2c0a6723 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -18,8 +18,9 @@ | |||
18 | 18 | ||
19 | extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; | 19 | extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; |
20 | 20 | ||
21 | bool reg_is_valid_request(const char *alpha2); | ||
21 | bool is_world_regdom(const char *alpha2); | 22 | bool is_world_regdom(const char *alpha2); |
22 | bool reg_supported_dfs_region(u8 dfs_region); | 23 | bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region); |
23 | 24 | ||
24 | int regulatory_hint_user(const char *alpha2, | 25 | int regulatory_hint_user(const char *alpha2, |
25 | enum nl80211_user_reg_hint_type user_reg_hint_type); | 26 | enum nl80211_user_reg_hint_type user_reg_hint_type); |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ba5f0d6614d5..f7aa7a72d9bc 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1653,9 +1653,8 @@ TRACE_EVENT(rdev_cancel_remain_on_channel, | |||
1653 | 1653 | ||
1654 | TRACE_EVENT(rdev_mgmt_tx, | 1654 | TRACE_EVENT(rdev_mgmt_tx, |
1655 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, | 1655 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, |
1656 | struct ieee80211_channel *chan, bool offchan, | 1656 | struct cfg80211_mgmt_tx_params *params), |
1657 | unsigned int wait, bool no_cck, bool dont_wait_for_ack), | 1657 | TP_ARGS(wiphy, wdev, params), |
1658 | TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack), | ||
1659 | TP_STRUCT__entry( | 1658 | TP_STRUCT__entry( |
1660 | WIPHY_ENTRY | 1659 | WIPHY_ENTRY |
1661 | WDEV_ENTRY | 1660 | WDEV_ENTRY |
@@ -1668,11 +1667,11 @@ TRACE_EVENT(rdev_mgmt_tx, | |||
1668 | TP_fast_assign( | 1667 | TP_fast_assign( |
1669 | WIPHY_ASSIGN; | 1668 | WIPHY_ASSIGN; |
1670 | WDEV_ASSIGN; | 1669 | WDEV_ASSIGN; |
1671 | CHAN_ASSIGN(chan); | 1670 | CHAN_ASSIGN(params->chan); |
1672 | __entry->offchan = offchan; | 1671 | __entry->offchan = params->offchan; |
1673 | __entry->wait = wait; | 1672 | __entry->wait = params->wait; |
1674 | __entry->no_cck = no_cck; | 1673 | __entry->no_cck = params->no_cck; |
1675 | __entry->dont_wait_for_ack = dont_wait_for_ack; | 1674 | __entry->dont_wait_for_ack = params->dont_wait_for_ack; |
1676 | ), | 1675 | ), |
1677 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," | 1676 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s," |
1678 | " wait: %u, no cck: %s, dont wait for ack: %s", | 1677 | " wait: %u, no cck: %s, dont wait for ack: %s", |