diff options
219 files changed, 12126 insertions, 7378 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index bc4b9c6eb80e..61d1a89baeaf 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -249,15 +249,6 @@ Who: Ravikiran Thirumalai <kiran@scalex86.org> | |||
249 | 249 | ||
250 | --------------------------- | 250 | --------------------------- |
251 | 251 | ||
252 | What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS | ||
253 | (in net/core/net-sysfs.c) | ||
254 | When: 3.5 | ||
255 | Why: Over 1K .text/.data size reduction, data is available in other | ||
256 | ways (ioctls) | ||
257 | Who: Johannes Berg <johannes@sipsolutions.net> | ||
258 | |||
259 | --------------------------- | ||
260 | |||
261 | What: sysfs ui for changing p4-clockmod parameters | 252 | What: sysfs ui for changing p4-clockmod parameters |
262 | When: September 2009 | 253 | When: September 2009 |
263 | Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and | 254 | Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and |
@@ -434,6 +425,19 @@ Who: Hans Verkuil <hans.verkuil@cisco.com> | |||
434 | 425 | ||
435 | ---------------------------- | 426 | ---------------------------- |
436 | 427 | ||
428 | What: CONFIG_CFG80211_WEXT | ||
429 | When: as soon as distributions ship new wireless tools, ie. wpa_supplicant 1.0 | ||
430 | and NetworkManager/connman/etc. that are able to use nl80211 | ||
431 | Why: Wireless extensions are deprecated, and userland tools are moving to | ||
432 | using nl80211. New drivers are no longer using wireless extensions, | ||
433 | and while there might still be old drivers, both new drivers and new | ||
434 | userland no longer needs them and they can't be used for an feature | ||
435 | developed in the past couple of years. As such, compatibility with | ||
436 | wireless extensions in new drivers will be removed. | ||
437 | Who: Johannes Berg <johannes@sipsolutions.net> | ||
438 | |||
439 | ---------------------------- | ||
440 | |||
437 | What: g_file_storage driver | 441 | What: g_file_storage driver |
438 | When: 3.8 | 442 | When: 3.8 |
439 | Why: This driver has been superseded by g_mass_storage. | 443 | Why: This driver has been superseded by g_mass_storage. |
diff --git a/MAINTAINERS b/MAINTAINERS index 55f0fda602ec..c5fd905206e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -329,7 +329,7 @@ F: drivers/hwmon/adm1029.c | |||
329 | 329 | ||
330 | ADM8211 WIRELESS DRIVER | 330 | ADM8211 WIRELESS DRIVER |
331 | L: linux-wireless@vger.kernel.org | 331 | L: linux-wireless@vger.kernel.org |
332 | W: http://linuxwireless.org/ | 332 | W: http://wireless.kernel.org/ |
333 | S: Orphan | 333 | S: Orphan |
334 | F: drivers/net/wireless/adm8211.* | 334 | F: drivers/net/wireless/adm8211.* |
335 | 335 | ||
@@ -1423,7 +1423,7 @@ B43 WIRELESS DRIVER | |||
1423 | M: Stefano Brivio <stefano.brivio@polimi.it> | 1423 | M: Stefano Brivio <stefano.brivio@polimi.it> |
1424 | L: linux-wireless@vger.kernel.org | 1424 | L: linux-wireless@vger.kernel.org |
1425 | L: b43-dev@lists.infradead.org | 1425 | L: b43-dev@lists.infradead.org |
1426 | W: http://linuxwireless.org/en/users/Drivers/b43 | 1426 | W: http://wireless.kernel.org/en/users/Drivers/b43 |
1427 | S: Maintained | 1427 | S: Maintained |
1428 | F: drivers/net/wireless/b43/ | 1428 | F: drivers/net/wireless/b43/ |
1429 | 1429 | ||
@@ -1432,7 +1432,7 @@ M: Larry Finger <Larry.Finger@lwfinger.net> | |||
1432 | M: Stefano Brivio <stefano.brivio@polimi.it> | 1432 | M: Stefano Brivio <stefano.brivio@polimi.it> |
1433 | L: linux-wireless@vger.kernel.org | 1433 | L: linux-wireless@vger.kernel.org |
1434 | L: b43-dev@lists.infradead.org | 1434 | L: b43-dev@lists.infradead.org |
1435 | W: http://linuxwireless.org/en/users/Drivers/b43 | 1435 | W: http://wireless.kernel.org/en/users/Drivers/b43 |
1436 | S: Maintained | 1436 | S: Maintained |
1437 | F: drivers/net/wireless/b43legacy/ | 1437 | F: drivers/net/wireless/b43legacy/ |
1438 | 1438 | ||
@@ -4339,7 +4339,7 @@ F: arch/m68k/hp300/ | |||
4339 | MAC80211 | 4339 | MAC80211 |
4340 | M: Johannes Berg <johannes@sipsolutions.net> | 4340 | M: Johannes Berg <johannes@sipsolutions.net> |
4341 | L: linux-wireless@vger.kernel.org | 4341 | L: linux-wireless@vger.kernel.org |
4342 | W: http://linuxwireless.org/ | 4342 | W: http://wireless.kernel.org/ |
4343 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git | 4343 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git |
4344 | S: Maintained | 4344 | S: Maintained |
4345 | F: Documentation/networking/mac80211-injection.txt | 4345 | F: Documentation/networking/mac80211-injection.txt |
@@ -4350,7 +4350,7 @@ MAC80211 PID RATE CONTROL | |||
4350 | M: Stefano Brivio <stefano.brivio@polimi.it> | 4350 | M: Stefano Brivio <stefano.brivio@polimi.it> |
4351 | M: Mattias Nissler <mattias.nissler@gmx.de> | 4351 | M: Mattias Nissler <mattias.nissler@gmx.de> |
4352 | L: linux-wireless@vger.kernel.org | 4352 | L: linux-wireless@vger.kernel.org |
4353 | W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID | 4353 | W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID |
4354 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git | 4354 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git |
4355 | S: Maintained | 4355 | S: Maintained |
4356 | F: net/mac80211/rc80211_pid* | 4356 | F: net/mac80211/rc80211_pid* |
@@ -5027,7 +5027,7 @@ F: fs/ocfs2/ | |||
5027 | 5027 | ||
5028 | ORINOCO DRIVER | 5028 | ORINOCO DRIVER |
5029 | L: linux-wireless@vger.kernel.org | 5029 | L: linux-wireless@vger.kernel.org |
5030 | W: http://linuxwireless.org/en/users/Drivers/orinoco | 5030 | W: http://wireless.kernel.org/en/users/Drivers/orinoco |
5031 | W: http://www.nongnu.org/orinoco/ | 5031 | W: http://www.nongnu.org/orinoco/ |
5032 | S: Orphan | 5032 | S: Orphan |
5033 | F: drivers/net/wireless/orinoco/ | 5033 | F: drivers/net/wireless/orinoco/ |
@@ -5729,7 +5729,7 @@ F: net/rose/ | |||
5729 | RTL8180 WIRELESS DRIVER | 5729 | RTL8180 WIRELESS DRIVER |
5730 | M: "John W. Linville" <linville@tuxdriver.com> | 5730 | M: "John W. Linville" <linville@tuxdriver.com> |
5731 | L: linux-wireless@vger.kernel.org | 5731 | L: linux-wireless@vger.kernel.org |
5732 | W: http://linuxwireless.org/ | 5732 | W: http://wireless.kernel.org/ |
5733 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 5733 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
5734 | S: Maintained | 5734 | S: Maintained |
5735 | F: drivers/net/wireless/rtl818x/rtl8180/ | 5735 | F: drivers/net/wireless/rtl818x/rtl8180/ |
@@ -5739,7 +5739,7 @@ M: Herton Ronaldo Krzesinski <herton@canonical.com> | |||
5739 | M: Hin-Tak Leung <htl10@users.sourceforge.net> | 5739 | M: Hin-Tak Leung <htl10@users.sourceforge.net> |
5740 | M: Larry Finger <Larry.Finger@lwfinger.net> | 5740 | M: Larry Finger <Larry.Finger@lwfinger.net> |
5741 | L: linux-wireless@vger.kernel.org | 5741 | L: linux-wireless@vger.kernel.org |
5742 | W: http://linuxwireless.org/ | 5742 | W: http://wireless.kernel.org/ |
5743 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 5743 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
5744 | S: Maintained | 5744 | S: Maintained |
5745 | F: drivers/net/wireless/rtl818x/rtl8187/ | 5745 | F: drivers/net/wireless/rtl818x/rtl8187/ |
@@ -5748,7 +5748,7 @@ RTL8192CE WIRELESS DRIVER | |||
5748 | M: Larry Finger <Larry.Finger@lwfinger.net> | 5748 | M: Larry Finger <Larry.Finger@lwfinger.net> |
5749 | M: Chaoming Li <chaoming_li@realsil.com.cn> | 5749 | M: Chaoming Li <chaoming_li@realsil.com.cn> |
5750 | L: linux-wireless@vger.kernel.org | 5750 | L: linux-wireless@vger.kernel.org |
5751 | W: http://linuxwireless.org/ | 5751 | W: http://wireless.kernel.org/ |
5752 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 5752 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
5753 | S: Maintained | 5753 | S: Maintained |
5754 | F: drivers/net/wireless/rtlwifi/ | 5754 | F: drivers/net/wireless/rtlwifi/ |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index b869a358ce43..f27e9732951d 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2585,35 +2585,6 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, | |||
2585 | return 0; | 2585 | return 0; |
2586 | } | 2586 | } |
2587 | 2587 | ||
2588 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
2589 | struct ieee80211_channel *chan, | ||
2590 | enum nl80211_channel_type channel_type) | ||
2591 | { | ||
2592 | struct ath6kl_vif *vif; | ||
2593 | |||
2594 | /* | ||
2595 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2596 | * device itself, instead of a particular VIF. | ||
2597 | * | ||
2598 | * FIXME: To be handled properly when monitor mode is supported. | ||
2599 | */ | ||
2600 | if (!dev) | ||
2601 | return -EBUSY; | ||
2602 | |||
2603 | vif = netdev_priv(dev); | ||
2604 | |||
2605 | if (!ath6kl_cfg80211_ready(vif)) | ||
2606 | return -EIO; | ||
2607 | |||
2608 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | ||
2609 | __func__, chan->center_freq, chan->hw_value); | ||
2610 | vif->next_chan = chan->center_freq; | ||
2611 | vif->next_ch_type = channel_type; | ||
2612 | vif->next_ch_band = chan->band; | ||
2613 | |||
2614 | return 0; | ||
2615 | } | ||
2616 | |||
2617 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | 2588 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, |
2618 | u8 *rsn_capab) | 2589 | u8 *rsn_capab) |
2619 | { | 2590 | { |
@@ -2791,7 +2762,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2791 | p.ssid_len = vif->ssid_len; | 2762 | p.ssid_len = vif->ssid_len; |
2792 | memcpy(p.ssid, vif->ssid, vif->ssid_len); | 2763 | memcpy(p.ssid, vif->ssid, vif->ssid_len); |
2793 | p.dot11_auth_mode = vif->dot11_auth_mode; | 2764 | p.dot11_auth_mode = vif->dot11_auth_mode; |
2794 | p.ch = cpu_to_le16(vif->next_chan); | 2765 | p.ch = cpu_to_le16(info->channel->center_freq); |
2795 | 2766 | ||
2796 | /* Enable uAPSD support by default */ | 2767 | /* Enable uAPSD support by default */ |
2797 | res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); | 2768 | res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); |
@@ -2815,8 +2786,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2815 | return res; | 2786 | return res; |
2816 | } | 2787 | } |
2817 | 2788 | ||
2818 | if (ath6kl_set_htcap(vif, vif->next_ch_band, | 2789 | if (ath6kl_set_htcap(vif, info->channel->band, |
2819 | vif->next_ch_type != NL80211_CHAN_NO_HT)) | 2790 | info->channel_type != NL80211_CHAN_NO_HT)) |
2820 | return -EIO; | 2791 | return -EIO; |
2821 | 2792 | ||
2822 | /* | 2793 | /* |
@@ -3271,7 +3242,6 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
3271 | .suspend = __ath6kl_cfg80211_suspend, | 3242 | .suspend = __ath6kl_cfg80211_suspend, |
3272 | .resume = __ath6kl_cfg80211_resume, | 3243 | .resume = __ath6kl_cfg80211_resume, |
3273 | #endif | 3244 | #endif |
3274 | .set_channel = ath6kl_set_channel, | ||
3275 | .start_ap = ath6kl_start_ap, | 3245 | .start_ap = ath6kl_start_ap, |
3276 | .change_beacon = ath6kl_change_beacon, | 3246 | .change_beacon = ath6kl_change_beacon, |
3277 | .stop_ap = ath6kl_stop_ap, | 3247 | .stop_ap = ath6kl_stop_ap, |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 4d9c6f142698..8443b2a4133e 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -553,9 +553,6 @@ struct ath6kl_vif { | |||
553 | u32 last_cancel_roc_id; | 553 | u32 last_cancel_roc_id; |
554 | u32 send_action_id; | 554 | u32 send_action_id; |
555 | bool probe_req_report; | 555 | bool probe_req_report; |
556 | u16 next_chan; | ||
557 | enum nl80211_channel_type next_ch_type; | ||
558 | enum ieee80211_band next_ch_band; | ||
559 | u16 assoc_bss_beacon_int; | 556 | u16 assoc_bss_beacon_int; |
560 | u16 listen_intvl_t; | 557 | u16 listen_intvl_t; |
561 | u16 bmiss_time_t; | 558 | u16 bmiss_time_t; |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index e5524470529c..b836f2795114 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -598,7 +598,6 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel) | |||
598 | 598 | ||
599 | struct ath6kl *ar = vif->ar; | 599 | struct ath6kl *ar = vif->ar; |
600 | 600 | ||
601 | vif->next_chan = channel; | ||
602 | vif->profile.ch = cpu_to_le16(channel); | 601 | vif->profile.ch = cpu_to_le16(channel); |
603 | 602 | ||
604 | switch (vif->nw_type) { | 603 | switch (vif->nw_type) { |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 3f0b84723789..9c41232b0cd0 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -3,7 +3,9 @@ ath9k-y += beacon.o \ | |||
3 | init.o \ | 3 | init.o \ |
4 | main.o \ | 4 | main.o \ |
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o | 6 | xmit.o \ |
7 | link.o \ | ||
8 | antenna.o | ||
7 | 9 | ||
8 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o | 10 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o |
9 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | 11 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 5e47ca6d16a8..4a4e8a2b9d2c 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -126,7 +126,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
126 | sc->irq = irq; | 126 | sc->irq = irq; |
127 | 127 | ||
128 | /* Will be cleared in ath9k_start() */ | 128 | /* Will be cleared in ath9k_start() */ |
129 | sc->sc_flags |= SC_OP_INVALID; | 129 | set_bit(SC_OP_INVALID, &sc->sc_flags); |
130 | 130 | ||
131 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 131 | ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
132 | if (ret) { | 132 | if (ret) { |
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c new file mode 100644 index 000000000000..bbcfeb3b2a60 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
@@ -0,0 +1,776 @@ | |||
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 "ath9k.h" | ||
18 | |||
19 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | ||
20 | int mindelta, int main_rssi_avg, | ||
21 | int alt_rssi_avg, int pkt_count) | ||
22 | { | ||
23 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
24 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | ||
25 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
26 | } | ||
27 | |||
28 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | ||
29 | int curr_main_set, int curr_alt_set, | ||
30 | int alt_rssi_avg, int main_rssi_avg) | ||
31 | { | ||
32 | bool result = false; | ||
33 | switch (div_group) { | ||
34 | case 0: | ||
35 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
36 | result = true; | ||
37 | break; | ||
38 | case 1: | ||
39 | case 2: | ||
40 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | ||
41 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | ||
42 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | ||
43 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | ||
44 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | ||
45 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | ||
46 | (alt_rssi_avg >= 4)) | ||
47 | result = true; | ||
48 | else | ||
49 | result = false; | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | return result; | ||
54 | } | ||
55 | |||
56 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
57 | struct ath_hw_antcomb_conf ant_conf, | ||
58 | int main_rssi_avg) | ||
59 | { | ||
60 | antcomb->quick_scan_cnt = 0; | ||
61 | |||
62 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
63 | antcomb->rssi_lna2 = main_rssi_avg; | ||
64 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
65 | antcomb->rssi_lna1 = main_rssi_avg; | ||
66 | |||
67 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
68 | case 0x10: /* LNA2 A-B */ | ||
69 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
70 | antcomb->first_quick_scan_conf = | ||
71 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
72 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
73 | break; | ||
74 | case 0x20: /* LNA1 A-B */ | ||
75 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
76 | antcomb->first_quick_scan_conf = | ||
77 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
78 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
79 | break; | ||
80 | case 0x21: /* LNA1 LNA2 */ | ||
81 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
82 | antcomb->first_quick_scan_conf = | ||
83 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
84 | antcomb->second_quick_scan_conf = | ||
85 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
86 | break; | ||
87 | case 0x12: /* LNA2 LNA1 */ | ||
88 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
89 | antcomb->first_quick_scan_conf = | ||
90 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
91 | antcomb->second_quick_scan_conf = | ||
92 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
93 | break; | ||
94 | case 0x13: /* LNA2 A+B */ | ||
95 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
96 | antcomb->first_quick_scan_conf = | ||
97 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
98 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
99 | break; | ||
100 | case 0x23: /* LNA1 A+B */ | ||
101 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
102 | antcomb->first_quick_scan_conf = | ||
103 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
104 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
105 | break; | ||
106 | default: | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
112 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
113 | int main_rssi_avg, int alt_rssi_avg, | ||
114 | int alt_ratio) | ||
115 | { | ||
116 | /* alt_good */ | ||
117 | switch (antcomb->quick_scan_cnt) { | ||
118 | case 0: | ||
119 | /* set alt to main, and alt to first conf */ | ||
120 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
121 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
122 | break; | ||
123 | case 1: | ||
124 | /* set alt to main, and alt to first conf */ | ||
125 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
126 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
127 | antcomb->rssi_first = main_rssi_avg; | ||
128 | antcomb->rssi_second = alt_rssi_avg; | ||
129 | |||
130 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
131 | /* main is LNA1 */ | ||
132 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
133 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
134 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
135 | main_rssi_avg, alt_rssi_avg, | ||
136 | antcomb->total_pkt_count)) | ||
137 | antcomb->first_ratio = true; | ||
138 | else | ||
139 | antcomb->first_ratio = false; | ||
140 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
141 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
142 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
143 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
144 | main_rssi_avg, alt_rssi_avg, | ||
145 | antcomb->total_pkt_count)) | ||
146 | antcomb->first_ratio = true; | ||
147 | else | ||
148 | antcomb->first_ratio = false; | ||
149 | } else { | ||
150 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
151 | (alt_rssi_avg > main_rssi_avg + | ||
152 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
153 | (alt_rssi_avg > main_rssi_avg)) && | ||
154 | (antcomb->total_pkt_count > 50)) | ||
155 | antcomb->first_ratio = true; | ||
156 | else | ||
157 | antcomb->first_ratio = false; | ||
158 | } | ||
159 | break; | ||
160 | case 2: | ||
161 | antcomb->alt_good = false; | ||
162 | antcomb->scan_not_start = false; | ||
163 | antcomb->scan = false; | ||
164 | antcomb->rssi_first = main_rssi_avg; | ||
165 | antcomb->rssi_third = alt_rssi_avg; | ||
166 | |||
167 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
168 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
169 | else if (antcomb->second_quick_scan_conf == | ||
170 | ATH_ANT_DIV_COMB_LNA2) | ||
171 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
172 | else if (antcomb->second_quick_scan_conf == | ||
173 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
174 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
175 | antcomb->rssi_lna2 = main_rssi_avg; | ||
176 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
177 | antcomb->rssi_lna1 = main_rssi_avg; | ||
178 | } | ||
179 | |||
180 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
181 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
182 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
183 | else | ||
184 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
185 | |||
186 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
187 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
188 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
189 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
190 | main_rssi_avg, alt_rssi_avg, | ||
191 | antcomb->total_pkt_count)) | ||
192 | antcomb->second_ratio = true; | ||
193 | else | ||
194 | antcomb->second_ratio = false; | ||
195 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
196 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
197 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
198 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
199 | main_rssi_avg, alt_rssi_avg, | ||
200 | antcomb->total_pkt_count)) | ||
201 | antcomb->second_ratio = true; | ||
202 | else | ||
203 | antcomb->second_ratio = false; | ||
204 | } else { | ||
205 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
206 | (alt_rssi_avg > main_rssi_avg + | ||
207 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
208 | (alt_rssi_avg > main_rssi_avg)) && | ||
209 | (antcomb->total_pkt_count > 50)) | ||
210 | antcomb->second_ratio = true; | ||
211 | else | ||
212 | antcomb->second_ratio = false; | ||
213 | } | ||
214 | |||
215 | /* set alt to the conf with maximun ratio */ | ||
216 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
217 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
218 | /* first alt*/ | ||
219 | if ((antcomb->first_quick_scan_conf == | ||
220 | ATH_ANT_DIV_COMB_LNA1) || | ||
221 | (antcomb->first_quick_scan_conf == | ||
222 | ATH_ANT_DIV_COMB_LNA2)) | ||
223 | /* Set alt LNA1 or LNA2*/ | ||
224 | if (div_ant_conf->main_lna_conf == | ||
225 | ATH_ANT_DIV_COMB_LNA2) | ||
226 | div_ant_conf->alt_lna_conf = | ||
227 | ATH_ANT_DIV_COMB_LNA1; | ||
228 | else | ||
229 | div_ant_conf->alt_lna_conf = | ||
230 | ATH_ANT_DIV_COMB_LNA2; | ||
231 | else | ||
232 | /* Set alt to A+B or A-B */ | ||
233 | div_ant_conf->alt_lna_conf = | ||
234 | antcomb->first_quick_scan_conf; | ||
235 | } else if ((antcomb->second_quick_scan_conf == | ||
236 | ATH_ANT_DIV_COMB_LNA1) || | ||
237 | (antcomb->second_quick_scan_conf == | ||
238 | ATH_ANT_DIV_COMB_LNA2)) { | ||
239 | /* Set alt LNA1 or LNA2 */ | ||
240 | if (div_ant_conf->main_lna_conf == | ||
241 | ATH_ANT_DIV_COMB_LNA2) | ||
242 | div_ant_conf->alt_lna_conf = | ||
243 | ATH_ANT_DIV_COMB_LNA1; | ||
244 | else | ||
245 | div_ant_conf->alt_lna_conf = | ||
246 | ATH_ANT_DIV_COMB_LNA2; | ||
247 | } else { | ||
248 | /* Set alt to A+B or A-B */ | ||
249 | div_ant_conf->alt_lna_conf = | ||
250 | antcomb->second_quick_scan_conf; | ||
251 | } | ||
252 | } else if (antcomb->first_ratio) { | ||
253 | /* first alt */ | ||
254 | if ((antcomb->first_quick_scan_conf == | ||
255 | ATH_ANT_DIV_COMB_LNA1) || | ||
256 | (antcomb->first_quick_scan_conf == | ||
257 | ATH_ANT_DIV_COMB_LNA2)) | ||
258 | /* Set alt LNA1 or LNA2 */ | ||
259 | if (div_ant_conf->main_lna_conf == | ||
260 | ATH_ANT_DIV_COMB_LNA2) | ||
261 | div_ant_conf->alt_lna_conf = | ||
262 | ATH_ANT_DIV_COMB_LNA1; | ||
263 | else | ||
264 | div_ant_conf->alt_lna_conf = | ||
265 | ATH_ANT_DIV_COMB_LNA2; | ||
266 | else | ||
267 | /* Set alt to A+B or A-B */ | ||
268 | div_ant_conf->alt_lna_conf = | ||
269 | antcomb->first_quick_scan_conf; | ||
270 | } else if (antcomb->second_ratio) { | ||
271 | /* second alt */ | ||
272 | if ((antcomb->second_quick_scan_conf == | ||
273 | ATH_ANT_DIV_COMB_LNA1) || | ||
274 | (antcomb->second_quick_scan_conf == | ||
275 | ATH_ANT_DIV_COMB_LNA2)) | ||
276 | /* Set alt LNA1 or LNA2 */ | ||
277 | if (div_ant_conf->main_lna_conf == | ||
278 | ATH_ANT_DIV_COMB_LNA2) | ||
279 | div_ant_conf->alt_lna_conf = | ||
280 | ATH_ANT_DIV_COMB_LNA1; | ||
281 | else | ||
282 | div_ant_conf->alt_lna_conf = | ||
283 | ATH_ANT_DIV_COMB_LNA2; | ||
284 | else | ||
285 | /* Set alt to A+B or A-B */ | ||
286 | div_ant_conf->alt_lna_conf = | ||
287 | antcomb->second_quick_scan_conf; | ||
288 | } else { | ||
289 | /* main is largest */ | ||
290 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
291 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
292 | /* Set alt LNA1 or LNA2 */ | ||
293 | if (div_ant_conf->main_lna_conf == | ||
294 | ATH_ANT_DIV_COMB_LNA2) | ||
295 | div_ant_conf->alt_lna_conf = | ||
296 | ATH_ANT_DIV_COMB_LNA1; | ||
297 | else | ||
298 | div_ant_conf->alt_lna_conf = | ||
299 | ATH_ANT_DIV_COMB_LNA2; | ||
300 | else | ||
301 | /* Set alt to A+B or A-B */ | ||
302 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
303 | } | ||
304 | break; | ||
305 | default: | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | ||
311 | struct ath_ant_comb *antcomb, | ||
312 | int alt_ratio) | ||
313 | { | ||
314 | if (ant_conf->div_group == 0) { | ||
315 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
316 | switch ((ant_conf->main_lna_conf << 4) | | ||
317 | ant_conf->alt_lna_conf) { | ||
318 | case 0x01: /* A-B LNA2 */ | ||
319 | ant_conf->fast_div_bias = 0x3b; | ||
320 | break; | ||
321 | case 0x02: /* A-B LNA1 */ | ||
322 | ant_conf->fast_div_bias = 0x3d; | ||
323 | break; | ||
324 | case 0x03: /* A-B A+B */ | ||
325 | ant_conf->fast_div_bias = 0x1; | ||
326 | break; | ||
327 | case 0x10: /* LNA2 A-B */ | ||
328 | ant_conf->fast_div_bias = 0x7; | ||
329 | break; | ||
330 | case 0x12: /* LNA2 LNA1 */ | ||
331 | ant_conf->fast_div_bias = 0x2; | ||
332 | break; | ||
333 | case 0x13: /* LNA2 A+B */ | ||
334 | ant_conf->fast_div_bias = 0x7; | ||
335 | break; | ||
336 | case 0x20: /* LNA1 A-B */ | ||
337 | ant_conf->fast_div_bias = 0x6; | ||
338 | break; | ||
339 | case 0x21: /* LNA1 LNA2 */ | ||
340 | ant_conf->fast_div_bias = 0x0; | ||
341 | break; | ||
342 | case 0x23: /* LNA1 A+B */ | ||
343 | ant_conf->fast_div_bias = 0x6; | ||
344 | break; | ||
345 | case 0x30: /* A+B A-B */ | ||
346 | ant_conf->fast_div_bias = 0x1; | ||
347 | break; | ||
348 | case 0x31: /* A+B LNA2 */ | ||
349 | ant_conf->fast_div_bias = 0x3b; | ||
350 | break; | ||
351 | case 0x32: /* A+B LNA1 */ | ||
352 | ant_conf->fast_div_bias = 0x3d; | ||
353 | break; | ||
354 | default: | ||
355 | break; | ||
356 | } | ||
357 | } else if (ant_conf->div_group == 1) { | ||
358 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
359 | switch ((ant_conf->main_lna_conf << 4) | | ||
360 | ant_conf->alt_lna_conf) { | ||
361 | case 0x01: /* A-B LNA2 */ | ||
362 | ant_conf->fast_div_bias = 0x1; | ||
363 | ant_conf->main_gaintb = 0; | ||
364 | ant_conf->alt_gaintb = 0; | ||
365 | break; | ||
366 | case 0x02: /* A-B LNA1 */ | ||
367 | ant_conf->fast_div_bias = 0x1; | ||
368 | ant_conf->main_gaintb = 0; | ||
369 | ant_conf->alt_gaintb = 0; | ||
370 | break; | ||
371 | case 0x03: /* A-B A+B */ | ||
372 | ant_conf->fast_div_bias = 0x1; | ||
373 | ant_conf->main_gaintb = 0; | ||
374 | ant_conf->alt_gaintb = 0; | ||
375 | break; | ||
376 | case 0x10: /* LNA2 A-B */ | ||
377 | if (!(antcomb->scan) && | ||
378 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
379 | ant_conf->fast_div_bias = 0x3f; | ||
380 | else | ||
381 | ant_conf->fast_div_bias = 0x1; | ||
382 | ant_conf->main_gaintb = 0; | ||
383 | ant_conf->alt_gaintb = 0; | ||
384 | break; | ||
385 | case 0x12: /* LNA2 LNA1 */ | ||
386 | ant_conf->fast_div_bias = 0x1; | ||
387 | ant_conf->main_gaintb = 0; | ||
388 | ant_conf->alt_gaintb = 0; | ||
389 | break; | ||
390 | case 0x13: /* LNA2 A+B */ | ||
391 | if (!(antcomb->scan) && | ||
392 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
393 | ant_conf->fast_div_bias = 0x3f; | ||
394 | else | ||
395 | ant_conf->fast_div_bias = 0x1; | ||
396 | ant_conf->main_gaintb = 0; | ||
397 | ant_conf->alt_gaintb = 0; | ||
398 | break; | ||
399 | case 0x20: /* LNA1 A-B */ | ||
400 | if (!(antcomb->scan) && | ||
401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
402 | ant_conf->fast_div_bias = 0x3f; | ||
403 | else | ||
404 | ant_conf->fast_div_bias = 0x1; | ||
405 | ant_conf->main_gaintb = 0; | ||
406 | ant_conf->alt_gaintb = 0; | ||
407 | break; | ||
408 | case 0x21: /* LNA1 LNA2 */ | ||
409 | ant_conf->fast_div_bias = 0x1; | ||
410 | ant_conf->main_gaintb = 0; | ||
411 | ant_conf->alt_gaintb = 0; | ||
412 | break; | ||
413 | case 0x23: /* LNA1 A+B */ | ||
414 | if (!(antcomb->scan) && | ||
415 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
416 | ant_conf->fast_div_bias = 0x3f; | ||
417 | else | ||
418 | ant_conf->fast_div_bias = 0x1; | ||
419 | ant_conf->main_gaintb = 0; | ||
420 | ant_conf->alt_gaintb = 0; | ||
421 | break; | ||
422 | case 0x30: /* A+B A-B */ | ||
423 | ant_conf->fast_div_bias = 0x1; | ||
424 | ant_conf->main_gaintb = 0; | ||
425 | ant_conf->alt_gaintb = 0; | ||
426 | break; | ||
427 | case 0x31: /* A+B LNA2 */ | ||
428 | ant_conf->fast_div_bias = 0x1; | ||
429 | ant_conf->main_gaintb = 0; | ||
430 | ant_conf->alt_gaintb = 0; | ||
431 | break; | ||
432 | case 0x32: /* A+B LNA1 */ | ||
433 | ant_conf->fast_div_bias = 0x1; | ||
434 | ant_conf->main_gaintb = 0; | ||
435 | ant_conf->alt_gaintb = 0; | ||
436 | break; | ||
437 | default: | ||
438 | break; | ||
439 | } | ||
440 | } else if (ant_conf->div_group == 2) { | ||
441 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
442 | switch ((ant_conf->main_lna_conf << 4) | | ||
443 | ant_conf->alt_lna_conf) { | ||
444 | case 0x01: /* A-B LNA2 */ | ||
445 | ant_conf->fast_div_bias = 0x1; | ||
446 | ant_conf->main_gaintb = 0; | ||
447 | ant_conf->alt_gaintb = 0; | ||
448 | break; | ||
449 | case 0x02: /* A-B LNA1 */ | ||
450 | ant_conf->fast_div_bias = 0x1; | ||
451 | ant_conf->main_gaintb = 0; | ||
452 | ant_conf->alt_gaintb = 0; | ||
453 | break; | ||
454 | case 0x03: /* A-B A+B */ | ||
455 | ant_conf->fast_div_bias = 0x1; | ||
456 | ant_conf->main_gaintb = 0; | ||
457 | ant_conf->alt_gaintb = 0; | ||
458 | break; | ||
459 | case 0x10: /* LNA2 A-B */ | ||
460 | if (!(antcomb->scan) && | ||
461 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
462 | ant_conf->fast_div_bias = 0x1; | ||
463 | else | ||
464 | ant_conf->fast_div_bias = 0x2; | ||
465 | ant_conf->main_gaintb = 0; | ||
466 | ant_conf->alt_gaintb = 0; | ||
467 | break; | ||
468 | case 0x12: /* LNA2 LNA1 */ | ||
469 | ant_conf->fast_div_bias = 0x1; | ||
470 | ant_conf->main_gaintb = 0; | ||
471 | ant_conf->alt_gaintb = 0; | ||
472 | break; | ||
473 | case 0x13: /* LNA2 A+B */ | ||
474 | if (!(antcomb->scan) && | ||
475 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
476 | ant_conf->fast_div_bias = 0x1; | ||
477 | else | ||
478 | ant_conf->fast_div_bias = 0x2; | ||
479 | ant_conf->main_gaintb = 0; | ||
480 | ant_conf->alt_gaintb = 0; | ||
481 | break; | ||
482 | case 0x20: /* LNA1 A-B */ | ||
483 | if (!(antcomb->scan) && | ||
484 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
485 | ant_conf->fast_div_bias = 0x1; | ||
486 | else | ||
487 | ant_conf->fast_div_bias = 0x2; | ||
488 | ant_conf->main_gaintb = 0; | ||
489 | ant_conf->alt_gaintb = 0; | ||
490 | break; | ||
491 | case 0x21: /* LNA1 LNA2 */ | ||
492 | ant_conf->fast_div_bias = 0x1; | ||
493 | ant_conf->main_gaintb = 0; | ||
494 | ant_conf->alt_gaintb = 0; | ||
495 | break; | ||
496 | case 0x23: /* LNA1 A+B */ | ||
497 | if (!(antcomb->scan) && | ||
498 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
499 | ant_conf->fast_div_bias = 0x1; | ||
500 | else | ||
501 | ant_conf->fast_div_bias = 0x2; | ||
502 | ant_conf->main_gaintb = 0; | ||
503 | ant_conf->alt_gaintb = 0; | ||
504 | break; | ||
505 | case 0x30: /* A+B A-B */ | ||
506 | ant_conf->fast_div_bias = 0x1; | ||
507 | ant_conf->main_gaintb = 0; | ||
508 | ant_conf->alt_gaintb = 0; | ||
509 | break; | ||
510 | case 0x31: /* A+B LNA2 */ | ||
511 | ant_conf->fast_div_bias = 0x1; | ||
512 | ant_conf->main_gaintb = 0; | ||
513 | ant_conf->alt_gaintb = 0; | ||
514 | break; | ||
515 | case 0x32: /* A+B LNA1 */ | ||
516 | ant_conf->fast_div_bias = 0x1; | ||
517 | ant_conf->main_gaintb = 0; | ||
518 | ant_conf->alt_gaintb = 0; | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | } | ||
524 | } | ||
525 | |||
526 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
527 | { | ||
528 | struct ath_hw_antcomb_conf div_ant_conf; | ||
529 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
530 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
531 | int curr_main_set; | ||
532 | int main_rssi = rs->rs_rssi_ctl0; | ||
533 | int alt_rssi = rs->rs_rssi_ctl1; | ||
534 | int rx_ant_conf, main_ant_conf; | ||
535 | bool short_scan = false; | ||
536 | |||
537 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
538 | ATH_ANT_RX_MASK; | ||
539 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
540 | ATH_ANT_RX_MASK; | ||
541 | |||
542 | /* Record packet only when both main_rssi and alt_rssi is positive */ | ||
543 | if (main_rssi > 0 && alt_rssi > 0) { | ||
544 | antcomb->total_pkt_count++; | ||
545 | antcomb->main_total_rssi += main_rssi; | ||
546 | antcomb->alt_total_rssi += alt_rssi; | ||
547 | if (main_ant_conf == rx_ant_conf) | ||
548 | antcomb->main_recv_cnt++; | ||
549 | else | ||
550 | antcomb->alt_recv_cnt++; | ||
551 | } | ||
552 | |||
553 | /* Short scan check */ | ||
554 | if (antcomb->scan && antcomb->alt_good) { | ||
555 | if (time_after(jiffies, antcomb->scan_start_time + | ||
556 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
557 | short_scan = true; | ||
558 | else | ||
559 | if (antcomb->total_pkt_count == | ||
560 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
561 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
562 | antcomb->total_pkt_count); | ||
563 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
564 | short_scan = true; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
569 | rs->rs_moreaggr) && !short_scan) | ||
570 | return; | ||
571 | |||
572 | if (antcomb->total_pkt_count) { | ||
573 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
574 | antcomb->total_pkt_count); | ||
575 | main_rssi_avg = (antcomb->main_total_rssi / | ||
576 | antcomb->total_pkt_count); | ||
577 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
578 | antcomb->total_pkt_count); | ||
579 | } | ||
580 | |||
581 | |||
582 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
583 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
584 | curr_main_set = div_ant_conf.main_lna_conf; | ||
585 | |||
586 | antcomb->count++; | ||
587 | |||
588 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
589 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
590 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
591 | main_rssi_avg); | ||
592 | antcomb->alt_good = true; | ||
593 | } else { | ||
594 | antcomb->alt_good = false; | ||
595 | } | ||
596 | |||
597 | antcomb->count = 0; | ||
598 | antcomb->scan = true; | ||
599 | antcomb->scan_not_start = true; | ||
600 | } | ||
601 | |||
602 | if (!antcomb->scan) { | ||
603 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | ||
604 | alt_ratio, curr_main_set, curr_alt_set, | ||
605 | alt_rssi_avg, main_rssi_avg)) { | ||
606 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
607 | /* Switch main and alt LNA */ | ||
608 | div_ant_conf.main_lna_conf = | ||
609 | ATH_ANT_DIV_COMB_LNA2; | ||
610 | div_ant_conf.alt_lna_conf = | ||
611 | ATH_ANT_DIV_COMB_LNA1; | ||
612 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
613 | div_ant_conf.main_lna_conf = | ||
614 | ATH_ANT_DIV_COMB_LNA1; | ||
615 | div_ant_conf.alt_lna_conf = | ||
616 | ATH_ANT_DIV_COMB_LNA2; | ||
617 | } | ||
618 | |||
619 | goto div_comb_done; | ||
620 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
621 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
622 | /* Set alt to another LNA */ | ||
623 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
624 | div_ant_conf.alt_lna_conf = | ||
625 | ATH_ANT_DIV_COMB_LNA1; | ||
626 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
627 | div_ant_conf.alt_lna_conf = | ||
628 | ATH_ANT_DIV_COMB_LNA2; | ||
629 | |||
630 | goto div_comb_done; | ||
631 | } | ||
632 | |||
633 | if ((alt_rssi_avg < (main_rssi_avg + | ||
634 | div_ant_conf.lna1_lna2_delta))) | ||
635 | goto div_comb_done; | ||
636 | } | ||
637 | |||
638 | if (!antcomb->scan_not_start) { | ||
639 | switch (curr_alt_set) { | ||
640 | case ATH_ANT_DIV_COMB_LNA2: | ||
641 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
642 | antcomb->rssi_lna1 = main_rssi_avg; | ||
643 | antcomb->scan = true; | ||
644 | /* set to A+B */ | ||
645 | div_ant_conf.main_lna_conf = | ||
646 | ATH_ANT_DIV_COMB_LNA1; | ||
647 | div_ant_conf.alt_lna_conf = | ||
648 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
649 | break; | ||
650 | case ATH_ANT_DIV_COMB_LNA1: | ||
651 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
652 | antcomb->rssi_lna2 = main_rssi_avg; | ||
653 | antcomb->scan = true; | ||
654 | /* set to A+B */ | ||
655 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
656 | div_ant_conf.alt_lna_conf = | ||
657 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
658 | break; | ||
659 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
660 | antcomb->rssi_add = alt_rssi_avg; | ||
661 | antcomb->scan = true; | ||
662 | /* set to A-B */ | ||
663 | div_ant_conf.alt_lna_conf = | ||
664 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
665 | break; | ||
666 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
667 | antcomb->rssi_sub = alt_rssi_avg; | ||
668 | antcomb->scan = false; | ||
669 | if (antcomb->rssi_lna2 > | ||
670 | (antcomb->rssi_lna1 + | ||
671 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
672 | /* use LNA2 as main LNA */ | ||
673 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
674 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
675 | /* set to A+B */ | ||
676 | div_ant_conf.main_lna_conf = | ||
677 | ATH_ANT_DIV_COMB_LNA2; | ||
678 | div_ant_conf.alt_lna_conf = | ||
679 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
680 | } else if (antcomb->rssi_sub > | ||
681 | antcomb->rssi_lna1) { | ||
682 | /* set to A-B */ | ||
683 | div_ant_conf.main_lna_conf = | ||
684 | ATH_ANT_DIV_COMB_LNA2; | ||
685 | div_ant_conf.alt_lna_conf = | ||
686 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
687 | } else { | ||
688 | /* set to LNA1 */ | ||
689 | div_ant_conf.main_lna_conf = | ||
690 | ATH_ANT_DIV_COMB_LNA2; | ||
691 | div_ant_conf.alt_lna_conf = | ||
692 | ATH_ANT_DIV_COMB_LNA1; | ||
693 | } | ||
694 | } else { | ||
695 | /* use LNA1 as main LNA */ | ||
696 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
697 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
698 | /* set to A+B */ | ||
699 | div_ant_conf.main_lna_conf = | ||
700 | ATH_ANT_DIV_COMB_LNA1; | ||
701 | div_ant_conf.alt_lna_conf = | ||
702 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
703 | } else if (antcomb->rssi_sub > | ||
704 | antcomb->rssi_lna1) { | ||
705 | /* set to A-B */ | ||
706 | div_ant_conf.main_lna_conf = | ||
707 | ATH_ANT_DIV_COMB_LNA1; | ||
708 | div_ant_conf.alt_lna_conf = | ||
709 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
710 | } else { | ||
711 | /* set to LNA2 */ | ||
712 | div_ant_conf.main_lna_conf = | ||
713 | ATH_ANT_DIV_COMB_LNA1; | ||
714 | div_ant_conf.alt_lna_conf = | ||
715 | ATH_ANT_DIV_COMB_LNA2; | ||
716 | } | ||
717 | } | ||
718 | break; | ||
719 | default: | ||
720 | break; | ||
721 | } | ||
722 | } else { | ||
723 | if (!antcomb->alt_good) { | ||
724 | antcomb->scan_not_start = false; | ||
725 | /* Set alt to another LNA */ | ||
726 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
727 | div_ant_conf.main_lna_conf = | ||
728 | ATH_ANT_DIV_COMB_LNA2; | ||
729 | div_ant_conf.alt_lna_conf = | ||
730 | ATH_ANT_DIV_COMB_LNA1; | ||
731 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
732 | div_ant_conf.main_lna_conf = | ||
733 | ATH_ANT_DIV_COMB_LNA1; | ||
734 | div_ant_conf.alt_lna_conf = | ||
735 | ATH_ANT_DIV_COMB_LNA2; | ||
736 | } | ||
737 | goto div_comb_done; | ||
738 | } | ||
739 | } | ||
740 | |||
741 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
742 | main_rssi_avg, alt_rssi_avg, | ||
743 | alt_ratio); | ||
744 | |||
745 | antcomb->quick_scan_cnt++; | ||
746 | |||
747 | div_comb_done: | ||
748 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | ||
749 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
750 | |||
751 | antcomb->scan_start_time = jiffies; | ||
752 | antcomb->total_pkt_count = 0; | ||
753 | antcomb->main_total_rssi = 0; | ||
754 | antcomb->alt_total_rssi = 0; | ||
755 | antcomb->main_recv_cnt = 0; | ||
756 | antcomb->alt_recv_cnt = 0; | ||
757 | } | ||
758 | |||
759 | void ath_ant_comb_update(struct ath_softc *sc) | ||
760 | { | ||
761 | struct ath_hw *ah = sc->sc_ah; | ||
762 | struct ath_hw_antcomb_conf div_ant_conf; | ||
763 | u8 lna_conf; | ||
764 | |||
765 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
766 | |||
767 | if (sc->ant_rx == 1) | ||
768 | lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
769 | else | ||
770 | lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
771 | |||
772 | div_ant_conf.main_lna_conf = lna_conf; | ||
773 | div_ant_conf.alt_lna_conf = lna_conf; | ||
774 | |||
775 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | ||
776 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 9fdd70fcaf5b..d7deb8c9f299 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -653,7 +653,6 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, | |||
653 | } | 653 | } |
654 | 654 | ||
655 | static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, | 655 | static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, |
656 | u8 num_chains, | ||
657 | struct coeff *coeff, | 656 | struct coeff *coeff, |
658 | bool is_reusable) | 657 | bool is_reusable) |
659 | { | 658 | { |
@@ -677,7 +676,9 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, | |||
677 | } | 676 | } |
678 | 677 | ||
679 | /* Load the average of 2 passes */ | 678 | /* Load the average of 2 passes */ |
680 | for (i = 0; i < num_chains; i++) { | 679 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
680 | if (!(ah->txchainmask & (1 << i))) | ||
681 | continue; | ||
681 | nmeasurement = REG_READ_FIELD(ah, | 682 | nmeasurement = REG_READ_FIELD(ah, |
682 | AR_PHY_TX_IQCAL_STATUS_B0, | 683 | AR_PHY_TX_IQCAL_STATUS_B0, |
683 | AR_PHY_CALIBRATED_GAINS_0); | 684 | AR_PHY_CALIBRATED_GAINS_0); |
@@ -767,16 +768,13 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
767 | }; | 768 | }; |
768 | struct coeff coeff; | 769 | struct coeff coeff; |
769 | s32 iq_res[6]; | 770 | s32 iq_res[6]; |
770 | u8 num_chains = 0; | ||
771 | int i, im, j; | 771 | int i, im, j; |
772 | int nmeasurement; | 772 | int nmeasurement; |
773 | 773 | ||
774 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 774 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
775 | if (ah->txchainmask & (1 << i)) | 775 | if (!(ah->txchainmask & (1 << i))) |
776 | num_chains++; | 776 | continue; |
777 | } | ||
778 | 777 | ||
779 | for (i = 0; i < num_chains; i++) { | ||
780 | nmeasurement = REG_READ_FIELD(ah, | 778 | nmeasurement = REG_READ_FIELD(ah, |
781 | AR_PHY_TX_IQCAL_STATUS_B0, | 779 | AR_PHY_TX_IQCAL_STATUS_B0, |
782 | AR_PHY_CALIBRATED_GAINS_0); | 780 | AR_PHY_CALIBRATED_GAINS_0); |
@@ -839,8 +837,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
839 | coeff.phs_coeff[i][im] -= 128; | 837 | coeff.phs_coeff[i][im] -= 128; |
840 | } | 838 | } |
841 | } | 839 | } |
842 | ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, | 840 | ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable); |
843 | &coeff, is_reusable); | ||
844 | 841 | ||
845 | return; | 842 | return; |
846 | 843 | ||
@@ -901,7 +898,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
901 | bool is_reusable = true, status = true; | 898 | bool is_reusable = true, status = true; |
902 | bool run_rtt_cal = false, run_agc_cal; | 899 | bool run_rtt_cal = false, run_agc_cal; |
903 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | 900 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); |
904 | bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
905 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | 901 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | |
906 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 902 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
907 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 903 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
@@ -970,7 +966,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
970 | } else if (caldata && !caldata->done_txiqcal_once) | 966 | } else if (caldata && !caldata->done_txiqcal_once) |
971 | run_agc_cal = true; | 967 | run_agc_cal = true; |
972 | 968 | ||
973 | if (mci && IS_CHAN_2GHZ(chan) && run_agc_cal) | 969 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
974 | ar9003_mci_init_cal_req(ah, &is_reusable); | 970 | ar9003_mci_init_cal_req(ah, &is_reusable); |
975 | 971 | ||
976 | if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) { | 972 | if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) { |
@@ -993,7 +989,7 @@ skip_tx_iqcal: | |||
993 | 0, AH_WAIT_TIMEOUT); | 989 | 0, AH_WAIT_TIMEOUT); |
994 | } | 990 | } |
995 | 991 | ||
996 | if (mci && IS_CHAN_2GHZ(chan) && run_agc_cal) | 992 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
997 | ar9003_mci_init_cal_done(ah); | 993 | ar9003_mci_init_cal_done(ah); |
998 | 994 | ||
999 | if (rtt && !run_rtt_cal) { | 995 | if (rtt && !run_rtt_cal) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ca881558da78..b1e59236d245 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3412,11 +3412,11 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
3412 | if (!dump_base_hdr) { | 3412 | if (!dump_base_hdr) { |
3413 | len += snprintf(buf + len, size - len, | 3413 | len += snprintf(buf + len, size - len, |
3414 | "%20s :\n", "2GHz modal Header"); | 3414 | "%20s :\n", "2GHz modal Header"); |
3415 | len += ar9003_dump_modal_eeprom(buf, len, size, | 3415 | len = ar9003_dump_modal_eeprom(buf, len, size, |
3416 | &eep->modalHeader2G); | 3416 | &eep->modalHeader2G); |
3417 | len += snprintf(buf + len, size - len, | 3417 | len += snprintf(buf + len, size - len, |
3418 | "%20s :\n", "5GHz modal Header"); | 3418 | "%20s :\n", "5GHz modal Header"); |
3419 | len += ar9003_dump_modal_eeprom(buf, len, size, | 3419 | len = ar9003_dump_modal_eeprom(buf, len, size, |
3420 | &eep->modalHeader5G); | 3420 | &eep->modalHeader5G); |
3421 | goto out; | 3421 | goto out; |
3422 | } | 3422 | } |
@@ -3613,6 +3613,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3613 | value = ar9003_switch_com_spdt_get(ah, is2ghz); | 3613 | value = ar9003_switch_com_spdt_get(ah, is2ghz); |
3614 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, | 3614 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, |
3615 | AR_SWITCH_TABLE_COM_SPDT_ALL, value); | 3615 | AR_SWITCH_TABLE_COM_SPDT_ALL, value); |
3616 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE); | ||
3616 | } | 3617 | } |
3617 | 3618 | ||
3618 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); | 3619 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index ffbb180f91e1..b1ced2a76da3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -35,31 +35,30 @@ static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, | |||
35 | struct ath_common *common = ath9k_hw_common(ah); | 35 | struct ath_common *common = ath9k_hw_common(ah); |
36 | 36 | ||
37 | while (time_out) { | 37 | while (time_out) { |
38 | if (REG_READ(ah, address) & bit_position) { | 38 | if (!(REG_READ(ah, address) & bit_position)) { |
39 | REG_WRITE(ah, address, bit_position); | 39 | udelay(10); |
40 | 40 | time_out -= 10; | |
41 | if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { | ||
42 | if (bit_position & | ||
43 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) | ||
44 | ar9003_mci_reset_req_wakeup(ah); | ||
45 | |||
46 | if (bit_position & | ||
47 | (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | | ||
48 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) | ||
49 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
50 | AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); | ||
51 | |||
52 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
53 | AR_MCI_INTERRUPT_RX_MSG); | ||
54 | } | ||
55 | break; | ||
56 | } | ||
57 | 41 | ||
58 | udelay(10); | 42 | if (time_out < 0) |
59 | time_out -= 10; | 43 | break; |
44 | else | ||
45 | continue; | ||
46 | } | ||
47 | REG_WRITE(ah, address, bit_position); | ||
60 | 48 | ||
61 | if (time_out < 0) | 49 | if (address != AR_MCI_INTERRUPT_RX_MSG_RAW) |
62 | break; | 50 | break; |
51 | |||
52 | if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) | ||
53 | ar9003_mci_reset_req_wakeup(ah); | ||
54 | |||
55 | if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | | ||
56 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) | ||
57 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | ||
58 | AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); | ||
59 | |||
60 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG); | ||
61 | break; | ||
63 | } | 62 | } |
64 | 63 | ||
65 | if (time_out <= 0) { | 64 | if (time_out <= 0) { |
@@ -127,14 +126,13 @@ static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, | |||
127 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 126 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
128 | u32 payload[4] = {0, 0, 0, 0}; | 127 | u32 payload[4] = {0, 0, 0, 0}; |
129 | 128 | ||
130 | if (!mci->bt_version_known && | 129 | if (mci->bt_version_known || |
131 | (mci->bt_state != MCI_BT_SLEEP)) { | 130 | (mci->bt_state == MCI_BT_SLEEP)) |
132 | MCI_GPM_SET_TYPE_OPCODE(payload, | 131 | return; |
133 | MCI_GPM_COEX_AGENT, | 132 | |
134 | MCI_GPM_COEX_VERSION_QUERY); | 133 | MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, |
135 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | 134 | MCI_GPM_COEX_VERSION_QUERY); |
136 | wait_done, true); | 135 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); |
137 | } | ||
138 | } | 136 | } |
139 | 137 | ||
140 | static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, | 138 | static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, |
@@ -158,15 +156,14 @@ static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, | |||
158 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 156 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
159 | u32 *payload = &mci->wlan_channels[0]; | 157 | u32 *payload = &mci->wlan_channels[0]; |
160 | 158 | ||
161 | if ((mci->wlan_channels_update == true) && | 159 | if (!mci->wlan_channels_update || |
162 | (mci->bt_state != MCI_BT_SLEEP)) { | 160 | (mci->bt_state == MCI_BT_SLEEP)) |
163 | MCI_GPM_SET_TYPE_OPCODE(payload, | 161 | return; |
164 | MCI_GPM_COEX_AGENT, | 162 | |
165 | MCI_GPM_COEX_WLAN_CHANNELS); | 163 | MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, |
166 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | 164 | MCI_GPM_COEX_WLAN_CHANNELS); |
167 | wait_done, true); | 165 | ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); |
168 | MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); | 166 | MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); |
169 | } | ||
170 | } | 167 | } |
171 | 168 | ||
172 | static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, | 169 | static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, |
@@ -174,29 +171,30 @@ static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, | |||
174 | { | 171 | { |
175 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 172 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
176 | u32 payload[4] = {0, 0, 0, 0}; | 173 | u32 payload[4] = {0, 0, 0, 0}; |
177 | bool query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | | 174 | bool query_btinfo; |
178 | MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); | ||
179 | |||
180 | if (mci->bt_state != MCI_BT_SLEEP) { | ||
181 | 175 | ||
182 | MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, | 176 | if (mci->bt_state == MCI_BT_SLEEP) |
183 | MCI_GPM_COEX_STATUS_QUERY); | 177 | return; |
184 | 178 | ||
185 | *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; | 179 | query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | |
180 | MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); | ||
181 | MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, | ||
182 | MCI_GPM_COEX_STATUS_QUERY); | ||
186 | 183 | ||
187 | /* | 184 | *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; |
188 | * If bt_status_query message is not sent successfully, | ||
189 | * then need_flush_btinfo should be set again. | ||
190 | */ | ||
191 | if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
192 | wait_done, true)) { | ||
193 | if (query_btinfo) | ||
194 | mci->need_flush_btinfo = true; | ||
195 | } | ||
196 | 185 | ||
186 | /* | ||
187 | * If bt_status_query message is not sent successfully, | ||
188 | * then need_flush_btinfo should be set again. | ||
189 | */ | ||
190 | if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, | ||
191 | wait_done, true)) { | ||
197 | if (query_btinfo) | 192 | if (query_btinfo) |
198 | mci->query_bt = false; | 193 | mci->need_flush_btinfo = true; |
199 | } | 194 | } |
195 | |||
196 | if (query_btinfo) | ||
197 | mci->query_bt = false; | ||
200 | } | 198 | } |
201 | 199 | ||
202 | static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, | 200 | static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, |
@@ -241,73 +239,73 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah) | |||
241 | ar9003_mci_remote_reset(ah, true); | 239 | ar9003_mci_remote_reset(ah, true); |
242 | ar9003_mci_send_req_wake(ah, true); | 240 | ar9003_mci_send_req_wake(ah, true); |
243 | 241 | ||
244 | if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 242 | if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
245 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { | 243 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) |
244 | goto clear_redunt; | ||
246 | 245 | ||
247 | mci->bt_state = MCI_BT_AWAKE; | 246 | mci->bt_state = MCI_BT_AWAKE; |
248 | 247 | ||
249 | /* | 248 | /* |
250 | * we don't need to send more remote_reset at this moment. | 249 | * we don't need to send more remote_reset at this moment. |
251 | * If BT receive first remote_reset, then BT HW will | 250 | * If BT receive first remote_reset, then BT HW will |
252 | * be cleaned up and will be able to receive req_wake | 251 | * be cleaned up and will be able to receive req_wake |
253 | * and BT HW will respond sys_waking. | 252 | * and BT HW will respond sys_waking. |
254 | * In this case, WLAN will receive BT's HW sys_waking. | 253 | * In this case, WLAN will receive BT's HW sys_waking. |
255 | * Otherwise, if BT SW missed initial remote_reset, | 254 | * Otherwise, if BT SW missed initial remote_reset, |
256 | * that remote_reset will still clean up BT MCI RX, | 255 | * that remote_reset will still clean up BT MCI RX, |
257 | * and the req_wake will wake BT up, | 256 | * and the req_wake will wake BT up, |
258 | * and BT SW will respond this req_wake with a remote_reset and | 257 | * and BT SW will respond this req_wake with a remote_reset and |
259 | * sys_waking. In this case, WLAN will receive BT's SW | 258 | * sys_waking. In this case, WLAN will receive BT's SW |
260 | * sys_waking. In either case, BT's RX is cleaned up. So we | 259 | * sys_waking. In either case, BT's RX is cleaned up. So we |
261 | * don't need to reply BT's remote_reset now, if any. | 260 | * don't need to reply BT's remote_reset now, if any. |
262 | * Similarly, if in any case, WLAN can receive BT's sys_waking, | 261 | * Similarly, if in any case, WLAN can receive BT's sys_waking, |
263 | * that means WLAN's RX is also fine. | 262 | * that means WLAN's RX is also fine. |
264 | */ | 263 | */ |
265 | ar9003_mci_send_sys_waking(ah, true); | 264 | ar9003_mci_send_sys_waking(ah, true); |
266 | udelay(10); | 265 | udelay(10); |
267 | 266 | ||
268 | /* | 267 | /* |
269 | * Set BT priority interrupt value to be 0xff to | 268 | * Set BT priority interrupt value to be 0xff to |
270 | * avoid having too many BT PRIORITY interrupts. | 269 | * avoid having too many BT PRIORITY interrupts. |
271 | */ | 270 | */ |
272 | REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); | 271 | REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); |
273 | REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); | 272 | REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); |
274 | REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); | 273 | REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); |
275 | REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); | 274 | REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); |
276 | REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); | 275 | REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); |
277 | 276 | ||
278 | /* | 277 | /* |
279 | * A contention reset will be received after send out | 278 | * A contention reset will be received after send out |
280 | * sys_waking. Also BT priority interrupt bits will be set. | 279 | * sys_waking. Also BT priority interrupt bits will be set. |
281 | * Clear those bits before the next step. | 280 | * Clear those bits before the next step. |
282 | */ | 281 | */ |
283 | 282 | ||
284 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 283 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
285 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST); | 284 | AR_MCI_INTERRUPT_RX_MSG_CONT_RST); |
286 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, | 285 | REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); |
287 | AR_MCI_INTERRUPT_BT_PRI); | ||
288 | 286 | ||
289 | if (mci->is_2g) { | 287 | if (mci->is_2g) { |
290 | ar9003_mci_send_lna_transfer(ah, true); | 288 | ar9003_mci_send_lna_transfer(ah, true); |
291 | udelay(5); | 289 | udelay(5); |
292 | } | 290 | } |
293 | 291 | ||
294 | if ((mci->is_2g && !mci->update_2g5g)) { | 292 | if ((mci->is_2g && !mci->update_2g5g)) { |
295 | if (ar9003_mci_wait_for_interrupt(ah, | 293 | if (ar9003_mci_wait_for_interrupt(ah, |
296 | AR_MCI_INTERRUPT_RX_MSG_RAW, | 294 | AR_MCI_INTERRUPT_RX_MSG_RAW, |
297 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, | 295 | AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, |
298 | mci_timeout)) | 296 | mci_timeout)) |
299 | ath_dbg(common, MCI, | 297 | ath_dbg(common, MCI, |
300 | "MCI WLAN has control over the LNA & BT obeys it\n"); | 298 | "MCI WLAN has control over the LNA & BT obeys it\n"); |
301 | else | 299 | else |
302 | ath_dbg(common, MCI, | 300 | ath_dbg(common, MCI, |
303 | "MCI BT didn't respond to LNA_TRANS\n"); | 301 | "MCI BT didn't respond to LNA_TRANS\n"); |
304 | } | ||
305 | } | 302 | } |
306 | 303 | ||
304 | clear_redunt: | ||
307 | /* Clear the extra redundant SYS_WAKING from BT */ | 305 | /* Clear the extra redundant SYS_WAKING from BT */ |
308 | if ((mci->bt_state == MCI_BT_AWAKE) && | 306 | if ((mci->bt_state == MCI_BT_AWAKE) && |
309 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 307 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
310 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && | 308 | AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && |
311 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 309 | (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
312 | AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { | 310 | AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { |
313 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 311 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
@@ -330,7 +328,6 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah) | |||
330 | } | 328 | } |
331 | 329 | ||
332 | mci->ready = false; | 330 | mci->ready = false; |
333 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
334 | } | 331 | } |
335 | 332 | ||
336 | static void ar9003_mci_disable_interrupt(struct ath_hw *ah) | 333 | static void ar9003_mci_disable_interrupt(struct ath_hw *ah) |
@@ -615,9 +612,9 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, | |||
615 | } | 612 | } |
616 | break; | 613 | break; |
617 | } | 614 | } |
618 | } else if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) { | 615 | } else if ((recv_type == gpm_type) && |
616 | (recv_opcode == gpm_opcode)) | ||
619 | break; | 617 | break; |
620 | } | ||
621 | 618 | ||
622 | /* | 619 | /* |
623 | * check if it's cal_grant | 620 | * check if it's cal_grant |
@@ -731,38 +728,38 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
731 | if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) | 728 | if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) |
732 | goto exit; | 729 | goto exit; |
733 | 730 | ||
734 | if (ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || | 731 | if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) && |
735 | ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { | 732 | !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) |
733 | goto exit; | ||
736 | 734 | ||
737 | /* | 735 | /* |
738 | * BT is sleeping. Check if BT wakes up during | 736 | * BT is sleeping. Check if BT wakes up during |
739 | * WLAN calibration. If BT wakes up during | 737 | * WLAN calibration. If BT wakes up during |
740 | * WLAN calibration, need to go through all | 738 | * WLAN calibration, need to go through all |
741 | * message exchanges again and recal. | 739 | * message exchanges again and recal. |
742 | */ | 740 | */ |
743 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, | 741 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, |
744 | AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | | 742 | (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | |
745 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); | 743 | AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)); |
746 | 744 | ||
747 | ar9003_mci_remote_reset(ah, true); | 745 | ar9003_mci_remote_reset(ah, true); |
748 | ar9003_mci_send_sys_waking(ah, true); | 746 | ar9003_mci_send_sys_waking(ah, true); |
749 | udelay(1); | 747 | udelay(1); |
750 | 748 | ||
751 | if (IS_CHAN_2GHZ(chan)) | 749 | if (IS_CHAN_2GHZ(chan)) |
752 | ar9003_mci_send_lna_transfer(ah, true); | 750 | ar9003_mci_send_lna_transfer(ah, true); |
753 | 751 | ||
754 | mci_hw->bt_state = MCI_BT_AWAKE; | 752 | mci_hw->bt_state = MCI_BT_AWAKE; |
755 | 753 | ||
756 | if (caldata) { | 754 | if (caldata) { |
757 | caldata->done_txiqcal_once = false; | 755 | caldata->done_txiqcal_once = false; |
758 | caldata->done_txclcal_once = false; | 756 | caldata->done_txclcal_once = false; |
759 | caldata->rtt_done = false; | 757 | caldata->rtt_done = false; |
760 | } | 758 | } |
761 | 759 | ||
762 | if (!ath9k_hw_init_cal(ah, chan)) | 760 | if (!ath9k_hw_init_cal(ah, chan)) |
763 | return -EIO; | 761 | return -EIO; |
764 | 762 | ||
765 | } | ||
766 | exit: | 763 | exit: |
767 | ar9003_mci_enable_interrupt(ah); | 764 | ar9003_mci_enable_interrupt(ah); |
768 | return 0; | 765 | return 0; |
@@ -798,29 +795,27 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) | |||
798 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 795 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
799 | u32 thresh; | 796 | u32 thresh; |
800 | 797 | ||
801 | if (enable) { | 798 | if (!enable) { |
802 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | ||
803 | AR_MCI_SCHD_TABLE_2_HW_BASED, 1); | ||
804 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | ||
805 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); | ||
806 | |||
807 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { | ||
808 | thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); | ||
809 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
810 | AR_BTCOEX_CTRL_AGGR_THRESH, thresh); | ||
811 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
812 | AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); | ||
813 | } else { | ||
814 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
815 | AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); | ||
816 | } | ||
817 | |||
818 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
819 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); | ||
820 | } else { | ||
821 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, | 799 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, |
822 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | 800 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); |
801 | return; | ||
823 | } | 802 | } |
803 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); | ||
804 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | ||
805 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); | ||
806 | |||
807 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { | ||
808 | thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); | ||
809 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
810 | AR_BTCOEX_CTRL_AGGR_THRESH, thresh); | ||
811 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
812 | AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); | ||
813 | } else | ||
814 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
815 | AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); | ||
816 | |||
817 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
818 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); | ||
824 | } | 819 | } |
825 | 820 | ||
826 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | 821 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, |
@@ -943,26 +938,27 @@ static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) | |||
943 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 938 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
944 | u32 new_flags, to_set, to_clear; | 939 | u32 new_flags, to_set, to_clear; |
945 | 940 | ||
946 | if (mci->update_2g5g && (mci->bt_state != MCI_BT_SLEEP)) { | 941 | if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP)) |
947 | if (mci->is_2g) { | 942 | return; |
948 | new_flags = MCI_2G_FLAGS; | 943 | |
949 | to_clear = MCI_2G_FLAGS_CLEAR_MASK; | 944 | if (mci->is_2g) { |
950 | to_set = MCI_2G_FLAGS_SET_MASK; | 945 | new_flags = MCI_2G_FLAGS; |
951 | } else { | 946 | to_clear = MCI_2G_FLAGS_CLEAR_MASK; |
952 | new_flags = MCI_5G_FLAGS; | 947 | to_set = MCI_2G_FLAGS_SET_MASK; |
953 | to_clear = MCI_5G_FLAGS_CLEAR_MASK; | 948 | } else { |
954 | to_set = MCI_5G_FLAGS_SET_MASK; | 949 | new_flags = MCI_5G_FLAGS; |
955 | } | 950 | to_clear = MCI_5G_FLAGS_CLEAR_MASK; |
951 | to_set = MCI_5G_FLAGS_SET_MASK; | ||
952 | } | ||
956 | 953 | ||
957 | if (to_clear) | 954 | if (to_clear) |
958 | ar9003_mci_send_coex_bt_flags(ah, wait_done, | 955 | ar9003_mci_send_coex_bt_flags(ah, wait_done, |
959 | MCI_GPM_COEX_BT_FLAGS_CLEAR, | 956 | MCI_GPM_COEX_BT_FLAGS_CLEAR, |
960 | to_clear); | 957 | to_clear); |
961 | if (to_set) | 958 | if (to_set) |
962 | ar9003_mci_send_coex_bt_flags(ah, wait_done, | 959 | ar9003_mci_send_coex_bt_flags(ah, wait_done, |
963 | MCI_GPM_COEX_BT_FLAGS_SET, | 960 | MCI_GPM_COEX_BT_FLAGS_SET, |
964 | to_set); | 961 | to_set); |
965 | } | ||
966 | } | 962 | } |
967 | 963 | ||
968 | static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, | 964 | static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, |
@@ -1018,34 +1014,34 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) | |||
1018 | { | 1014 | { |
1019 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 1015 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
1020 | 1016 | ||
1021 | if (mci->update_2g5g) { | 1017 | if (!mci->update_2g5g) |
1022 | if (mci->is_2g) { | 1018 | return; |
1023 | ar9003_mci_send_2g5g_status(ah, true); | ||
1024 | ar9003_mci_send_lna_transfer(ah, true); | ||
1025 | udelay(5); | ||
1026 | 1019 | ||
1027 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, | 1020 | if (mci->is_2g) { |
1028 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | 1021 | ar9003_mci_send_2g5g_status(ah, true); |
1029 | REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, | 1022 | ar9003_mci_send_lna_transfer(ah, true); |
1030 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | 1023 | udelay(5); |
1031 | 1024 | ||
1032 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) { | 1025 | REG_CLR_BIT(ah, AR_MCI_TX_CTRL, |
1033 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, | 1026 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); |
1034 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | 1027 | REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, |
1035 | } | 1028 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); |
1036 | } else { | 1029 | |
1037 | ar9003_mci_send_lna_take(ah, true); | 1030 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) |
1038 | udelay(5); | 1031 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, |
1039 | |||
1040 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, | ||
1041 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); | ||
1042 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, | ||
1043 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | ||
1044 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, | ||
1045 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | 1032 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); |
1033 | } else { | ||
1034 | ar9003_mci_send_lna_take(ah, true); | ||
1035 | udelay(5); | ||
1046 | 1036 | ||
1047 | ar9003_mci_send_2g5g_status(ah, true); | 1037 | REG_SET_BIT(ah, AR_MCI_TX_CTRL, |
1048 | } | 1038 | AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); |
1039 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, | ||
1040 | AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | ||
1041 | REG_CLR_BIT(ah, AR_BTCOEX_CTRL, | ||
1042 | AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | ||
1043 | |||
1044 | ar9003_mci_send_2g5g_status(ah, true); | ||
1049 | } | 1045 | } |
1050 | } | 1046 | } |
1051 | 1047 | ||
@@ -1132,7 +1128,7 @@ void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) | |||
1132 | if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { | 1128 | if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { |
1133 | ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); | 1129 | ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); |
1134 | } else { | 1130 | } else { |
1135 | is_reusable = false; | 1131 | *is_reusable = false; |
1136 | ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); | 1132 | ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); |
1137 | } | 1133 | } |
1138 | } | 1134 | } |
@@ -1259,12 +1255,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1259 | } | 1255 | } |
1260 | if (p_data) | 1256 | if (p_data) |
1261 | *p_data = more_gpm; | 1257 | *p_data = more_gpm; |
1262 | } | 1258 | } |
1263 | 1259 | ||
1264 | if (value != MCI_GPM_INVALID) | 1260 | if (value != MCI_GPM_INVALID) |
1265 | value <<= 4; | 1261 | value <<= 4; |
1266 | 1262 | ||
1267 | break; | 1263 | break; |
1268 | case MCI_STATE_LAST_SCHD_MSG_OFFSET: | 1264 | case MCI_STATE_LAST_SCHD_MSG_OFFSET: |
1269 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), | 1265 | value = MS(REG_READ(ah, AR_MCI_RX_STATUS), |
1270 | AR_MCI_RX_LAST_SCHD_MSG_INDEX); | 1266 | AR_MCI_RX_LAST_SCHD_MSG_INDEX); |
@@ -1359,24 +1355,22 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1359 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); | 1355 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); |
1360 | break; | 1356 | break; |
1361 | case MCI_STATE_NEED_FLUSH_BT_INFO: | 1357 | case MCI_STATE_NEED_FLUSH_BT_INFO: |
1362 | /* | 1358 | /* |
1363 | * btcoex_hw.mci.unhalt_bt_gpm means whether it's | 1359 | * btcoex_hw.mci.unhalt_bt_gpm means whether it's |
1364 | * needed to send UNHALT message. It's set whenever | 1360 | * needed to send UNHALT message. It's set whenever |
1365 | * there's a request to send HALT message. | 1361 | * there's a request to send HALT message. |
1366 | * mci_halted_bt_gpm means whether HALT message is sent | 1362 | * mci_halted_bt_gpm means whether HALT message is sent |
1367 | * out successfully. | 1363 | * out successfully. |
1368 | * | 1364 | * |
1369 | * Checking (mci_unhalt_bt_gpm == false) instead of | 1365 | * Checking (mci_unhalt_bt_gpm == false) instead of |
1370 | * checking (ah->mci_halted_bt_gpm == false) will make | 1366 | * checking (ah->mci_halted_bt_gpm == false) will make |
1371 | * sure currently is in UNHALT-ed mode and BT can | 1367 | * sure currently is in UNHALT-ed mode and BT can |
1372 | * respond to status query. | 1368 | * respond to status query. |
1373 | */ | 1369 | */ |
1374 | value = (!mci->unhalt_bt_gpm && | 1370 | value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; |
1375 | mci->need_flush_btinfo) ? 1 : 0; | 1371 | if (p_data) |
1376 | if (p_data) | 1372 | mci->need_flush_btinfo = (*p_data != 0) ? true : false; |
1377 | mci->need_flush_btinfo = | 1373 | break; |
1378 | (*p_data != 0) ? true : false; | ||
1379 | break; | ||
1380 | case MCI_STATE_RECOVER_RX: | 1374 | case MCI_STATE_RECOVER_RX: |
1381 | ar9003_mci_prep_interface(ah); | 1375 | ar9003_mci_prep_interface(ah); |
1382 | mci->query_bt = true; | 1376 | mci->query_bt = true; |
@@ -1387,9 +1381,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1387 | case MCI_STATE_NEED_FTP_STOMP: | 1381 | case MCI_STATE_NEED_FTP_STOMP: |
1388 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); | 1382 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); |
1389 | break; | 1383 | break; |
1390 | case MCI_STATE_NEED_TUNING: | ||
1391 | value = !(mci->config & ATH_MCI_CONFIG_DISABLE_TUNING); | ||
1392 | break; | ||
1393 | default: | 1384 | default: |
1394 | break; | 1385 | break; |
1395 | } | 1386 | } |
@@ -1397,3 +1388,19 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) | |||
1397 | return value; | 1388 | return value; |
1398 | } | 1389 | } |
1399 | EXPORT_SYMBOL(ar9003_mci_state); | 1390 | EXPORT_SYMBOL(ar9003_mci_state); |
1391 | |||
1392 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | ||
1393 | { | ||
1394 | struct ath_common *common = ath9k_hw_common(ah); | ||
1395 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
1396 | |||
1397 | ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); | ||
1398 | |||
1399 | REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); | ||
1400 | mci->is_2g = false; | ||
1401 | mci->update_2g5g = true; | ||
1402 | ar9003_mci_send_2g5g_status(ah, true); | ||
1403 | |||
1404 | /* Force another 2g5g update at next scanning */ | ||
1405 | mci->update_2g5g = true; | ||
1406 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 4842f6c06b8c..10282e2bcdc9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -212,7 +212,6 @@ enum mci_state_type { | |||
212 | MCI_STATE_SET_CONCUR_TX_PRI, | 212 | MCI_STATE_SET_CONCUR_TX_PRI, |
213 | MCI_STATE_RECOVER_RX, | 213 | MCI_STATE_RECOVER_RX, |
214 | MCI_STATE_NEED_FTP_STOMP, | 214 | MCI_STATE_NEED_FTP_STOMP, |
215 | MCI_STATE_NEED_TUNING, | ||
216 | MCI_STATE_DEBUG, | 215 | MCI_STATE_DEBUG, |
217 | MCI_STATE_MAX | 216 | MCI_STATE_MAX |
218 | }; | 217 | }; |
@@ -266,6 +265,7 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, | |||
266 | void ar9003_mci_cleanup(struct ath_hw *ah); | 265 | void ar9003_mci_cleanup(struct ath_hw *ah); |
267 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | 266 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, |
268 | u32 *rx_msg_intr); | 267 | u32 *rx_msg_intr); |
268 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | ||
269 | 269 | ||
270 | /* | 270 | /* |
271 | * These functions are used by ath9k_hw. | 271 | * These functions are used by ath9k_hw. |
@@ -273,10 +273,6 @@ void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | |||
273 | 273 | ||
274 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 274 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
275 | 275 | ||
276 | static inline bool ar9003_mci_is_ready(struct ath_hw *ah) | ||
277 | { | ||
278 | return ah->btcoex_hw.mci.ready; | ||
279 | } | ||
280 | void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep); | 276 | void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep); |
281 | void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable); | 277 | void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable); |
282 | void ar9003_mci_init_cal_done(struct ath_hw *ah); | 278 | void ar9003_mci_init_cal_done(struct ath_hw *ah); |
@@ -292,10 +288,6 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); | |||
292 | 288 | ||
293 | #else | 289 | #else |
294 | 290 | ||
295 | static inline bool ar9003_mci_is_ready(struct ath_hw *ah) | ||
296 | { | ||
297 | return false; | ||
298 | } | ||
299 | static inline void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) | 291 | static inline void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) |
300 | { | 292 | { |
301 | } | 293 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 11abb972be1f..d6baf69cdc14 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -676,6 +676,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
676 | if (chan->channel == 2484) | 676 | if (chan->channel == 2484) |
677 | ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); | 677 | ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); |
678 | 678 | ||
679 | if (AR_SREV_9462(ah)) | ||
680 | REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, | ||
681 | AR_GLB_SWREG_DISCONT_EN_BT_WLAN); | ||
682 | |||
679 | ah->modes_index = modesIndex; | 683 | ah->modes_index = modesIndex; |
680 | ar9003_hw_override_ini(ah); | 684 | ar9003_hw_override_ini(ah); |
681 | ar9003_hw_set_channel_regs(ah, chan); | 685 | ar9003_hw_set_channel_regs(ah, chan); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7268a48a92a1..ed662c3bae5b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -820,18 +820,26 @@ | |||
820 | #define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 | 820 | #define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 |
821 | #define AR_PHY_RX_DELAY_DELAY 0x00003FFF | 821 | #define AR_PHY_RX_DELAY_DELAY 0x00003FFF |
822 | #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 | 822 | #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 |
823 | #define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001 | 823 | |
824 | #define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0 | 824 | #define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001 |
825 | #define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 | 825 | #define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0 |
826 | #define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 | 826 | #define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 |
827 | #define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 | 827 | #define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 |
828 | #define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 | 828 | #define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 |
829 | #define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 | 829 | #define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 |
830 | #define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 | 830 | #define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 |
831 | #define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 | 831 | #define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 |
832 | #define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 | 832 | #define AR_PHY_SPECTRAL_SCAN_COUNT 0x0FFF0000 |
833 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 | 833 | #define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 |
834 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 | 834 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x10000000 |
835 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 28 | ||
836 | #define AR_PHY_SPECTRAL_SCAN_PRIORITY 0x20000000 | ||
837 | #define AR_PHY_SPECTRAL_SCAN_PRIORITY_S 29 | ||
838 | #define AR_PHY_SPECTRAL_SCAN_USE_ERR5 0x40000000 | ||
839 | #define AR_PHY_SPECTRAL_SCAN_USE_ERR5_S 30 | ||
840 | #define AR_PHY_SPECTRAL_SCAN_COMPRESSED_RPT 0x80000000 | ||
841 | #define AR_PHY_SPECTRAL_SCAN_COMPRESSED_RPT_S 31 | ||
842 | |||
835 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 | 843 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 |
836 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001 | 844 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001 |
837 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0 | 845 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 1d6658e139b5..4a93e1534c1d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -958,7 +958,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { | |||
958 | {0x0001604c, 0x2699e04f}, | 958 | {0x0001604c, 0x2699e04f}, |
959 | {0x00016050, 0x6db6db6c}, | 959 | {0x00016050, 0x6db6db6c}, |
960 | {0x00016058, 0x6c200000}, | 960 | {0x00016058, 0x6c200000}, |
961 | {0x00016080, 0x00040000}, | 961 | {0x00016080, 0x000c0000}, |
962 | {0x00016084, 0x9a68048c}, | 962 | {0x00016084, 0x9a68048c}, |
963 | {0x00016088, 0x54214514}, | 963 | {0x00016088, 0x54214514}, |
964 | {0x0001608c, 0x1203040b}, | 964 | {0x0001608c, 0x1203040b}, |
@@ -981,7 +981,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { | |||
981 | {0x00016144, 0x02084080}, | 981 | {0x00016144, 0x02084080}, |
982 | {0x00016148, 0x000080c0}, | 982 | {0x00016148, 0x000080c0}, |
983 | {0x00016280, 0x050a0001}, | 983 | {0x00016280, 0x050a0001}, |
984 | {0x00016284, 0x3d841400}, | 984 | {0x00016284, 0x3d841418}, |
985 | {0x00016288, 0x00000000}, | 985 | {0x00016288, 0x00000000}, |
986 | {0x0001628c, 0xe3000000}, | 986 | {0x0001628c, 0xe3000000}, |
987 | {0x00016290, 0xa1005080}, | 987 | {0x00016290, 0xa1005080}, |
@@ -1007,6 +1007,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { | |||
1007 | 1007 | ||
1008 | static const u32 ar9462_2p0_soc_preamble[][2] = { | 1008 | static const u32 ar9462_2p0_soc_preamble[][2] = { |
1009 | /* Addr allmodes */ | 1009 | /* Addr allmodes */ |
1010 | {0x000040a4 ,0x00a0c1c9}, | ||
1010 | {0x00007020, 0x00000000}, | 1011 | {0x00007020, 0x00000000}, |
1011 | {0x00007034, 0x00000002}, | 1012 | {0x00007034, 0x00000002}, |
1012 | {0x00007038, 0x000004c2}, | 1013 | {0x00007038, 0x000004c2}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a277cf6f339d..02fc1c1e5eeb 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -307,6 +307,7 @@ struct ath_rx { | |||
307 | u8 defant; | 307 | u8 defant; |
308 | u8 rxotherant; | 308 | u8 rxotherant; |
309 | u32 *rxlink; | 309 | u32 *rxlink; |
310 | u32 num_pkts; | ||
310 | unsigned int rxfilter; | 311 | unsigned int rxfilter; |
311 | spinlock_t rxbuflock; | 312 | spinlock_t rxbuflock; |
312 | struct list_head rxbuf; | 313 | struct list_head rxbuf; |
@@ -325,6 +326,9 @@ int ath_rx_init(struct ath_softc *sc, int nbufs); | |||
325 | void ath_rx_cleanup(struct ath_softc *sc); | 326 | void ath_rx_cleanup(struct ath_softc *sc); |
326 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); | 327 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); |
327 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); | 328 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); |
329 | void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq); | ||
330 | void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq); | ||
331 | void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq); | ||
328 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | 332 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); |
329 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); | 333 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); |
330 | void ath_draintxq(struct ath_softc *sc, | 334 | void ath_draintxq(struct ath_softc *sc, |
@@ -414,9 +418,9 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
414 | void ath_set_beacon(struct ath_softc *sc); | 418 | void ath_set_beacon(struct ath_softc *sc); |
415 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); | 419 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); |
416 | 420 | ||
417 | /*******/ | 421 | /*******************/ |
418 | /* ANI */ | 422 | /* Link Monitoring */ |
419 | /*******/ | 423 | /*******************/ |
420 | 424 | ||
421 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | 425 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ |
422 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 426 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
@@ -427,7 +431,9 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); | |||
427 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 431 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
428 | 432 | ||
429 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | 433 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ |
434 | #define ATH_PLL_WORK_INTERVAL 100 | ||
430 | 435 | ||
436 | void ath_tx_complete_poll_work(struct work_struct *work); | ||
431 | void ath_reset_work(struct work_struct *work); | 437 | void ath_reset_work(struct work_struct *work); |
432 | void ath_hw_check(struct work_struct *work); | 438 | void ath_hw_check(struct work_struct *work); |
433 | void ath_hw_pll_work(struct work_struct *work); | 439 | void ath_hw_pll_work(struct work_struct *work); |
@@ -436,22 +442,31 @@ void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon); | |||
436 | void ath_paprd_calibrate(struct work_struct *work); | 442 | void ath_paprd_calibrate(struct work_struct *work); |
437 | void ath_ani_calibrate(unsigned long data); | 443 | void ath_ani_calibrate(unsigned long data); |
438 | void ath_start_ani(struct ath_common *common); | 444 | void ath_start_ani(struct ath_common *common); |
445 | int ath_update_survey_stats(struct ath_softc *sc); | ||
446 | void ath_update_survey_nf(struct ath_softc *sc, int channel); | ||
439 | 447 | ||
440 | /**********/ | 448 | /**********/ |
441 | /* BTCOEX */ | 449 | /* BTCOEX */ |
442 | /**********/ | 450 | /**********/ |
443 | 451 | ||
452 | enum bt_op_flags { | ||
453 | BT_OP_PRIORITY_DETECTED, | ||
454 | BT_OP_SCAN, | ||
455 | }; | ||
456 | |||
444 | struct ath_btcoex { | 457 | struct ath_btcoex { |
445 | bool hw_timer_enabled; | 458 | bool hw_timer_enabled; |
446 | spinlock_t btcoex_lock; | 459 | spinlock_t btcoex_lock; |
447 | struct timer_list period_timer; /* Timer for BT period */ | 460 | struct timer_list period_timer; /* Timer for BT period */ |
448 | u32 bt_priority_cnt; | 461 | u32 bt_priority_cnt; |
449 | unsigned long bt_priority_time; | 462 | unsigned long bt_priority_time; |
463 | unsigned long op_flags; | ||
450 | int bt_stomp_type; /* Types of BT stomping */ | 464 | int bt_stomp_type; /* Types of BT stomping */ |
451 | u32 btcoex_no_stomp; /* in usec */ | 465 | u32 btcoex_no_stomp; /* in usec */ |
452 | u32 btcoex_period; /* in usec */ | 466 | u32 btcoex_period; /* in usec */ |
453 | u32 btscan_no_stomp; /* in usec */ | 467 | u32 btscan_no_stomp; /* in usec */ |
454 | u32 duty_cycle; | 468 | u32 duty_cycle; |
469 | u32 bt_wait_time; | ||
455 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ | 470 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ |
456 | struct ath_mci_profile mci; | 471 | struct ath_mci_profile mci; |
457 | }; | 472 | }; |
@@ -513,8 +528,10 @@ static inline void ath_deinit_leds(struct ath_softc *sc) | |||
513 | } | 528 | } |
514 | #endif | 529 | #endif |
515 | 530 | ||
516 | 531 | /*******************************/ | |
517 | /* Antenna diversity/combining */ | 532 | /* Antenna diversity/combining */ |
533 | /*******************************/ | ||
534 | |||
518 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | 535 | #define ATH_ANT_RX_CURRENT_SHIFT 4 |
519 | #define ATH_ANT_RX_MAIN_SHIFT 2 | 536 | #define ATH_ANT_RX_MAIN_SHIFT 2 |
520 | #define ATH_ANT_RX_MASK 0x3 | 537 | #define ATH_ANT_RX_MASK 0x3 |
@@ -567,6 +584,9 @@ struct ath_ant_comb { | |||
567 | unsigned long scan_start_time; | 584 | unsigned long scan_start_time; |
568 | }; | 585 | }; |
569 | 586 | ||
587 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | ||
588 | void ath_ant_comb_update(struct ath_softc *sc); | ||
589 | |||
570 | /********************/ | 590 | /********************/ |
571 | /* Main driver core */ | 591 | /* Main driver core */ |
572 | /********************/ | 592 | /********************/ |
@@ -584,15 +604,15 @@ struct ath_ant_comb { | |||
584 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 604 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
585 | #define ATH_RATE_DUMMY_MARKER 0 | 605 | #define ATH_RATE_DUMMY_MARKER 0 |
586 | 606 | ||
587 | #define SC_OP_INVALID BIT(0) | 607 | enum sc_op_flags { |
588 | #define SC_OP_BEACONS BIT(1) | 608 | SC_OP_INVALID, |
589 | #define SC_OP_OFFCHANNEL BIT(2) | 609 | SC_OP_BEACONS, |
590 | #define SC_OP_RXFLUSH BIT(3) | 610 | SC_OP_RXFLUSH, |
591 | #define SC_OP_TSF_RESET BIT(4) | 611 | SC_OP_TSF_RESET, |
592 | #define SC_OP_BT_PRIORITY_DETECTED BIT(5) | 612 | SC_OP_ANI_RUN, |
593 | #define SC_OP_BT_SCAN BIT(6) | 613 | SC_OP_PRIM_STA_VIF, |
594 | #define SC_OP_ANI_RUN BIT(7) | 614 | SC_OP_HW_RESET, |
595 | #define SC_OP_PRIM_STA_VIF BIT(8) | 615 | }; |
596 | 616 | ||
597 | /* Powersave flags */ | 617 | /* Powersave flags */ |
598 | #define PS_WAIT_FOR_BEACON BIT(0) | 618 | #define PS_WAIT_FOR_BEACON BIT(0) |
@@ -638,9 +658,9 @@ struct ath_softc { | |||
638 | struct completion paprd_complete; | 658 | struct completion paprd_complete; |
639 | 659 | ||
640 | unsigned int hw_busy_count; | 660 | unsigned int hw_busy_count; |
661 | unsigned long sc_flags; | ||
641 | 662 | ||
642 | u32 intrstatus; | 663 | u32 intrstatus; |
643 | u32 sc_flags; /* SC_OP_* */ | ||
644 | u16 ps_flags; /* PS_* */ | 664 | u16 ps_flags; /* PS_* */ |
645 | u16 curtxpow; | 665 | u16 curtxpow; |
646 | bool ps_enabled; | 666 | bool ps_enabled; |
@@ -736,5 +756,4 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
736 | struct ieee80211_vif *vif, | 756 | struct ieee80211_vif *vif, |
737 | struct ath9k_vif_iter_data *iter_data); | 757 | struct ath9k_vif_iter_data *iter_data); |
738 | 758 | ||
739 | |||
740 | #endif /* ATH9K_H */ | 759 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 11bc55e3d697..40775da8941e 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -48,7 +48,10 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
48 | txq = sc->tx.txq_map[WME_AC_BE]; | 48 | txq = sc->tx.txq_map[WME_AC_BE]; |
49 | ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); | 49 | ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); |
50 | qi.tqi_aifs = qi_be.tqi_aifs; | 50 | qi.tqi_aifs = qi_be.tqi_aifs; |
51 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | 51 | if (ah->slottime == ATH9K_SLOT_TIME_20) |
52 | qi.tqi_cwmin = 2*qi_be.tqi_cwmin; | ||
53 | else | ||
54 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
52 | qi.tqi_cwmax = qi_be.tqi_cwmax; | 55 | qi.tqi_cwmax = qi_be.tqi_cwmax; |
53 | } | 56 | } |
54 | 57 | ||
@@ -387,7 +390,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
387 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 390 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
388 | ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); | 391 | ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); |
389 | sc->beacon.bmisscnt = 0; | 392 | sc->beacon.bmisscnt = 0; |
390 | sc->sc_flags |= SC_OP_TSF_RESET; | 393 | set_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
391 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 394 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
392 | } | 395 | } |
393 | 396 | ||
@@ -477,16 +480,16 @@ static void ath9k_beacon_init(struct ath_softc *sc, | |||
477 | u32 next_beacon, | 480 | u32 next_beacon, |
478 | u32 beacon_period) | 481 | u32 beacon_period) |
479 | { | 482 | { |
480 | if (sc->sc_flags & SC_OP_TSF_RESET) { | 483 | if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { |
481 | ath9k_ps_wakeup(sc); | 484 | ath9k_ps_wakeup(sc); |
482 | ath9k_hw_reset_tsf(sc->sc_ah); | 485 | ath9k_hw_reset_tsf(sc->sc_ah); |
483 | } | 486 | } |
484 | 487 | ||
485 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); | 488 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); |
486 | 489 | ||
487 | if (sc->sc_flags & SC_OP_TSF_RESET) { | 490 | if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { |
488 | ath9k_ps_restore(sc); | 491 | ath9k_ps_restore(sc); |
489 | sc->sc_flags &= ~SC_OP_TSF_RESET; | 492 | clear_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
490 | } | 493 | } |
491 | } | 494 | } |
492 | 495 | ||
@@ -516,7 +519,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
516 | /* Set the computed AP beacon timers */ | 519 | /* Set the computed AP beacon timers */ |
517 | 520 | ||
518 | ath9k_hw_disable_interrupts(ah); | 521 | ath9k_hw_disable_interrupts(ah); |
519 | sc->sc_flags |= SC_OP_TSF_RESET; | 522 | set_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
520 | ath9k_beacon_init(sc, nexttbtt, intval); | 523 | ath9k_beacon_init(sc, nexttbtt, intval); |
521 | sc->beacon.bmisscnt = 0; | 524 | sc->beacon.bmisscnt = 0; |
522 | ath9k_hw_set_interrupts(ah); | 525 | ath9k_hw_set_interrupts(ah); |
@@ -659,7 +662,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
659 | u32 tsf, intval, nexttbtt; | 662 | u32 tsf, intval, nexttbtt; |
660 | 663 | ||
661 | ath9k_reset_beacon_status(sc); | 664 | ath9k_reset_beacon_status(sc); |
662 | if (!(sc->sc_flags & SC_OP_BEACONS)) | 665 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
663 | ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp); | 666 | ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp); |
664 | 667 | ||
665 | intval = TU_TO_USEC(conf->beacon_interval); | 668 | intval = TU_TO_USEC(conf->beacon_interval); |
@@ -724,7 +727,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc, | |||
724 | */ | 727 | */ |
725 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | 728 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && |
726 | (vif->type == NL80211_IFTYPE_STATION) && | 729 | (vif->type == NL80211_IFTYPE_STATION) && |
727 | (sc->sc_flags & SC_OP_BEACONS) && | 730 | test_bit(SC_OP_BEACONS, &sc->sc_flags) && |
728 | !avp->primary_sta_vif) { | 731 | !avp->primary_sta_vif) { |
729 | ath_dbg(common, CONFIG, | 732 | ath_dbg(common, CONFIG, |
730 | "Beacon already configured for a station interface\n"); | 733 | "Beacon already configured for a station interface\n"); |
@@ -810,7 +813,7 @@ void ath_set_beacon(struct ath_softc *sc) | |||
810 | return; | 813 | return; |
811 | } | 814 | } |
812 | 815 | ||
813 | sc->sc_flags |= SC_OP_BEACONS; | 816 | set_bit(SC_OP_BEACONS, &sc->sc_flags); |
814 | } | 817 | } |
815 | 818 | ||
816 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) | 819 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) |
@@ -818,7 +821,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) | |||
818 | struct ath_hw *ah = sc->sc_ah; | 821 | struct ath_hw *ah = sc->sc_ah; |
819 | 822 | ||
820 | if (!ath_has_valid_bslot(sc)) { | 823 | if (!ath_has_valid_bslot(sc)) { |
821 | sc->sc_flags &= ~SC_OP_BEACONS; | 824 | clear_bit(SC_OP_BEACONS, &sc->sc_flags); |
822 | return; | 825 | return; |
823 | } | 826 | } |
824 | 827 | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 1ca6da80d4ad..acd437384fe4 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -336,10 +336,16 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, | |||
336 | enum ath_stomp_type stomp_type) | 336 | enum ath_stomp_type stomp_type) |
337 | { | 337 | { |
338 | struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; | 338 | struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; |
339 | const u32 *weight = AR_SREV_9462(ah) ? ar9003_wlan_weights[stomp_type] : | 339 | const u32 *weight = ar9003_wlan_weights[stomp_type]; |
340 | ar9462_wlan_weights[stomp_type]; | ||
341 | int i; | 340 | int i; |
342 | 341 | ||
342 | if (AR_SREV_9462(ah)) { | ||
343 | if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | ||
344 | btcoex->mci.stomp_ftp) | ||
345 | stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; | ||
346 | weight = ar9462_wlan_weights[stomp_type]; | ||
347 | } | ||
348 | |||
343 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | 349 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { |
344 | btcoex->bt_weight[i] = AR9300_BT_WGHT; | 350 | btcoex->bt_weight[i] = AR9300_BT_WGHT; |
345 | btcoex->wlan_weight[i] = weight[i]; | 351 | btcoex->wlan_weight[i] = weight[i]; |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 3a1e1cfabd5e..20092f98658f 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -36,6 +36,9 @@ | |||
36 | #define ATH_BT_CNT_THRESHOLD 3 | 36 | #define ATH_BT_CNT_THRESHOLD 3 |
37 | #define ATH_BT_CNT_SCAN_THRESHOLD 15 | 37 | #define ATH_BT_CNT_SCAN_THRESHOLD 15 |
38 | 38 | ||
39 | #define ATH_BTCOEX_RX_WAIT_TIME 100 | ||
40 | #define ATH_BTCOEX_STOMP_FTP_THRESH 5 | ||
41 | |||
39 | #define AR9300_NUM_BT_WEIGHTS 4 | 42 | #define AR9300_NUM_BT_WEIGHTS 4 |
40 | #define AR9300_NUM_WLAN_WEIGHTS 4 | 43 | #define AR9300_NUM_WLAN_WEIGHTS 4 |
41 | /* Defines the BT AR_BT_COEX_WGHT used */ | 44 | /* Defines the BT AR_BT_COEX_WGHT used */ |
@@ -80,6 +83,7 @@ struct ath9k_hw_mci { | |||
80 | u8 bt_ver_major; | 83 | u8 bt_ver_major; |
81 | u8 bt_ver_minor; | 84 | u8 bt_ver_minor; |
82 | u8 bt_state; | 85 | u8 bt_state; |
86 | u8 stomp_ftp; | ||
83 | }; | 87 | }; |
84 | 88 | ||
85 | struct ath_btcoex_hw { | 89 | struct ath_btcoex_hw { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index fde700c4e490..2831258d9507 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -205,10 +205,10 @@ static ssize_t write_file_disable_ani(struct file *file, | |||
205 | common->disable_ani = !!disable_ani; | 205 | common->disable_ani = !!disable_ani; |
206 | 206 | ||
207 | if (disable_ani) { | 207 | if (disable_ani) { |
208 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 208 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
209 | del_timer_sync(&common->ani.timer); | 209 | del_timer_sync(&common->ani.timer); |
210 | } else { | 210 | } else { |
211 | sc->sc_flags |= SC_OP_ANI_RUN; | 211 | set_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
212 | ath_start_ani(common); | 212 | ath_start_ani(common); |
213 | } | 213 | } |
214 | 214 | ||
@@ -374,6 +374,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | |||
374 | sc->debug.stats.istats.dtim++; | 374 | sc->debug.stats.istats.dtim++; |
375 | if (status & ATH9K_INT_TSFOOR) | 375 | if (status & ATH9K_INT_TSFOOR) |
376 | sc->debug.stats.istats.tsfoor++; | 376 | sc->debug.stats.istats.tsfoor++; |
377 | if (status & ATH9K_INT_MCI) | ||
378 | sc->debug.stats.istats.mci++; | ||
377 | } | 379 | } |
378 | 380 | ||
379 | static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | 381 | static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, |
@@ -418,6 +420,7 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
418 | PR_IS("DTIMSYNC", dtimsync); | 420 | PR_IS("DTIMSYNC", dtimsync); |
419 | PR_IS("DTIM", dtim); | 421 | PR_IS("DTIM", dtim); |
420 | PR_IS("TSFOOR", tsfoor); | 422 | PR_IS("TSFOOR", tsfoor); |
423 | PR_IS("MCI", mci); | ||
421 | PR_IS("TOTAL", total); | 424 | PR_IS("TOTAL", total); |
422 | 425 | ||
423 | len += snprintf(buf + len, mxlen - len, | 426 | len += snprintf(buf + len, mxlen - len, |
@@ -1318,7 +1321,7 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) | |||
1318 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 1321 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
1319 | u8 nread; | 1322 | u8 nread; |
1320 | 1323 | ||
1321 | if (sc->sc_flags & SC_OP_INVALID) | 1324 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
1322 | return -EAGAIN; | 1325 | return -EAGAIN; |
1323 | 1326 | ||
1324 | buf = vmalloc(size); | 1327 | buf = vmalloc(size); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index c34da09d9103..d0f851cea43a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -86,6 +86,7 @@ struct ath_interrupt_stats { | |||
86 | u32 dtim; | 86 | u32 dtim; |
87 | u32 bb_watchdog; | 87 | u32 bb_watchdog; |
88 | u32 tsfoor; | 88 | u32 tsfoor; |
89 | u32 mci; | ||
89 | 90 | ||
90 | /* Sync-cause stats */ | 91 | /* Sync-cause stats */ |
91 | u32 sync_cause_all; | 92 | u32 sync_cause_all; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 92543d166fe9..7d075105a85d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -135,7 +135,7 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
135 | if (!dump_base_hdr) { | 135 | if (!dump_base_hdr) { |
136 | len += snprintf(buf + len, size - len, | 136 | len += snprintf(buf + len, size - len, |
137 | "%20s :\n", "2GHz modal Header"); | 137 | "%20s :\n", "2GHz modal Header"); |
138 | len += ath9k_dump_4k_modal_eeprom(buf, len, size, | 138 | len = ath9k_dump_4k_modal_eeprom(buf, len, size, |
139 | &eep->modalHeader); | 139 | &eep->modalHeader); |
140 | goto out; | 140 | goto out; |
141 | } | 141 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index aa614767adff..cd742fb944c2 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -132,7 +132,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
132 | if (!dump_base_hdr) { | 132 | if (!dump_base_hdr) { |
133 | len += snprintf(buf + len, size - len, | 133 | len += snprintf(buf + len, size - len, |
134 | "%20s :\n", "2GHz modal Header"); | 134 | "%20s :\n", "2GHz modal Header"); |
135 | len += ar9287_dump_modal_eeprom(buf, len, size, | 135 | len = ar9287_dump_modal_eeprom(buf, len, size, |
136 | &eep->modalHeader); | 136 | &eep->modalHeader); |
137 | goto out; | 137 | goto out; |
138 | } | 138 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index a9f071bc643a..a8ac30a00720 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -211,11 +211,11 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
211 | if (!dump_base_hdr) { | 211 | if (!dump_base_hdr) { |
212 | len += snprintf(buf + len, size - len, | 212 | len += snprintf(buf + len, size - len, |
213 | "%20s :\n", "2GHz modal Header"); | 213 | "%20s :\n", "2GHz modal Header"); |
214 | len += ath9k_def_dump_modal_eeprom(buf, len, size, | 214 | len = ath9k_def_dump_modal_eeprom(buf, len, size, |
215 | &eep->modalHeader[0]); | 215 | &eep->modalHeader[0]); |
216 | len += snprintf(buf + len, size - len, | 216 | len += snprintf(buf + len, size - len, |
217 | "%20s :\n", "5GHz modal Header"); | 217 | "%20s :\n", "5GHz modal Header"); |
218 | len += ath9k_def_dump_modal_eeprom(buf, len, size, | 218 | len = ath9k_def_dump_modal_eeprom(buf, len, size, |
219 | &eep->modalHeader[1]); | 219 | &eep->modalHeader[1]); |
220 | goto out; | 220 | goto out; |
221 | } | 221 | } |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 281a9af0f1b6..af6d27350291 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -132,17 +132,18 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
132 | 132 | ||
133 | if (time_after(jiffies, btcoex->bt_priority_time + | 133 | if (time_after(jiffies, btcoex->bt_priority_time + |
134 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | 134 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { |
135 | sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); | 135 | clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); |
136 | clear_bit(BT_OP_SCAN, &btcoex->op_flags); | ||
136 | /* Detect if colocated bt started scanning */ | 137 | /* Detect if colocated bt started scanning */ |
137 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | 138 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { |
138 | ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, | 139 | ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, |
139 | "BT scan detected\n"); | 140 | "BT scan detected\n"); |
140 | sc->sc_flags |= (SC_OP_BT_SCAN | | 141 | set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); |
141 | SC_OP_BT_PRIORITY_DETECTED); | 142 | set_bit(BT_OP_SCAN, &btcoex->op_flags); |
142 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | 143 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { |
143 | ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, | 144 | ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, |
144 | "BT priority traffic detected\n"); | 145 | "BT priority traffic detected\n"); |
145 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | 146 | set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); |
146 | } | 147 | } |
147 | 148 | ||
148 | btcoex->bt_priority_cnt = 0; | 149 | btcoex->bt_priority_cnt = 0; |
@@ -190,13 +191,26 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
190 | struct ath_softc *sc = (struct ath_softc *) data; | 191 | struct ath_softc *sc = (struct ath_softc *) data; |
191 | struct ath_hw *ah = sc->sc_ah; | 192 | struct ath_hw *ah = sc->sc_ah; |
192 | struct ath_btcoex *btcoex = &sc->btcoex; | 193 | struct ath_btcoex *btcoex = &sc->btcoex; |
194 | struct ath_mci_profile *mci = &btcoex->mci; | ||
193 | u32 timer_period; | 195 | u32 timer_period; |
194 | bool is_btscan; | 196 | bool is_btscan; |
195 | 197 | ||
196 | ath9k_ps_wakeup(sc); | 198 | ath9k_ps_wakeup(sc); |
197 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) | 199 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) |
198 | ath_detect_bt_priority(sc); | 200 | ath_detect_bt_priority(sc); |
199 | is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 201 | is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags); |
202 | |||
203 | btcoex->bt_wait_time += btcoex->btcoex_period; | ||
204 | if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | ||
205 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) && | ||
206 | (mci->num_pan || mci->num_other_acl)) | ||
207 | ah->btcoex_hw.mci.stomp_ftp = | ||
208 | (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | ||
209 | else | ||
210 | ah->btcoex_hw.mci.stomp_ftp = false; | ||
211 | btcoex->bt_wait_time = 0; | ||
212 | sc->rx.num_pkts = 0; | ||
213 | } | ||
200 | 214 | ||
201 | spin_lock_bh(&btcoex->btcoex_lock); | 215 | spin_lock_bh(&btcoex->btcoex_lock); |
202 | 216 | ||
@@ -219,8 +233,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
219 | 233 | ||
220 | ath9k_ps_restore(sc); | 234 | ath9k_ps_restore(sc); |
221 | timer_period = btcoex->btcoex_period / 1000; | 235 | timer_period = btcoex->btcoex_period / 1000; |
222 | mod_timer(&btcoex->period_timer, jiffies + | 236 | mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); |
223 | msecs_to_jiffies(timer_period)); | ||
224 | } | 237 | } |
225 | 238 | ||
226 | /* | 239 | /* |
@@ -233,14 +246,14 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
233 | struct ath_hw *ah = sc->sc_ah; | 246 | struct ath_hw *ah = sc->sc_ah; |
234 | struct ath_btcoex *btcoex = &sc->btcoex; | 247 | struct ath_btcoex *btcoex = &sc->btcoex; |
235 | struct ath_common *common = ath9k_hw_common(ah); | 248 | struct ath_common *common = ath9k_hw_common(ah); |
236 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | ||
237 | 249 | ||
238 | ath_dbg(common, BTCOEX, "no stomp timer running\n"); | 250 | ath_dbg(common, BTCOEX, "no stomp timer running\n"); |
239 | 251 | ||
240 | ath9k_ps_wakeup(sc); | 252 | ath9k_ps_wakeup(sc); |
241 | spin_lock_bh(&btcoex->btcoex_lock); | 253 | spin_lock_bh(&btcoex->btcoex_lock); |
242 | 254 | ||
243 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | 255 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || |
256 | test_bit(BT_OP_SCAN, &btcoex->op_flags)) | ||
244 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); | 257 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); |
245 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 258 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
246 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); | 259 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); |
@@ -292,7 +305,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) | |||
292 | 305 | ||
293 | btcoex->bt_priority_cnt = 0; | 306 | btcoex->bt_priority_cnt = 0; |
294 | btcoex->bt_priority_time = jiffies; | 307 | btcoex->bt_priority_time = jiffies; |
295 | sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); | 308 | btcoex->op_flags &= ~(BT_OP_PRIORITY_DETECTED | BT_OP_SCAN); |
296 | 309 | ||
297 | mod_timer(&btcoex->period_timer, jiffies); | 310 | mod_timer(&btcoex->period_timer, jiffies); |
298 | } | 311 | } |
@@ -316,12 +329,13 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) | |||
316 | 329 | ||
317 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) | 330 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) |
318 | { | 331 | { |
332 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
319 | struct ath_mci_profile *mci = &sc->btcoex.mci; | 333 | struct ath_mci_profile *mci = &sc->btcoex.mci; |
320 | u16 aggr_limit = 0; | 334 | u16 aggr_limit = 0; |
321 | 335 | ||
322 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit) | 336 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit) |
323 | aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4; | 337 | aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4; |
324 | else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) | 338 | else if (test_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags)) |
325 | aggr_limit = min((max_4ms_framelen * 3) / 8, | 339 | aggr_limit = min((max_4ms_framelen * 3) / 8, |
326 | (u32)ATH_AMPDU_LIMIT_MAX); | 340 | (u32)ATH_AMPDU_LIMIT_MAX); |
327 | 341 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7db1890448f2..45e670087e1c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -390,14 +390,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) | |||
390 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 390 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
391 | } | 391 | } |
392 | 392 | ||
393 | static void ath9k_hw_aspm_init(struct ath_hw *ah) | ||
394 | { | ||
395 | struct ath_common *common = ath9k_hw_common(ah); | ||
396 | |||
397 | if (common->bus_ops->aspm_init) | ||
398 | common->bus_ops->aspm_init(common); | ||
399 | } | ||
400 | |||
401 | /* This should work for all families including legacy */ | 393 | /* This should work for all families including legacy */ |
402 | static bool ath9k_hw_chip_test(struct ath_hw *ah) | 394 | static bool ath9k_hw_chip_test(struct ath_hw *ah) |
403 | { | 395 | { |
@@ -693,9 +685,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
693 | if (r) | 685 | if (r) |
694 | return r; | 686 | return r; |
695 | 687 | ||
696 | if (ah->is_pciexpress) | ||
697 | ath9k_hw_aspm_init(ah); | ||
698 | |||
699 | r = ath9k_hw_init_macaddr(ah); | 688 | r = ath9k_hw_init_macaddr(ah); |
700 | if (r) { | 689 | if (r) { |
701 | ath_err(common, "Failed to initialize MAC address\n"); | 690 | ath_err(common, "Failed to initialize MAC address\n"); |
@@ -1443,9 +1432,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | |||
1443 | break; | 1432 | break; |
1444 | } | 1433 | } |
1445 | 1434 | ||
1446 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
1447 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
1448 | |||
1449 | return ret; | 1435 | return ret; |
1450 | } | 1436 | } |
1451 | 1437 | ||
@@ -1721,7 +1707,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1721 | ath9k_hw_loadnf(ah, ah->curchan); | 1707 | ath9k_hw_loadnf(ah, ah->curchan); |
1722 | ath9k_hw_start_nfcal(ah, true); | 1708 | ath9k_hw_start_nfcal(ah, true); |
1723 | 1709 | ||
1724 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah)) | 1710 | if (ath9k_hw_mci_is_enabled(ah)) |
1725 | ar9003_mci_2g5g_switch(ah, true); | 1711 | ar9003_mci_2g5g_switch(ah, true); |
1726 | 1712 | ||
1727 | if (AR_SREV_9271(ah)) | 1713 | if (AR_SREV_9271(ah)) |
@@ -1742,10 +1728,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1742 | u64 tsf = 0; | 1728 | u64 tsf = 0; |
1743 | int i, r; | 1729 | int i, r; |
1744 | bool start_mci_reset = false; | 1730 | bool start_mci_reset = false; |
1745 | bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
1746 | bool save_fullsleep = ah->chip_fullsleep; | 1731 | bool save_fullsleep = ah->chip_fullsleep; |
1747 | 1732 | ||
1748 | if (mci) { | 1733 | if (ath9k_hw_mci_is_enabled(ah)) { |
1749 | start_mci_reset = ar9003_mci_start_reset(ah, chan); | 1734 | start_mci_reset = ar9003_mci_start_reset(ah, chan); |
1750 | if (start_mci_reset) | 1735 | if (start_mci_reset) |
1751 | return 0; | 1736 | return 0; |
@@ -1774,7 +1759,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1774 | return r; | 1759 | return r; |
1775 | } | 1760 | } |
1776 | 1761 | ||
1777 | if (mci) | 1762 | if (ath9k_hw_mci_is_enabled(ah)) |
1778 | ar9003_mci_stop_bt(ah, save_fullsleep); | 1763 | ar9003_mci_stop_bt(ah, save_fullsleep); |
1779 | 1764 | ||
1780 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); | 1765 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); |
@@ -1832,7 +1817,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1832 | if (r) | 1817 | if (r) |
1833 | return r; | 1818 | return r; |
1834 | 1819 | ||
1835 | if (mci) | 1820 | if (ath9k_hw_mci_is_enabled(ah)) |
1836 | ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); | 1821 | ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); |
1837 | 1822 | ||
1838 | /* | 1823 | /* |
@@ -1951,7 +1936,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1951 | ath9k_hw_loadnf(ah, chan); | 1936 | ath9k_hw_loadnf(ah, chan); |
1952 | ath9k_hw_start_nfcal(ah, true); | 1937 | ath9k_hw_start_nfcal(ah, true); |
1953 | 1938 | ||
1954 | if (mci && ar9003_mci_end_reset(ah, chan, caldata)) | 1939 | if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) |
1955 | return -EIO; | 1940 | return -EIO; |
1956 | 1941 | ||
1957 | ENABLE_REGWRITE_BUFFER(ah); | 1942 | ENABLE_REGWRITE_BUFFER(ah); |
@@ -1996,7 +1981,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1996 | if (ath9k_hw_btcoex_is_enabled(ah)) | 1981 | if (ath9k_hw_btcoex_is_enabled(ah)) |
1997 | ath9k_hw_btcoex_enable(ah); | 1982 | ath9k_hw_btcoex_enable(ah); |
1998 | 1983 | ||
1999 | if (mci) | 1984 | if (ath9k_hw_mci_is_enabled(ah)) |
2000 | ar9003_mci_check_bt(ah); | 1985 | ar9003_mci_check_bt(ah); |
2001 | 1986 | ||
2002 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1987 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
@@ -2019,39 +2004,35 @@ EXPORT_SYMBOL(ath9k_hw_reset); | |||
2019 | * Notify Power Mgt is disabled in self-generated frames. | 2004 | * Notify Power Mgt is disabled in self-generated frames. |
2020 | * If requested, force chip to sleep. | 2005 | * If requested, force chip to sleep. |
2021 | */ | 2006 | */ |
2022 | static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | 2007 | static void ath9k_set_power_sleep(struct ath_hw *ah) |
2023 | { | 2008 | { |
2024 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | 2009 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); |
2025 | if (setChip) { | ||
2026 | if (AR_SREV_9462(ah)) { | ||
2027 | REG_WRITE(ah, AR_TIMER_MODE, | ||
2028 | REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00); | ||
2029 | REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah, | ||
2030 | AR_NDP2_TIMER_MODE) & 0xFFFFFF00); | ||
2031 | REG_WRITE(ah, AR_SLP32_INC, | ||
2032 | REG_READ(ah, AR_SLP32_INC) & 0xFFF00000); | ||
2033 | /* xxx Required for WLAN only case ? */ | ||
2034 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); | ||
2035 | udelay(100); | ||
2036 | } | ||
2037 | 2010 | ||
2038 | /* | 2011 | if (AR_SREV_9462(ah)) { |
2039 | * Clear the RTC force wake bit to allow the | 2012 | REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff); |
2040 | * mac to go to sleep. | 2013 | REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff); |
2041 | */ | 2014 | REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff); |
2042 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); | 2015 | /* xxx Required for WLAN only case ? */ |
2016 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); | ||
2017 | udelay(100); | ||
2018 | } | ||
2043 | 2019 | ||
2044 | if (AR_SREV_9462(ah)) | 2020 | /* |
2045 | udelay(100); | 2021 | * Clear the RTC force wake bit to allow the |
2022 | * mac to go to sleep. | ||
2023 | */ | ||
2024 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); | ||
2025 | |||
2026 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2027 | udelay(100); | ||
2046 | 2028 | ||
2047 | if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | 2029 | if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) |
2048 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | 2030 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); |
2049 | 2031 | ||
2050 | /* Shutdown chip. Active low */ | 2032 | /* Shutdown chip. Active low */ |
2051 | if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { | 2033 | if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { |
2052 | REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); | 2034 | REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); |
2053 | udelay(2); | 2035 | udelay(2); |
2054 | } | ||
2055 | } | 2036 | } |
2056 | 2037 | ||
2057 | /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ | 2038 | /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ |
@@ -2064,44 +2045,38 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | |||
2064 | * frames. If request, set power mode of chip to | 2045 | * frames. If request, set power mode of chip to |
2065 | * auto/normal. Duration in units of 128us (1/8 TU). | 2046 | * auto/normal. Duration in units of 128us (1/8 TU). |
2066 | */ | 2047 | */ |
2067 | static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) | 2048 | static void ath9k_set_power_network_sleep(struct ath_hw *ah) |
2068 | { | 2049 | { |
2069 | u32 val; | 2050 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
2070 | 2051 | ||
2071 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | 2052 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); |
2072 | if (setChip) { | ||
2073 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
2074 | 2053 | ||
2075 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 2054 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
2076 | /* Set WakeOnInterrupt bit; clear ForceWake bit */ | 2055 | /* Set WakeOnInterrupt bit; clear ForceWake bit */ |
2077 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, | 2056 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, |
2078 | AR_RTC_FORCE_WAKE_ON_INT); | 2057 | AR_RTC_FORCE_WAKE_ON_INT); |
2079 | } else { | 2058 | } else { |
2080 | 2059 | ||
2081 | /* When chip goes into network sleep, it could be waken | 2060 | /* When chip goes into network sleep, it could be waken |
2082 | * up by MCI_INT interrupt caused by BT's HW messages | 2061 | * up by MCI_INT interrupt caused by BT's HW messages |
2083 | * (LNA_xxx, CONT_xxx) which chould be in a very fast | 2062 | * (LNA_xxx, CONT_xxx) which chould be in a very fast |
2084 | * rate (~100us). This will cause chip to leave and | 2063 | * rate (~100us). This will cause chip to leave and |
2085 | * re-enter network sleep mode frequently, which in | 2064 | * re-enter network sleep mode frequently, which in |
2086 | * consequence will have WLAN MCI HW to generate lots of | 2065 | * consequence will have WLAN MCI HW to generate lots of |
2087 | * SYS_WAKING and SYS_SLEEPING messages which will make | 2066 | * SYS_WAKING and SYS_SLEEPING messages which will make |
2088 | * BT CPU to busy to process. | 2067 | * BT CPU to busy to process. |
2089 | */ | 2068 | */ |
2090 | if (AR_SREV_9462(ah)) { | 2069 | if (ath9k_hw_mci_is_enabled(ah)) |
2091 | val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) & | 2070 | REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN, |
2092 | ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK; | 2071 | AR_MCI_INTERRUPT_RX_HW_MSG_MASK); |
2093 | REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val); | 2072 | /* |
2094 | } | 2073 | * Clear the RTC force wake bit to allow the |
2095 | /* | 2074 | * mac to go to sleep. |
2096 | * Clear the RTC force wake bit to allow the | 2075 | */ |
2097 | * mac to go to sleep. | 2076 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); |
2098 | */ | 2077 | |
2099 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, | 2078 | if (ath9k_hw_mci_is_enabled(ah)) |
2100 | AR_RTC_FORCE_WAKE_EN); | 2079 | udelay(30); |
2101 | |||
2102 | if (AR_SREV_9462(ah)) | ||
2103 | udelay(30); | ||
2104 | } | ||
2105 | } | 2080 | } |
2106 | 2081 | ||
2107 | /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ | 2082 | /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ |
@@ -2109,7 +2084,7 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) | |||
2109 | REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); | 2084 | REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); |
2110 | } | 2085 | } |
2111 | 2086 | ||
2112 | static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | 2087 | static bool ath9k_hw_set_power_awake(struct ath_hw *ah) |
2113 | { | 2088 | { |
2114 | u32 val; | 2089 | u32 val; |
2115 | int i; | 2090 | int i; |
@@ -2120,37 +2095,35 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2120 | udelay(10); | 2095 | udelay(10); |
2121 | } | 2096 | } |
2122 | 2097 | ||
2123 | if (setChip) { | 2098 | if ((REG_READ(ah, AR_RTC_STATUS) & |
2124 | if ((REG_READ(ah, AR_RTC_STATUS) & | 2099 | AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { |
2125 | AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { | 2100 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { |
2126 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 2101 | return false; |
2127 | return false; | ||
2128 | } | ||
2129 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
2130 | ath9k_hw_init_pll(ah, NULL); | ||
2131 | } | 2102 | } |
2132 | if (AR_SREV_9100(ah)) | 2103 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
2133 | REG_SET_BIT(ah, AR_RTC_RESET, | 2104 | ath9k_hw_init_pll(ah, NULL); |
2134 | AR_RTC_RESET_EN); | 2105 | } |
2106 | if (AR_SREV_9100(ah)) | ||
2107 | REG_SET_BIT(ah, AR_RTC_RESET, | ||
2108 | AR_RTC_RESET_EN); | ||
2135 | 2109 | ||
2110 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
2111 | AR_RTC_FORCE_WAKE_EN); | ||
2112 | udelay(50); | ||
2113 | |||
2114 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | ||
2115 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | ||
2116 | if (val == AR_RTC_STATUS_ON) | ||
2117 | break; | ||
2118 | udelay(50); | ||
2136 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | 2119 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, |
2137 | AR_RTC_FORCE_WAKE_EN); | 2120 | AR_RTC_FORCE_WAKE_EN); |
2138 | udelay(50); | 2121 | } |
2139 | 2122 | if (i == 0) { | |
2140 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | 2123 | ath_err(ath9k_hw_common(ah), |
2141 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | 2124 | "Failed to wakeup in %uus\n", |
2142 | if (val == AR_RTC_STATUS_ON) | 2125 | POWER_UP_TIME / 20); |
2143 | break; | 2126 | return false; |
2144 | udelay(50); | ||
2145 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
2146 | AR_RTC_FORCE_WAKE_EN); | ||
2147 | } | ||
2148 | if (i == 0) { | ||
2149 | ath_err(ath9k_hw_common(ah), | ||
2150 | "Failed to wakeup in %uus\n", | ||
2151 | POWER_UP_TIME / 20); | ||
2152 | return false; | ||
2153 | } | ||
2154 | } | 2127 | } |
2155 | 2128 | ||
2156 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | 2129 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); |
@@ -2161,7 +2134,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2161 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | 2134 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) |
2162 | { | 2135 | { |
2163 | struct ath_common *common = ath9k_hw_common(ah); | 2136 | struct ath_common *common = ath9k_hw_common(ah); |
2164 | int status = true, setChip = true; | 2137 | int status = true; |
2165 | static const char *modes[] = { | 2138 | static const char *modes[] = { |
2166 | "AWAKE", | 2139 | "AWAKE", |
2167 | "FULL-SLEEP", | 2140 | "FULL-SLEEP", |
@@ -2177,25 +2150,17 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
2177 | 2150 | ||
2178 | switch (mode) { | 2151 | switch (mode) { |
2179 | case ATH9K_PM_AWAKE: | 2152 | case ATH9K_PM_AWAKE: |
2180 | status = ath9k_hw_set_power_awake(ah, setChip); | 2153 | status = ath9k_hw_set_power_awake(ah); |
2181 | |||
2182 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
2183 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
2184 | |||
2185 | break; | 2154 | break; |
2186 | case ATH9K_PM_FULL_SLEEP: | 2155 | case ATH9K_PM_FULL_SLEEP: |
2187 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | 2156 | if (ath9k_hw_mci_is_enabled(ah)) |
2188 | ar9003_mci_set_full_sleep(ah); | 2157 | ar9003_mci_set_full_sleep(ah); |
2189 | 2158 | ||
2190 | ath9k_set_power_sleep(ah, setChip); | 2159 | ath9k_set_power_sleep(ah); |
2191 | ah->chip_fullsleep = true; | 2160 | ah->chip_fullsleep = true; |
2192 | break; | 2161 | break; |
2193 | case ATH9K_PM_NETWORK_SLEEP: | 2162 | case ATH9K_PM_NETWORK_SLEEP: |
2194 | 2163 | ath9k_set_power_network_sleep(ah); | |
2195 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
2196 | REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); | ||
2197 | |||
2198 | ath9k_set_power_network_sleep(ah, setChip); | ||
2199 | break; | 2164 | break; |
2200 | default: | 2165 | default: |
2201 | ath_err(common, "Unknown power mode %u\n", mode); | 2166 | ath_err(common, "Unknown power mode %u\n", mode); |
@@ -2765,6 +2730,9 @@ EXPORT_SYMBOL(ath9k_hw_setrxfilter); | |||
2765 | 2730 | ||
2766 | bool ath9k_hw_phy_disable(struct ath_hw *ah) | 2731 | bool ath9k_hw_phy_disable(struct ath_hw *ah) |
2767 | { | 2732 | { |
2733 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2734 | ar9003_mci_bt_gain_ctrl(ah); | ||
2735 | |||
2768 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | 2736 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) |
2769 | return false; | 2737 | return false; |
2770 | 2738 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b620c557c2a6..03d590924c64 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -824,7 +824,6 @@ struct ath_hw { | |||
824 | struct ar5416IniArray ini_japan2484; | 824 | struct ar5416IniArray ini_japan2484; |
825 | struct ar5416IniArray iniModes_9271_ANI_reg; | 825 | struct ar5416IniArray iniModes_9271_ANI_reg; |
826 | struct ar5416IniArray ini_radio_post_sys2ant; | 826 | struct ar5416IniArray ini_radio_post_sys2ant; |
827 | struct ar5416IniArray ini_BTCOEX_MAX_TXPWR; | ||
828 | 827 | ||
829 | struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; | 828 | struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; |
830 | struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; | 829 | struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; |
@@ -1037,6 +1036,11 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) | |||
1037 | { | 1036 | { |
1038 | return ah->btcoex_hw.enabled; | 1037 | return ah->btcoex_hw.enabled; |
1039 | } | 1038 | } |
1039 | static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) | ||
1040 | { | ||
1041 | return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI); | ||
1042 | |||
1043 | } | ||
1040 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 1044 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
1041 | static inline enum ath_btcoex_scheme | 1045 | static inline enum ath_btcoex_scheme |
1042 | ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) | 1046 | ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) |
@@ -1048,6 +1052,10 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) | |||
1048 | { | 1052 | { |
1049 | return false; | 1053 | return false; |
1050 | } | 1054 | } |
1055 | static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) | ||
1056 | { | ||
1057 | return false; | ||
1058 | } | ||
1051 | static inline void ath9k_hw_btcoex_enable(struct ath_hw *ah) | 1059 | static inline void ath9k_hw_btcoex_enable(struct ath_hw *ah) |
1052 | { | 1060 | { |
1053 | } | 1061 | } |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index dee9e092449a..9dfce1a69c73 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -489,6 +489,7 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
489 | 489 | ||
490 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | 490 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); |
491 | 491 | ||
492 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
492 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | 493 | sc->config.txpowlimit = ATH_TXPOWER_MAX; |
493 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 494 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
494 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 495 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
@@ -560,6 +561,12 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
560 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | 561 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, |
561 | (unsigned long)sc); | 562 | (unsigned long)sc); |
562 | 563 | ||
564 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); | ||
565 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | ||
566 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | ||
567 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); | ||
568 | setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); | ||
569 | |||
563 | /* | 570 | /* |
564 | * Cache line size is used to size and align various | 571 | * Cache line size is used to size and align various |
565 | * structures used to communicate with the hardware. | 572 | * structures used to communicate with the hardware. |
@@ -590,6 +597,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
590 | ath9k_cmn_init_crypto(sc->sc_ah); | 597 | ath9k_cmn_init_crypto(sc->sc_ah); |
591 | ath9k_init_misc(sc); | 598 | ath9k_init_misc(sc); |
592 | 599 | ||
600 | if (common->bus_ops->aspm_init) | ||
601 | common->bus_ops->aspm_init(common); | ||
602 | |||
593 | return 0; | 603 | return 0; |
594 | 604 | ||
595 | err_btcoex: | 605 | err_btcoex: |
@@ -782,11 +792,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
782 | ARRAY_SIZE(ath9k_tpt_blink)); | 792 | ARRAY_SIZE(ath9k_tpt_blink)); |
783 | #endif | 793 | #endif |
784 | 794 | ||
785 | INIT_WORK(&sc->hw_reset_work, ath_reset_work); | ||
786 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | ||
787 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | ||
788 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); | ||
789 | |||
790 | /* Register with mac80211 */ | 795 | /* Register with mac80211 */ |
791 | error = ieee80211_register_hw(hw); | 796 | error = ieee80211_register_hw(hw); |
792 | if (error) | 797 | if (error) |
@@ -805,9 +810,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
805 | goto error_world; | 810 | goto error_world; |
806 | } | 811 | } |
807 | 812 | ||
808 | setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); | ||
809 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
810 | |||
811 | ath_init_leds(sc); | 813 | ath_init_leds(sc); |
812 | ath_start_rfkill_poll(sc); | 814 | ath_start_rfkill_poll(sc); |
813 | 815 | ||
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c new file mode 100644 index 000000000000..0cc4c70f7f0c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -0,0 +1,502 @@ | |||
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 "ath9k.h" | ||
18 | |||
19 | /* | ||
20 | * TX polling - checks if the TX engine is stuck somewhere | ||
21 | * and issues a chip reset if so. | ||
22 | */ | ||
23 | void ath_tx_complete_poll_work(struct work_struct *work) | ||
24 | { | ||
25 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
26 | tx_complete_work.work); | ||
27 | struct ath_txq *txq; | ||
28 | int i; | ||
29 | bool needreset = false; | ||
30 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
31 | sc->tx_complete_poll_work_seen++; | ||
32 | #endif | ||
33 | |||
34 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
35 | if (ATH_TXQ_SETUP(sc, i)) { | ||
36 | txq = &sc->tx.txq[i]; | ||
37 | ath_txq_lock(sc, txq); | ||
38 | if (txq->axq_depth) { | ||
39 | if (txq->axq_tx_inprogress) { | ||
40 | needreset = true; | ||
41 | ath_txq_unlock(sc, txq); | ||
42 | break; | ||
43 | } else { | ||
44 | txq->axq_tx_inprogress = true; | ||
45 | } | ||
46 | } | ||
47 | ath_txq_unlock_complete(sc, txq); | ||
48 | } | ||
49 | |||
50 | if (needreset) { | ||
51 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | ||
52 | "tx hung, resetting the chip\n"); | ||
53 | RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); | ||
54 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | ||
59 | msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Checks if the BB/MAC is hung. | ||
64 | */ | ||
65 | void ath_hw_check(struct work_struct *work) | ||
66 | { | ||
67 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | ||
68 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
69 | unsigned long flags; | ||
70 | int busy; | ||
71 | u8 is_alive, nbeacon = 1; | ||
72 | |||
73 | ath9k_ps_wakeup(sc); | ||
74 | is_alive = ath9k_hw_check_alive(sc->sc_ah); | ||
75 | |||
76 | if (is_alive && !AR_SREV_9300(sc->sc_ah)) | ||
77 | goto out; | ||
78 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | ||
79 | ath_dbg(common, RESET, | ||
80 | "DCU stuck is detected. Schedule chip reset\n"); | ||
81 | RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); | ||
82 | goto sched_reset; | ||
83 | } | ||
84 | |||
85 | spin_lock_irqsave(&common->cc_lock, flags); | ||
86 | busy = ath_update_survey_stats(sc); | ||
87 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
88 | |||
89 | ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", | ||
90 | busy, sc->hw_busy_count + 1); | ||
91 | if (busy >= 99) { | ||
92 | if (++sc->hw_busy_count >= 3) { | ||
93 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); | ||
94 | goto sched_reset; | ||
95 | } | ||
96 | } else if (busy >= 0) { | ||
97 | sc->hw_busy_count = 0; | ||
98 | nbeacon = 3; | ||
99 | } | ||
100 | |||
101 | ath_start_rx_poll(sc, nbeacon); | ||
102 | goto out; | ||
103 | |||
104 | sched_reset: | ||
105 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
106 | out: | ||
107 | ath9k_ps_restore(sc); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * PLL-WAR for AR9485/AR9340 | ||
112 | */ | ||
113 | static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | ||
114 | { | ||
115 | static int count; | ||
116 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
117 | |||
118 | if (pll_sqsum >= 0x40000) { | ||
119 | count++; | ||
120 | if (count == 3) { | ||
121 | ath_dbg(common, RESET, "PLL WAR, resetting the chip\n"); | ||
122 | RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); | ||
123 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
124 | count = 0; | ||
125 | return true; | ||
126 | } | ||
127 | } else { | ||
128 | count = 0; | ||
129 | } | ||
130 | |||
131 | return false; | ||
132 | } | ||
133 | |||
134 | void ath_hw_pll_work(struct work_struct *work) | ||
135 | { | ||
136 | u32 pll_sqsum; | ||
137 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
138 | hw_pll_work.work); | ||
139 | |||
140 | ath9k_ps_wakeup(sc); | ||
141 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | ||
142 | ath9k_ps_restore(sc); | ||
143 | if (ath_hw_pll_rx_hang_check(sc, pll_sqsum)) | ||
144 | return; | ||
145 | |||
146 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, | ||
147 | msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * RX Polling - monitors baseband hangs. | ||
152 | */ | ||
153 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) | ||
154 | { | ||
155 | if (!AR_SREV_9300(sc->sc_ah)) | ||
156 | return; | ||
157 | |||
158 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) | ||
159 | return; | ||
160 | |||
161 | mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies | ||
162 | (nbeacon * sc->cur_beacon_conf.beacon_interval)); | ||
163 | } | ||
164 | |||
165 | void ath_rx_poll(unsigned long data) | ||
166 | { | ||
167 | struct ath_softc *sc = (struct ath_softc *)data; | ||
168 | |||
169 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * PA Pre-distortion. | ||
174 | */ | ||
175 | static void ath_paprd_activate(struct ath_softc *sc) | ||
176 | { | ||
177 | struct ath_hw *ah = sc->sc_ah; | ||
178 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
179 | int chain; | ||
180 | |||
181 | if (!caldata || !caldata->paprd_done) | ||
182 | return; | ||
183 | |||
184 | ath9k_ps_wakeup(sc); | ||
185 | ar9003_paprd_enable(ah, false); | ||
186 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
187 | if (!(ah->txchainmask & BIT(chain))) | ||
188 | continue; | ||
189 | |||
190 | ar9003_paprd_populate_single_table(ah, caldata, chain); | ||
191 | } | ||
192 | |||
193 | ar9003_paprd_enable(ah, true); | ||
194 | ath9k_ps_restore(sc); | ||
195 | } | ||
196 | |||
197 | static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) | ||
198 | { | ||
199 | struct ieee80211_hw *hw = sc->hw; | ||
200 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
201 | struct ath_hw *ah = sc->sc_ah; | ||
202 | struct ath_common *common = ath9k_hw_common(ah); | ||
203 | struct ath_tx_control txctl; | ||
204 | int time_left; | ||
205 | |||
206 | memset(&txctl, 0, sizeof(txctl)); | ||
207 | txctl.txq = sc->tx.txq_map[WME_AC_BE]; | ||
208 | |||
209 | memset(tx_info, 0, sizeof(*tx_info)); | ||
210 | tx_info->band = hw->conf.channel->band; | ||
211 | tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
212 | tx_info->control.rates[0].idx = 0; | ||
213 | tx_info->control.rates[0].count = 1; | ||
214 | tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | ||
215 | tx_info->control.rates[1].idx = -1; | ||
216 | |||
217 | init_completion(&sc->paprd_complete); | ||
218 | txctl.paprd = BIT(chain); | ||
219 | |||
220 | if (ath_tx_start(hw, skb, &txctl) != 0) { | ||
221 | ath_dbg(common, CALIBRATE, "PAPRD TX failed\n"); | ||
222 | dev_kfree_skb_any(skb); | ||
223 | return false; | ||
224 | } | ||
225 | |||
226 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | ||
227 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | ||
228 | |||
229 | if (!time_left) | ||
230 | ath_dbg(common, CALIBRATE, | ||
231 | "Timeout waiting for paprd training on TX chain %d\n", | ||
232 | chain); | ||
233 | |||
234 | return !!time_left; | ||
235 | } | ||
236 | |||
237 | void ath_paprd_calibrate(struct work_struct *work) | ||
238 | { | ||
239 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); | ||
240 | struct ieee80211_hw *hw = sc->hw; | ||
241 | struct ath_hw *ah = sc->sc_ah; | ||
242 | struct ieee80211_hdr *hdr; | ||
243 | struct sk_buff *skb = NULL; | ||
244 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
245 | struct ath_common *common = ath9k_hw_common(ah); | ||
246 | int ftype; | ||
247 | int chain_ok = 0; | ||
248 | int chain; | ||
249 | int len = 1800; | ||
250 | |||
251 | if (!caldata) | ||
252 | return; | ||
253 | |||
254 | ath9k_ps_wakeup(sc); | ||
255 | |||
256 | if (ar9003_paprd_init_table(ah) < 0) | ||
257 | goto fail_paprd; | ||
258 | |||
259 | skb = alloc_skb(len, GFP_KERNEL); | ||
260 | if (!skb) | ||
261 | goto fail_paprd; | ||
262 | |||
263 | skb_put(skb, len); | ||
264 | memset(skb->data, 0, len); | ||
265 | hdr = (struct ieee80211_hdr *)skb->data; | ||
266 | ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; | ||
267 | hdr->frame_control = cpu_to_le16(ftype); | ||
268 | hdr->duration_id = cpu_to_le16(10); | ||
269 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
270 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
271 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
272 | |||
273 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
274 | if (!(ah->txchainmask & BIT(chain))) | ||
275 | continue; | ||
276 | |||
277 | chain_ok = 0; | ||
278 | |||
279 | ath_dbg(common, CALIBRATE, | ||
280 | "Sending PAPRD frame for thermal measurement on chain %d\n", | ||
281 | chain); | ||
282 | if (!ath_paprd_send_frame(sc, skb, chain)) | ||
283 | goto fail_paprd; | ||
284 | |||
285 | ar9003_paprd_setup_gain_table(ah, chain); | ||
286 | |||
287 | ath_dbg(common, CALIBRATE, | ||
288 | "Sending PAPRD training frame on chain %d\n", chain); | ||
289 | if (!ath_paprd_send_frame(sc, skb, chain)) | ||
290 | goto fail_paprd; | ||
291 | |||
292 | if (!ar9003_paprd_is_done(ah)) { | ||
293 | ath_dbg(common, CALIBRATE, | ||
294 | "PAPRD not yet done on chain %d\n", chain); | ||
295 | break; | ||
296 | } | ||
297 | |||
298 | if (ar9003_paprd_create_curve(ah, caldata, chain)) { | ||
299 | ath_dbg(common, CALIBRATE, | ||
300 | "PAPRD create curve failed on chain %d\n", | ||
301 | chain); | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | chain_ok = 1; | ||
306 | } | ||
307 | kfree_skb(skb); | ||
308 | |||
309 | if (chain_ok) { | ||
310 | caldata->paprd_done = true; | ||
311 | ath_paprd_activate(sc); | ||
312 | } | ||
313 | |||
314 | fail_paprd: | ||
315 | ath9k_ps_restore(sc); | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * ANI performs periodic noise floor calibration | ||
320 | * that is used to adjust and optimize the chip performance. This | ||
321 | * takes environmental changes (location, temperature) into account. | ||
322 | * When the task is complete, it reschedules itself depending on the | ||
323 | * appropriate interval that was calculated. | ||
324 | */ | ||
325 | void ath_ani_calibrate(unsigned long data) | ||
326 | { | ||
327 | struct ath_softc *sc = (struct ath_softc *)data; | ||
328 | struct ath_hw *ah = sc->sc_ah; | ||
329 | struct ath_common *common = ath9k_hw_common(ah); | ||
330 | bool longcal = false; | ||
331 | bool shortcal = false; | ||
332 | bool aniflag = false; | ||
333 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
334 | u32 cal_interval, short_cal_interval, long_cal_interval; | ||
335 | unsigned long flags; | ||
336 | |||
337 | if (ah->caldata && ah->caldata->nfcal_interference) | ||
338 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | ||
339 | else | ||
340 | long_cal_interval = ATH_LONG_CALINTERVAL; | ||
341 | |||
342 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | ||
343 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | ||
344 | |||
345 | /* Only calibrate if awake */ | ||
346 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | ||
347 | goto set_timer; | ||
348 | |||
349 | ath9k_ps_wakeup(sc); | ||
350 | |||
351 | /* Long calibration runs independently of short calibration. */ | ||
352 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { | ||
353 | longcal = true; | ||
354 | common->ani.longcal_timer = timestamp; | ||
355 | } | ||
356 | |||
357 | /* Short calibration applies only while caldone is false */ | ||
358 | if (!common->ani.caldone) { | ||
359 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { | ||
360 | shortcal = true; | ||
361 | common->ani.shortcal_timer = timestamp; | ||
362 | common->ani.resetcal_timer = timestamp; | ||
363 | } | ||
364 | } else { | ||
365 | if ((timestamp - common->ani.resetcal_timer) >= | ||
366 | ATH_RESTART_CALINTERVAL) { | ||
367 | common->ani.caldone = ath9k_hw_reset_calvalid(ah); | ||
368 | if (common->ani.caldone) | ||
369 | common->ani.resetcal_timer = timestamp; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* Verify whether we must check ANI */ | ||
374 | if (sc->sc_ah->config.enable_ani | ||
375 | && (timestamp - common->ani.checkani_timer) >= | ||
376 | ah->config.ani_poll_interval) { | ||
377 | aniflag = true; | ||
378 | common->ani.checkani_timer = timestamp; | ||
379 | } | ||
380 | |||
381 | /* Call ANI routine if necessary */ | ||
382 | if (aniflag) { | ||
383 | spin_lock_irqsave(&common->cc_lock, flags); | ||
384 | ath9k_hw_ani_monitor(ah, ah->curchan); | ||
385 | ath_update_survey_stats(sc); | ||
386 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
387 | } | ||
388 | |||
389 | /* Perform calibration if necessary */ | ||
390 | if (longcal || shortcal) { | ||
391 | common->ani.caldone = | ||
392 | ath9k_hw_calibrate(ah, ah->curchan, | ||
393 | ah->rxchainmask, longcal); | ||
394 | } | ||
395 | |||
396 | ath_dbg(common, ANI, | ||
397 | "Calibration @%lu finished: %s %s %s, caldone: %s\n", | ||
398 | jiffies, | ||
399 | longcal ? "long" : "", shortcal ? "short" : "", | ||
400 | aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); | ||
401 | |||
402 | ath9k_ps_restore(sc); | ||
403 | |||
404 | set_timer: | ||
405 | /* | ||
406 | * Set timer interval based on previous results. | ||
407 | * The interval must be the shortest necessary to satisfy ANI, | ||
408 | * short calibration and long calibration. | ||
409 | */ | ||
410 | ath9k_debug_samp_bb_mac(sc); | ||
411 | cal_interval = ATH_LONG_CALINTERVAL; | ||
412 | if (sc->sc_ah->config.enable_ani) | ||
413 | cal_interval = min(cal_interval, | ||
414 | (u32)ah->config.ani_poll_interval); | ||
415 | if (!common->ani.caldone) | ||
416 | cal_interval = min(cal_interval, (u32)short_cal_interval); | ||
417 | |||
418 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | ||
419 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { | ||
420 | if (!ah->caldata->paprd_done) | ||
421 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | ||
422 | else if (!ah->paprd_table_write_done) | ||
423 | ath_paprd_activate(sc); | ||
424 | } | ||
425 | } | ||
426 | |||
427 | void ath_start_ani(struct ath_common *common) | ||
428 | { | ||
429 | struct ath_hw *ah = common->ah; | ||
430 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
431 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
432 | |||
433 | if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) | ||
434 | return; | ||
435 | |||
436 | if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | ||
437 | return; | ||
438 | |||
439 | common->ani.longcal_timer = timestamp; | ||
440 | common->ani.shortcal_timer = timestamp; | ||
441 | common->ani.checkani_timer = timestamp; | ||
442 | |||
443 | mod_timer(&common->ani.timer, | ||
444 | jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
445 | } | ||
446 | |||
447 | void ath_update_survey_nf(struct ath_softc *sc, int channel) | ||
448 | { | ||
449 | struct ath_hw *ah = sc->sc_ah; | ||
450 | struct ath9k_channel *chan = &ah->channels[channel]; | ||
451 | struct survey_info *survey = &sc->survey[channel]; | ||
452 | |||
453 | if (chan->noisefloor) { | ||
454 | survey->filled |= SURVEY_INFO_NOISE_DBM; | ||
455 | survey->noise = ath9k_hw_getchan_noise(ah, chan); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Updates the survey statistics and returns the busy time since last | ||
461 | * update in %, if the measurement duration was long enough for the | ||
462 | * result to be useful, -1 otherwise. | ||
463 | */ | ||
464 | int ath_update_survey_stats(struct ath_softc *sc) | ||
465 | { | ||
466 | struct ath_hw *ah = sc->sc_ah; | ||
467 | struct ath_common *common = ath9k_hw_common(ah); | ||
468 | int pos = ah->curchan - &ah->channels[0]; | ||
469 | struct survey_info *survey = &sc->survey[pos]; | ||
470 | struct ath_cycle_counters *cc = &common->cc_survey; | ||
471 | unsigned int div = common->clockrate * 1000; | ||
472 | int ret = 0; | ||
473 | |||
474 | if (!ah->curchan) | ||
475 | return -1; | ||
476 | |||
477 | if (ah->power_mode == ATH9K_PM_AWAKE) | ||
478 | ath_hw_cycle_counters_update(common); | ||
479 | |||
480 | if (cc->cycles > 0) { | ||
481 | survey->filled |= SURVEY_INFO_CHANNEL_TIME | | ||
482 | SURVEY_INFO_CHANNEL_TIME_BUSY | | ||
483 | SURVEY_INFO_CHANNEL_TIME_RX | | ||
484 | SURVEY_INFO_CHANNEL_TIME_TX; | ||
485 | survey->channel_time += cc->cycles / div; | ||
486 | survey->channel_time_busy += cc->rx_busy / div; | ||
487 | survey->channel_time_rx += cc->rx_frame / div; | ||
488 | survey->channel_time_tx += cc->tx_frame / div; | ||
489 | } | ||
490 | |||
491 | if (cc->cycles < div) | ||
492 | return -1; | ||
493 | |||
494 | if (cc->cycles > 0) | ||
495 | ret = cc->rx_busy * 100 / cc->cycles; | ||
496 | |||
497 | memset(cc, 0, sizeof(*cc)); | ||
498 | |||
499 | ath_update_survey_nf(sc, pos); | ||
500 | |||
501 | return ret; | ||
502 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4de4473776ac..c0f478b0a9a2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -101,6 +101,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc) | |||
101 | spin_lock(&common->cc_lock); | 101 | spin_lock(&common->cc_lock); |
102 | ath_hw_cycle_counters_update(common); | 102 | ath_hw_cycle_counters_update(common); |
103 | memset(&common->cc_survey, 0, sizeof(common->cc_survey)); | 103 | memset(&common->cc_survey, 0, sizeof(common->cc_survey)); |
104 | memset(&common->cc_ani, 0, sizeof(common->cc_ani)); | ||
104 | spin_unlock(&common->cc_lock); | 105 | spin_unlock(&common->cc_lock); |
105 | } | 106 | } |
106 | 107 | ||
@@ -143,84 +144,6 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
143 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 144 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
144 | } | 145 | } |
145 | 146 | ||
146 | void ath_start_ani(struct ath_common *common) | ||
147 | { | ||
148 | struct ath_hw *ah = common->ah; | ||
149 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
150 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
151 | |||
152 | if (!(sc->sc_flags & SC_OP_ANI_RUN)) | ||
153 | return; | ||
154 | |||
155 | if (sc->sc_flags & SC_OP_OFFCHANNEL) | ||
156 | return; | ||
157 | |||
158 | common->ani.longcal_timer = timestamp; | ||
159 | common->ani.shortcal_timer = timestamp; | ||
160 | common->ani.checkani_timer = timestamp; | ||
161 | |||
162 | mod_timer(&common->ani.timer, | ||
163 | jiffies + | ||
164 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
165 | } | ||
166 | |||
167 | static void ath_update_survey_nf(struct ath_softc *sc, int channel) | ||
168 | { | ||
169 | struct ath_hw *ah = sc->sc_ah; | ||
170 | struct ath9k_channel *chan = &ah->channels[channel]; | ||
171 | struct survey_info *survey = &sc->survey[channel]; | ||
172 | |||
173 | if (chan->noisefloor) { | ||
174 | survey->filled |= SURVEY_INFO_NOISE_DBM; | ||
175 | survey->noise = ath9k_hw_getchan_noise(ah, chan); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Updates the survey statistics and returns the busy time since last | ||
181 | * update in %, if the measurement duration was long enough for the | ||
182 | * result to be useful, -1 otherwise. | ||
183 | */ | ||
184 | static int ath_update_survey_stats(struct ath_softc *sc) | ||
185 | { | ||
186 | struct ath_hw *ah = sc->sc_ah; | ||
187 | struct ath_common *common = ath9k_hw_common(ah); | ||
188 | int pos = ah->curchan - &ah->channels[0]; | ||
189 | struct survey_info *survey = &sc->survey[pos]; | ||
190 | struct ath_cycle_counters *cc = &common->cc_survey; | ||
191 | unsigned int div = common->clockrate * 1000; | ||
192 | int ret = 0; | ||
193 | |||
194 | if (!ah->curchan) | ||
195 | return -1; | ||
196 | |||
197 | if (ah->power_mode == ATH9K_PM_AWAKE) | ||
198 | ath_hw_cycle_counters_update(common); | ||
199 | |||
200 | if (cc->cycles > 0) { | ||
201 | survey->filled |= SURVEY_INFO_CHANNEL_TIME | | ||
202 | SURVEY_INFO_CHANNEL_TIME_BUSY | | ||
203 | SURVEY_INFO_CHANNEL_TIME_RX | | ||
204 | SURVEY_INFO_CHANNEL_TIME_TX; | ||
205 | survey->channel_time += cc->cycles / div; | ||
206 | survey->channel_time_busy += cc->rx_busy / div; | ||
207 | survey->channel_time_rx += cc->rx_frame / div; | ||
208 | survey->channel_time_tx += cc->tx_frame / div; | ||
209 | } | ||
210 | |||
211 | if (cc->cycles < div) | ||
212 | return -1; | ||
213 | |||
214 | if (cc->cycles > 0) | ||
215 | ret = cc->rx_busy * 100 / cc->cycles; | ||
216 | |||
217 | memset(cc, 0, sizeof(*cc)); | ||
218 | |||
219 | ath_update_survey_nf(sc, pos); | ||
220 | |||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | static void __ath_cancel_work(struct ath_softc *sc) | 147 | static void __ath_cancel_work(struct ath_softc *sc) |
225 | { | 148 | { |
226 | cancel_work_sync(&sc->paprd_work); | 149 | cancel_work_sync(&sc->paprd_work); |
@@ -235,6 +158,22 @@ static void ath_cancel_work(struct ath_softc *sc) | |||
235 | cancel_work_sync(&sc->hw_reset_work); | 158 | cancel_work_sync(&sc->hw_reset_work); |
236 | } | 159 | } |
237 | 160 | ||
161 | static void ath_restart_work(struct ath_softc *sc) | ||
162 | { | ||
163 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
164 | |||
165 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
166 | |||
167 | if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah)) | ||
168 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, | ||
169 | msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); | ||
170 | |||
171 | ath_start_rx_poll(sc, 3); | ||
172 | |||
173 | if (!common->disable_ani) | ||
174 | ath_start_ani(common); | ||
175 | } | ||
176 | |||
238 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | 177 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) |
239 | { | 178 | { |
240 | struct ath_hw *ah = sc->sc_ah; | 179 | struct ath_hw *ah = sc->sc_ah; |
@@ -271,6 +210,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
271 | { | 210 | { |
272 | struct ath_hw *ah = sc->sc_ah; | 211 | struct ath_hw *ah = sc->sc_ah; |
273 | struct ath_common *common = ath9k_hw_common(ah); | 212 | struct ath_common *common = ath9k_hw_common(ah); |
213 | unsigned long flags; | ||
274 | 214 | ||
275 | if (ath_startrecv(sc) != 0) { | 215 | if (ath_startrecv(sc) != 0) { |
276 | ath_err(common, "Unable to restart recv logic\n"); | 216 | ath_err(common, "Unable to restart recv logic\n"); |
@@ -279,36 +219,30 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
279 | 219 | ||
280 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 220 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
281 | sc->config.txpowlimit, &sc->curtxpow); | 221 | sc->config.txpowlimit, &sc->curtxpow); |
222 | |||
223 | clear_bit(SC_OP_HW_RESET, &sc->sc_flags); | ||
282 | ath9k_hw_set_interrupts(ah); | 224 | ath9k_hw_set_interrupts(ah); |
283 | ath9k_hw_enable_interrupts(ah); | 225 | ath9k_hw_enable_interrupts(ah); |
284 | 226 | ||
285 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) { | 227 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) { |
286 | if (sc->sc_flags & SC_OP_BEACONS) | 228 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
287 | ath_set_beacon(sc); | 229 | goto work; |
288 | 230 | ||
289 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 231 | ath_set_beacon(sc); |
290 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); | ||
291 | ath_start_rx_poll(sc, 3); | ||
292 | if (!common->disable_ani) | ||
293 | ath_start_ani(common); | ||
294 | } | ||
295 | |||
296 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { | ||
297 | struct ath_hw_antcomb_conf div_ant_conf; | ||
298 | u8 lna_conf; | ||
299 | |||
300 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
301 | |||
302 | if (sc->ant_rx == 1) | ||
303 | lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
304 | else | ||
305 | lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
306 | div_ant_conf.main_lna_conf = lna_conf; | ||
307 | div_ant_conf.alt_lna_conf = lna_conf; | ||
308 | 232 | ||
309 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | 233 | if (ah->opmode == NL80211_IFTYPE_STATION && |
234 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | ||
235 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
236 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | ||
237 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
238 | } | ||
239 | work: | ||
240 | ath_restart_work(sc); | ||
310 | } | 241 | } |
311 | 242 | ||
243 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) | ||
244 | ath_ant_comb_update(sc); | ||
245 | |||
312 | ieee80211_wake_queues(sc->hw); | 246 | ieee80211_wake_queues(sc->hw); |
313 | 247 | ||
314 | return true; | 248 | return true; |
@@ -328,7 +262,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
328 | 262 | ||
329 | spin_lock_bh(&sc->sc_pcu_lock); | 263 | spin_lock_bh(&sc->sc_pcu_lock); |
330 | 264 | ||
331 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { | 265 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { |
332 | fastcc = false; | 266 | fastcc = false; |
333 | caldata = &sc->caldata; | 267 | caldata = &sc->caldata; |
334 | } | 268 | } |
@@ -371,7 +305,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
371 | { | 305 | { |
372 | int r; | 306 | int r; |
373 | 307 | ||
374 | if (sc->sc_flags & SC_OP_INVALID) | 308 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
375 | return -EIO; | 309 | return -EIO; |
376 | 310 | ||
377 | r = ath_reset_internal(sc, hchan, false); | 311 | r = ath_reset_internal(sc, hchan, false); |
@@ -379,258 +313,6 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
379 | return r; | 313 | return r; |
380 | } | 314 | } |
381 | 315 | ||
382 | static void ath_paprd_activate(struct ath_softc *sc) | ||
383 | { | ||
384 | struct ath_hw *ah = sc->sc_ah; | ||
385 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
386 | int chain; | ||
387 | |||
388 | if (!caldata || !caldata->paprd_done) | ||
389 | return; | ||
390 | |||
391 | ath9k_ps_wakeup(sc); | ||
392 | ar9003_paprd_enable(ah, false); | ||
393 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
394 | if (!(ah->txchainmask & BIT(chain))) | ||
395 | continue; | ||
396 | |||
397 | ar9003_paprd_populate_single_table(ah, caldata, chain); | ||
398 | } | ||
399 | |||
400 | ar9003_paprd_enable(ah, true); | ||
401 | ath9k_ps_restore(sc); | ||
402 | } | ||
403 | |||
404 | static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) | ||
405 | { | ||
406 | struct ieee80211_hw *hw = sc->hw; | ||
407 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
408 | struct ath_hw *ah = sc->sc_ah; | ||
409 | struct ath_common *common = ath9k_hw_common(ah); | ||
410 | struct ath_tx_control txctl; | ||
411 | int time_left; | ||
412 | |||
413 | memset(&txctl, 0, sizeof(txctl)); | ||
414 | txctl.txq = sc->tx.txq_map[WME_AC_BE]; | ||
415 | |||
416 | memset(tx_info, 0, sizeof(*tx_info)); | ||
417 | tx_info->band = hw->conf.channel->band; | ||
418 | tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
419 | tx_info->control.rates[0].idx = 0; | ||
420 | tx_info->control.rates[0].count = 1; | ||
421 | tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | ||
422 | tx_info->control.rates[1].idx = -1; | ||
423 | |||
424 | init_completion(&sc->paprd_complete); | ||
425 | txctl.paprd = BIT(chain); | ||
426 | |||
427 | if (ath_tx_start(hw, skb, &txctl) != 0) { | ||
428 | ath_dbg(common, CALIBRATE, "PAPRD TX failed\n"); | ||
429 | dev_kfree_skb_any(skb); | ||
430 | return false; | ||
431 | } | ||
432 | |||
433 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | ||
434 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | ||
435 | |||
436 | if (!time_left) | ||
437 | ath_dbg(common, CALIBRATE, | ||
438 | "Timeout waiting for paprd training on TX chain %d\n", | ||
439 | chain); | ||
440 | |||
441 | return !!time_left; | ||
442 | } | ||
443 | |||
444 | void ath_paprd_calibrate(struct work_struct *work) | ||
445 | { | ||
446 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); | ||
447 | struct ieee80211_hw *hw = sc->hw; | ||
448 | struct ath_hw *ah = sc->sc_ah; | ||
449 | struct ieee80211_hdr *hdr; | ||
450 | struct sk_buff *skb = NULL; | ||
451 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
452 | struct ath_common *common = ath9k_hw_common(ah); | ||
453 | int ftype; | ||
454 | int chain_ok = 0; | ||
455 | int chain; | ||
456 | int len = 1800; | ||
457 | |||
458 | if (!caldata) | ||
459 | return; | ||
460 | |||
461 | ath9k_ps_wakeup(sc); | ||
462 | |||
463 | if (ar9003_paprd_init_table(ah) < 0) | ||
464 | goto fail_paprd; | ||
465 | |||
466 | skb = alloc_skb(len, GFP_KERNEL); | ||
467 | if (!skb) | ||
468 | goto fail_paprd; | ||
469 | |||
470 | skb_put(skb, len); | ||
471 | memset(skb->data, 0, len); | ||
472 | hdr = (struct ieee80211_hdr *)skb->data; | ||
473 | ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; | ||
474 | hdr->frame_control = cpu_to_le16(ftype); | ||
475 | hdr->duration_id = cpu_to_le16(10); | ||
476 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
477 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
478 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
479 | |||
480 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
481 | if (!(ah->txchainmask & BIT(chain))) | ||
482 | continue; | ||
483 | |||
484 | chain_ok = 0; | ||
485 | |||
486 | ath_dbg(common, CALIBRATE, | ||
487 | "Sending PAPRD frame for thermal measurement on chain %d\n", | ||
488 | chain); | ||
489 | if (!ath_paprd_send_frame(sc, skb, chain)) | ||
490 | goto fail_paprd; | ||
491 | |||
492 | ar9003_paprd_setup_gain_table(ah, chain); | ||
493 | |||
494 | ath_dbg(common, CALIBRATE, | ||
495 | "Sending PAPRD training frame on chain %d\n", chain); | ||
496 | if (!ath_paprd_send_frame(sc, skb, chain)) | ||
497 | goto fail_paprd; | ||
498 | |||
499 | if (!ar9003_paprd_is_done(ah)) { | ||
500 | ath_dbg(common, CALIBRATE, | ||
501 | "PAPRD not yet done on chain %d\n", chain); | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | if (ar9003_paprd_create_curve(ah, caldata, chain)) { | ||
506 | ath_dbg(common, CALIBRATE, | ||
507 | "PAPRD create curve failed on chain %d\n", | ||
508 | chain); | ||
509 | break; | ||
510 | } | ||
511 | |||
512 | chain_ok = 1; | ||
513 | } | ||
514 | kfree_skb(skb); | ||
515 | |||
516 | if (chain_ok) { | ||
517 | caldata->paprd_done = true; | ||
518 | ath_paprd_activate(sc); | ||
519 | } | ||
520 | |||
521 | fail_paprd: | ||
522 | ath9k_ps_restore(sc); | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * This routine performs the periodic noise floor calibration function | ||
527 | * that is used to adjust and optimize the chip performance. This | ||
528 | * takes environmental changes (location, temperature) into account. | ||
529 | * When the task is complete, it reschedules itself depending on the | ||
530 | * appropriate interval that was calculated. | ||
531 | */ | ||
532 | void ath_ani_calibrate(unsigned long data) | ||
533 | { | ||
534 | struct ath_softc *sc = (struct ath_softc *)data; | ||
535 | struct ath_hw *ah = sc->sc_ah; | ||
536 | struct ath_common *common = ath9k_hw_common(ah); | ||
537 | bool longcal = false; | ||
538 | bool shortcal = false; | ||
539 | bool aniflag = false; | ||
540 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
541 | u32 cal_interval, short_cal_interval, long_cal_interval; | ||
542 | unsigned long flags; | ||
543 | |||
544 | if (ah->caldata && ah->caldata->nfcal_interference) | ||
545 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | ||
546 | else | ||
547 | long_cal_interval = ATH_LONG_CALINTERVAL; | ||
548 | |||
549 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | ||
550 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | ||
551 | |||
552 | /* Only calibrate if awake */ | ||
553 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | ||
554 | goto set_timer; | ||
555 | |||
556 | ath9k_ps_wakeup(sc); | ||
557 | |||
558 | /* Long calibration runs independently of short calibration. */ | ||
559 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { | ||
560 | longcal = true; | ||
561 | common->ani.longcal_timer = timestamp; | ||
562 | } | ||
563 | |||
564 | /* Short calibration applies only while caldone is false */ | ||
565 | if (!common->ani.caldone) { | ||
566 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { | ||
567 | shortcal = true; | ||
568 | common->ani.shortcal_timer = timestamp; | ||
569 | common->ani.resetcal_timer = timestamp; | ||
570 | } | ||
571 | } else { | ||
572 | if ((timestamp - common->ani.resetcal_timer) >= | ||
573 | ATH_RESTART_CALINTERVAL) { | ||
574 | common->ani.caldone = ath9k_hw_reset_calvalid(ah); | ||
575 | if (common->ani.caldone) | ||
576 | common->ani.resetcal_timer = timestamp; | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /* Verify whether we must check ANI */ | ||
581 | if (sc->sc_ah->config.enable_ani | ||
582 | && (timestamp - common->ani.checkani_timer) >= | ||
583 | ah->config.ani_poll_interval) { | ||
584 | aniflag = true; | ||
585 | common->ani.checkani_timer = timestamp; | ||
586 | } | ||
587 | |||
588 | /* Call ANI routine if necessary */ | ||
589 | if (aniflag) { | ||
590 | spin_lock_irqsave(&common->cc_lock, flags); | ||
591 | ath9k_hw_ani_monitor(ah, ah->curchan); | ||
592 | ath_update_survey_stats(sc); | ||
593 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
594 | } | ||
595 | |||
596 | /* Perform calibration if necessary */ | ||
597 | if (longcal || shortcal) { | ||
598 | common->ani.caldone = | ||
599 | ath9k_hw_calibrate(ah, ah->curchan, | ||
600 | ah->rxchainmask, longcal); | ||
601 | } | ||
602 | |||
603 | ath_dbg(common, ANI, | ||
604 | "Calibration @%lu finished: %s %s %s, caldone: %s\n", | ||
605 | jiffies, | ||
606 | longcal ? "long" : "", shortcal ? "short" : "", | ||
607 | aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); | ||
608 | |||
609 | ath9k_ps_restore(sc); | ||
610 | |||
611 | set_timer: | ||
612 | /* | ||
613 | * Set timer interval based on previous results. | ||
614 | * The interval must be the shortest necessary to satisfy ANI, | ||
615 | * short calibration and long calibration. | ||
616 | */ | ||
617 | ath9k_debug_samp_bb_mac(sc); | ||
618 | cal_interval = ATH_LONG_CALINTERVAL; | ||
619 | if (sc->sc_ah->config.enable_ani) | ||
620 | cal_interval = min(cal_interval, | ||
621 | (u32)ah->config.ani_poll_interval); | ||
622 | if (!common->ani.caldone) | ||
623 | cal_interval = min(cal_interval, (u32)short_cal_interval); | ||
624 | |||
625 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | ||
626 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { | ||
627 | if (!ah->caldata->paprd_done) | ||
628 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | ||
629 | else if (!ah->paprd_table_write_done) | ||
630 | ath_paprd_activate(sc); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | 316 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, |
635 | struct ieee80211_vif *vif) | 317 | struct ieee80211_vif *vif) |
636 | { | 318 | { |
@@ -668,13 +350,12 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
668 | ath_tx_node_cleanup(sc, an); | 350 | ath_tx_node_cleanup(sc, an); |
669 | } | 351 | } |
670 | 352 | ||
671 | |||
672 | void ath9k_tasklet(unsigned long data) | 353 | void ath9k_tasklet(unsigned long data) |
673 | { | 354 | { |
674 | struct ath_softc *sc = (struct ath_softc *)data; | 355 | struct ath_softc *sc = (struct ath_softc *)data; |
675 | struct ath_hw *ah = sc->sc_ah; | 356 | struct ath_hw *ah = sc->sc_ah; |
676 | struct ath_common *common = ath9k_hw_common(ah); | 357 | struct ath_common *common = ath9k_hw_common(ah); |
677 | 358 | unsigned long flags; | |
678 | u32 status = sc->intrstatus; | 359 | u32 status = sc->intrstatus; |
679 | u32 rxmask; | 360 | u32 rxmask; |
680 | 361 | ||
@@ -693,10 +374,12 @@ void ath9k_tasklet(unsigned long data) | |||
693 | 374 | ||
694 | RESET_STAT_INC(sc, type); | 375 | RESET_STAT_INC(sc, type); |
695 | #endif | 376 | #endif |
377 | set_bit(SC_OP_HW_RESET, &sc->sc_flags); | ||
696 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 378 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
697 | goto out; | 379 | goto out; |
698 | } | 380 | } |
699 | 381 | ||
382 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
700 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | 383 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { |
701 | /* | 384 | /* |
702 | * TSF sync does not look correct; remain awake to sync with | 385 | * TSF sync does not look correct; remain awake to sync with |
@@ -705,6 +388,7 @@ void ath9k_tasklet(unsigned long data) | |||
705 | ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n"); | 388 | ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n"); |
706 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; | 389 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; |
707 | } | 390 | } |
391 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
708 | 392 | ||
709 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 393 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
710 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | | 394 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | |
@@ -766,15 +450,17 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
766 | * touch anything. Note this can happen early | 450 | * touch anything. Note this can happen early |
767 | * on if the IRQ is shared. | 451 | * on if the IRQ is shared. |
768 | */ | 452 | */ |
769 | if (sc->sc_flags & SC_OP_INVALID) | 453 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
770 | return IRQ_NONE; | 454 | return IRQ_NONE; |
771 | 455 | ||
772 | |||
773 | /* shared irq, not for us */ | 456 | /* shared irq, not for us */ |
774 | 457 | ||
775 | if (!ath9k_hw_intrpend(ah)) | 458 | if (!ath9k_hw_intrpend(ah)) |
776 | return IRQ_NONE; | 459 | return IRQ_NONE; |
777 | 460 | ||
461 | if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) | ||
462 | return IRQ_HANDLED; | ||
463 | |||
778 | /* | 464 | /* |
779 | * Figure out the reason(s) for the interrupt. Note | 465 | * Figure out the reason(s) for the interrupt. Note |
780 | * that the hal returns a pseudo-ISR that may include | 466 | * that the hal returns a pseudo-ISR that may include |
@@ -852,8 +538,10 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
852 | /* Clear RxAbort bit so that we can | 538 | /* Clear RxAbort bit so that we can |
853 | * receive frames */ | 539 | * receive frames */ |
854 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 540 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
541 | spin_lock(&sc->sc_pm_lock); | ||
855 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 542 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
856 | sc->ps_flags |= PS_WAIT_FOR_BEACON; | 543 | sc->ps_flags |= PS_WAIT_FOR_BEACON; |
544 | spin_unlock(&sc->sc_pm_lock); | ||
857 | } | 545 | } |
858 | 546 | ||
859 | chip_reset: | 547 | chip_reset: |
@@ -902,87 +590,6 @@ void ath_reset_work(struct work_struct *work) | |||
902 | ath_reset(sc, true); | 590 | ath_reset(sc, true); |
903 | } | 591 | } |
904 | 592 | ||
905 | void ath_hw_check(struct work_struct *work) | ||
906 | { | ||
907 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | ||
908 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
909 | unsigned long flags; | ||
910 | int busy; | ||
911 | u8 is_alive, nbeacon = 1; | ||
912 | |||
913 | ath9k_ps_wakeup(sc); | ||
914 | is_alive = ath9k_hw_check_alive(sc->sc_ah); | ||
915 | |||
916 | if (is_alive && !AR_SREV_9300(sc->sc_ah)) | ||
917 | goto out; | ||
918 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | ||
919 | ath_dbg(common, RESET, | ||
920 | "DCU stuck is detected. Schedule chip reset\n"); | ||
921 | RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); | ||
922 | goto sched_reset; | ||
923 | } | ||
924 | |||
925 | spin_lock_irqsave(&common->cc_lock, flags); | ||
926 | busy = ath_update_survey_stats(sc); | ||
927 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
928 | |||
929 | ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", | ||
930 | busy, sc->hw_busy_count + 1); | ||
931 | if (busy >= 99) { | ||
932 | if (++sc->hw_busy_count >= 3) { | ||
933 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); | ||
934 | goto sched_reset; | ||
935 | } | ||
936 | } else if (busy >= 0) { | ||
937 | sc->hw_busy_count = 0; | ||
938 | nbeacon = 3; | ||
939 | } | ||
940 | |||
941 | ath_start_rx_poll(sc, nbeacon); | ||
942 | goto out; | ||
943 | |||
944 | sched_reset: | ||
945 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
946 | out: | ||
947 | ath9k_ps_restore(sc); | ||
948 | } | ||
949 | |||
950 | static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | ||
951 | { | ||
952 | static int count; | ||
953 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
954 | |||
955 | if (pll_sqsum >= 0x40000) { | ||
956 | count++; | ||
957 | if (count == 3) { | ||
958 | /* Rx is hung for more than 500ms. Reset it */ | ||
959 | ath_dbg(common, RESET, "Possible RX hang, resetting\n"); | ||
960 | RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); | ||
961 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
962 | count = 0; | ||
963 | } | ||
964 | } else | ||
965 | count = 0; | ||
966 | } | ||
967 | |||
968 | void ath_hw_pll_work(struct work_struct *work) | ||
969 | { | ||
970 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
971 | hw_pll_work.work); | ||
972 | u32 pll_sqsum; | ||
973 | |||
974 | if (AR_SREV_9485(sc->sc_ah)) { | ||
975 | |||
976 | ath9k_ps_wakeup(sc); | ||
977 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | ||
978 | ath9k_ps_restore(sc); | ||
979 | |||
980 | ath_hw_pll_rx_hang_check(sc, pll_sqsum); | ||
981 | |||
982 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); | ||
983 | } | ||
984 | } | ||
985 | |||
986 | /**********************/ | 593 | /**********************/ |
987 | /* mac80211 callbacks */ | 594 | /* mac80211 callbacks */ |
988 | /**********************/ | 595 | /**********************/ |
@@ -1045,10 +652,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1045 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 652 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1046 | ah->imask |= ATH9K_INT_CST; | 653 | ah->imask |= ATH9K_INT_CST; |
1047 | 654 | ||
1048 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | 655 | ath_mci_enable(sc); |
1049 | ah->imask |= ATH9K_INT_MCI; | ||
1050 | 656 | ||
1051 | sc->sc_flags &= ~SC_OP_INVALID; | 657 | clear_bit(SC_OP_INVALID, &sc->sc_flags); |
1052 | sc->sc_ah->is_monitoring = false; | 658 | sc->sc_ah->is_monitoring = false; |
1053 | 659 | ||
1054 | if (!ath_complete_reset(sc, false)) { | 660 | if (!ath_complete_reset(sc, false)) { |
@@ -1090,6 +696,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1090 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 696 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1091 | struct ath_tx_control txctl; | 697 | struct ath_tx_control txctl; |
1092 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 698 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
699 | unsigned long flags; | ||
1093 | 700 | ||
1094 | if (sc->ps_enabled) { | 701 | if (sc->ps_enabled) { |
1095 | /* | 702 | /* |
@@ -1112,6 +719,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1112 | * completed and if needed, also for RX of buffered frames. | 719 | * completed and if needed, also for RX of buffered frames. |
1113 | */ | 720 | */ |
1114 | ath9k_ps_wakeup(sc); | 721 | ath9k_ps_wakeup(sc); |
722 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1115 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 723 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
1116 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 724 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
1117 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 725 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
@@ -1127,6 +735,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1127 | * the ps_flags bit is cleared. We are just dropping | 735 | * the ps_flags bit is cleared. We are just dropping |
1128 | * the ps_usecount here. | 736 | * the ps_usecount here. |
1129 | */ | 737 | */ |
738 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1130 | ath9k_ps_restore(sc); | 739 | ath9k_ps_restore(sc); |
1131 | } | 740 | } |
1132 | 741 | ||
@@ -1167,7 +776,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1167 | ath_cancel_work(sc); | 776 | ath_cancel_work(sc); |
1168 | del_timer_sync(&sc->rx_poll_timer); | 777 | del_timer_sync(&sc->rx_poll_timer); |
1169 | 778 | ||
1170 | if (sc->sc_flags & SC_OP_INVALID) { | 779 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { |
1171 | ath_dbg(common, ANY, "Device not present\n"); | 780 | ath_dbg(common, ANY, "Device not present\n"); |
1172 | mutex_unlock(&sc->mutex); | 781 | mutex_unlock(&sc->mutex); |
1173 | return; | 782 | return; |
@@ -1224,7 +833,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1224 | 833 | ||
1225 | ath9k_ps_restore(sc); | 834 | ath9k_ps_restore(sc); |
1226 | 835 | ||
1227 | sc->sc_flags |= SC_OP_INVALID; | 836 | set_bit(SC_OP_INVALID, &sc->sc_flags); |
1228 | sc->ps_idle = prev_idle; | 837 | sc->ps_idle = prev_idle; |
1229 | 838 | ||
1230 | mutex_unlock(&sc->mutex); | 839 | mutex_unlock(&sc->mutex); |
@@ -1328,11 +937,11 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1328 | /* Set op-mode & TSF */ | 937 | /* Set op-mode & TSF */ |
1329 | if (iter_data.naps > 0) { | 938 | if (iter_data.naps > 0) { |
1330 | ath9k_hw_set_tsfadjust(ah, 1); | 939 | ath9k_hw_set_tsfadjust(ah, 1); |
1331 | sc->sc_flags |= SC_OP_TSF_RESET; | 940 | set_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
1332 | ah->opmode = NL80211_IFTYPE_AP; | 941 | ah->opmode = NL80211_IFTYPE_AP; |
1333 | } else { | 942 | } else { |
1334 | ath9k_hw_set_tsfadjust(ah, 0); | 943 | ath9k_hw_set_tsfadjust(ah, 0); |
1335 | sc->sc_flags &= ~SC_OP_TSF_RESET; | 944 | clear_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
1336 | 945 | ||
1337 | if (iter_data.nmeshes) | 946 | if (iter_data.nmeshes) |
1338 | ah->opmode = NL80211_IFTYPE_MESH_POINT; | 947 | ah->opmode = NL80211_IFTYPE_MESH_POINT; |
@@ -1363,12 +972,12 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1363 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 972 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
1364 | 973 | ||
1365 | if (!common->disable_ani) { | 974 | if (!common->disable_ani) { |
1366 | sc->sc_flags |= SC_OP_ANI_RUN; | 975 | set_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
1367 | ath_start_ani(common); | 976 | ath_start_ani(common); |
1368 | } | 977 | } |
1369 | 978 | ||
1370 | } else { | 979 | } else { |
1371 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 980 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
1372 | del_timer_sync(&common->ani.timer); | 981 | del_timer_sync(&common->ani.timer); |
1373 | } | 982 | } |
1374 | } | 983 | } |
@@ -1389,25 +998,6 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1389 | } | 998 | } |
1390 | } | 999 | } |
1391 | 1000 | ||
1392 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) | ||
1393 | { | ||
1394 | if (!AR_SREV_9300(sc->sc_ah)) | ||
1395 | return; | ||
1396 | |||
1397 | if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) | ||
1398 | return; | ||
1399 | |||
1400 | mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies | ||
1401 | (nbeacon * sc->cur_beacon_conf.beacon_interval)); | ||
1402 | } | ||
1403 | |||
1404 | void ath_rx_poll(unsigned long data) | ||
1405 | { | ||
1406 | struct ath_softc *sc = (struct ath_softc *)data; | ||
1407 | |||
1408 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
1409 | } | ||
1410 | |||
1411 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1001 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
1412 | struct ieee80211_vif *vif) | 1002 | struct ieee80211_vif *vif) |
1413 | { | 1003 | { |
@@ -1627,11 +1217,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1627 | if (ah->curchan) | 1217 | if (ah->curchan) |
1628 | old_pos = ah->curchan - &ah->channels[0]; | 1218 | old_pos = ah->curchan - &ah->channels[0]; |
1629 | 1219 | ||
1630 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | ||
1631 | sc->sc_flags |= SC_OP_OFFCHANNEL; | ||
1632 | else | ||
1633 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | ||
1634 | |||
1635 | ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n", | 1220 | ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n", |
1636 | curchan->center_freq, conf->channel_type); | 1221 | curchan->center_freq, conf->channel_type); |
1637 | 1222 | ||
@@ -1911,16 +1496,16 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1911 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1496 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1912 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1497 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1913 | struct ath_vif *avp = (void *)vif->drv_priv; | 1498 | struct ath_vif *avp = (void *)vif->drv_priv; |
1914 | 1499 | unsigned long flags; | |
1915 | /* | 1500 | /* |
1916 | * Skip iteration if primary station vif's bss info | 1501 | * Skip iteration if primary station vif's bss info |
1917 | * was not changed | 1502 | * was not changed |
1918 | */ | 1503 | */ |
1919 | if (sc->sc_flags & SC_OP_PRIM_STA_VIF) | 1504 | if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) |
1920 | return; | 1505 | return; |
1921 | 1506 | ||
1922 | if (bss_conf->assoc) { | 1507 | if (bss_conf->assoc) { |
1923 | sc->sc_flags |= SC_OP_PRIM_STA_VIF; | 1508 | set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); |
1924 | avp->primary_sta_vif = true; | 1509 | avp->primary_sta_vif = true; |
1925 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 1510 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1926 | common->curaid = bss_conf->aid; | 1511 | common->curaid = bss_conf->aid; |
@@ -1933,7 +1518,10 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1933 | * on the receipt of the first Beacon frame (i.e., | 1518 | * on the receipt of the first Beacon frame (i.e., |
1934 | * after time sync with the AP). | 1519 | * after time sync with the AP). |
1935 | */ | 1520 | */ |
1521 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1936 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 1522 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
1523 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1524 | |||
1937 | /* Reset rssi stats */ | 1525 | /* Reset rssi stats */ |
1938 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | 1526 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1939 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 1527 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
@@ -1941,7 +1529,7 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1941 | ath_start_rx_poll(sc, 3); | 1529 | ath_start_rx_poll(sc, 3); |
1942 | 1530 | ||
1943 | if (!common->disable_ani) { | 1531 | if (!common->disable_ani) { |
1944 | sc->sc_flags |= SC_OP_ANI_RUN; | 1532 | set_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
1945 | ath_start_ani(common); | 1533 | ath_start_ani(common); |
1946 | } | 1534 | } |
1947 | 1535 | ||
@@ -1961,7 +1549,8 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
1961 | if (avp->primary_sta_vif && !bss_conf->assoc) { | 1549 | if (avp->primary_sta_vif && !bss_conf->assoc) { |
1962 | ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n", | 1550 | ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n", |
1963 | common->curaid, common->curbssid); | 1551 | common->curaid, common->curbssid); |
1964 | sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); | 1552 | clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); |
1553 | clear_bit(SC_OP_BEACONS, &sc->sc_flags); | ||
1965 | avp->primary_sta_vif = false; | 1554 | avp->primary_sta_vif = false; |
1966 | memset(common->curbssid, 0, ETH_ALEN); | 1555 | memset(common->curbssid, 0, ETH_ALEN); |
1967 | common->curaid = 0; | 1556 | common->curaid = 0; |
@@ -1974,10 +1563,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
1974 | * None of station vifs are associated. | 1563 | * None of station vifs are associated. |
1975 | * Clear bssid & aid | 1564 | * Clear bssid & aid |
1976 | */ | 1565 | */ |
1977 | if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { | 1566 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { |
1978 | ath9k_hw_write_associd(sc->sc_ah); | 1567 | ath9k_hw_write_associd(sc->sc_ah); |
1979 | /* Stop ANI */ | 1568 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
1980 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1981 | del_timer_sync(&common->ani.timer); | 1569 | del_timer_sync(&common->ani.timer); |
1982 | del_timer_sync(&sc->rx_poll_timer); | 1570 | del_timer_sync(&sc->rx_poll_timer); |
1983 | memset(&sc->caldata, 0, sizeof(sc->caldata)); | 1571 | memset(&sc->caldata, 0, sizeof(sc->caldata)); |
@@ -2015,12 +1603,12 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2015 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 1603 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
2016 | 1604 | ||
2017 | if (!common->disable_ani) { | 1605 | if (!common->disable_ani) { |
2018 | sc->sc_flags |= SC_OP_ANI_RUN; | 1606 | set_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
2019 | ath_start_ani(common); | 1607 | ath_start_ani(common); |
2020 | } | 1608 | } |
2021 | 1609 | ||
2022 | } else { | 1610 | } else { |
2023 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 1611 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); |
2024 | del_timer_sync(&common->ani.timer); | 1612 | del_timer_sync(&common->ani.timer); |
2025 | del_timer_sync(&sc->rx_poll_timer); | 1613 | del_timer_sync(&sc->rx_poll_timer); |
2026 | } | 1614 | } |
@@ -2032,7 +1620,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2032 | */ | 1620 | */ |
2033 | if ((changed & BSS_CHANGED_BEACON_INT) && | 1621 | if ((changed & BSS_CHANGED_BEACON_INT) && |
2034 | (vif->type == NL80211_IFTYPE_AP)) | 1622 | (vif->type == NL80211_IFTYPE_AP)) |
2035 | sc->sc_flags |= SC_OP_TSF_RESET; | 1623 | set_bit(SC_OP_TSF_RESET, &sc->sc_flags); |
2036 | 1624 | ||
2037 | /* Configure beaconing (AP, IBSS, MESH) */ | 1625 | /* Configure beaconing (AP, IBSS, MESH) */ |
2038 | if (ath9k_uses_beacons(vif->type) && | 1626 | if (ath9k_uses_beacons(vif->type) && |
@@ -2224,7 +1812,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2224 | return; | 1812 | return; |
2225 | } | 1813 | } |
2226 | 1814 | ||
2227 | if (sc->sc_flags & SC_OP_INVALID) { | 1815 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { |
2228 | ath_dbg(common, ANY, "Device not present\n"); | 1816 | ath_dbg(common, ANY, "Device not present\n"); |
2229 | mutex_unlock(&sc->mutex); | 1817 | mutex_unlock(&sc->mutex); |
2230 | return; | 1818 | return; |
@@ -2389,6 +1977,134 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
2389 | return 0; | 1977 | return 0; |
2390 | } | 1978 | } |
2391 | 1979 | ||
1980 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
1981 | |||
1982 | /* Ethtool support for get-stats */ | ||
1983 | |||
1984 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" | ||
1985 | static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1986 | "tx_pkts_nic", | ||
1987 | "tx_bytes_nic", | ||
1988 | "rx_pkts_nic", | ||
1989 | "rx_bytes_nic", | ||
1990 | AMKSTR(d_tx_pkts), | ||
1991 | AMKSTR(d_tx_bytes), | ||
1992 | AMKSTR(d_tx_mpdus_queued), | ||
1993 | AMKSTR(d_tx_mpdus_completed), | ||
1994 | AMKSTR(d_tx_mpdu_xretries), | ||
1995 | AMKSTR(d_tx_aggregates), | ||
1996 | AMKSTR(d_tx_ampdus_queued_hw), | ||
1997 | AMKSTR(d_tx_ampdus_queued_sw), | ||
1998 | AMKSTR(d_tx_ampdus_completed), | ||
1999 | AMKSTR(d_tx_ampdu_retries), | ||
2000 | AMKSTR(d_tx_ampdu_xretries), | ||
2001 | AMKSTR(d_tx_fifo_underrun), | ||
2002 | AMKSTR(d_tx_op_exceeded), | ||
2003 | AMKSTR(d_tx_timer_expiry), | ||
2004 | AMKSTR(d_tx_desc_cfg_err), | ||
2005 | AMKSTR(d_tx_data_underrun), | ||
2006 | AMKSTR(d_tx_delim_underrun), | ||
2007 | |||
2008 | "d_rx_decrypt_crc_err", | ||
2009 | "d_rx_phy_err", | ||
2010 | "d_rx_mic_err", | ||
2011 | "d_rx_pre_delim_crc_err", | ||
2012 | "d_rx_post_delim_crc_err", | ||
2013 | "d_rx_decrypt_busy_err", | ||
2014 | |||
2015 | "d_rx_phyerr_radar", | ||
2016 | "d_rx_phyerr_ofdm_timing", | ||
2017 | "d_rx_phyerr_cck_timing", | ||
2018 | |||
2019 | }; | ||
2020 | #define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) | ||
2021 | |||
2022 | static void ath9k_get_et_strings(struct ieee80211_hw *hw, | ||
2023 | struct ieee80211_vif *vif, | ||
2024 | u32 sset, u8 *data) | ||
2025 | { | ||
2026 | if (sset == ETH_SS_STATS) | ||
2027 | memcpy(data, *ath9k_gstrings_stats, | ||
2028 | sizeof(ath9k_gstrings_stats)); | ||
2029 | } | ||
2030 | |||
2031 | static int ath9k_get_et_sset_count(struct ieee80211_hw *hw, | ||
2032 | struct ieee80211_vif *vif, int sset) | ||
2033 | { | ||
2034 | if (sset == ETH_SS_STATS) | ||
2035 | return ATH9K_SSTATS_LEN; | ||
2036 | return 0; | ||
2037 | } | ||
2038 | |||
2039 | #define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum) | ||
2040 | #define AWDATA(elem) \ | ||
2041 | do { \ | ||
2042 | data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem; \ | ||
2043 | data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem; \ | ||
2044 | data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem; \ | ||
2045 | data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem; \ | ||
2046 | } while (0) | ||
2047 | |||
2048 | #define AWDATA_RX(elem) \ | ||
2049 | do { \ | ||
2050 | data[i++] = sc->debug.stats.rxstats.elem; \ | ||
2051 | } while (0) | ||
2052 | |||
2053 | static void ath9k_get_et_stats(struct ieee80211_hw *hw, | ||
2054 | struct ieee80211_vif *vif, | ||
2055 | struct ethtool_stats *stats, u64 *data) | ||
2056 | { | ||
2057 | struct ath_softc *sc = hw->priv; | ||
2058 | int i = 0; | ||
2059 | |||
2060 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_pkts_all + | ||
2061 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_pkts_all + | ||
2062 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_pkts_all + | ||
2063 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_pkts_all); | ||
2064 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_bytes_all + | ||
2065 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_bytes_all + | ||
2066 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_bytes_all + | ||
2067 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_bytes_all); | ||
2068 | AWDATA_RX(rx_pkts_all); | ||
2069 | AWDATA_RX(rx_bytes_all); | ||
2070 | |||
2071 | AWDATA(tx_pkts_all); | ||
2072 | AWDATA(tx_bytes_all); | ||
2073 | AWDATA(queued); | ||
2074 | AWDATA(completed); | ||
2075 | AWDATA(xretries); | ||
2076 | AWDATA(a_aggr); | ||
2077 | AWDATA(a_queued_hw); | ||
2078 | AWDATA(a_queued_sw); | ||
2079 | AWDATA(a_completed); | ||
2080 | AWDATA(a_retries); | ||
2081 | AWDATA(a_xretries); | ||
2082 | AWDATA(fifo_underrun); | ||
2083 | AWDATA(xtxop); | ||
2084 | AWDATA(timer_exp); | ||
2085 | AWDATA(desc_cfg_err); | ||
2086 | AWDATA(data_underrun); | ||
2087 | AWDATA(delim_underrun); | ||
2088 | |||
2089 | AWDATA_RX(decrypt_crc_err); | ||
2090 | AWDATA_RX(phy_err); | ||
2091 | AWDATA_RX(mic_err); | ||
2092 | AWDATA_RX(pre_delim_crc_err); | ||
2093 | AWDATA_RX(post_delim_crc_err); | ||
2094 | AWDATA_RX(decrypt_busy_err); | ||
2095 | |||
2096 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); | ||
2097 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); | ||
2098 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); | ||
2099 | |||
2100 | WARN_ON(i != ATH9K_SSTATS_LEN); | ||
2101 | } | ||
2102 | |||
2103 | /* End of ethtool get-stats functions */ | ||
2104 | |||
2105 | #endif | ||
2106 | |||
2107 | |||
2392 | struct ieee80211_ops ath9k_ops = { | 2108 | struct ieee80211_ops ath9k_ops = { |
2393 | .tx = ath9k_tx, | 2109 | .tx = ath9k_tx, |
2394 | .start = ath9k_start, | 2110 | .start = ath9k_start, |
@@ -2417,4 +2133,10 @@ struct ieee80211_ops ath9k_ops = { | |||
2417 | .get_stats = ath9k_get_stats, | 2133 | .get_stats = ath9k_get_stats, |
2418 | .set_antenna = ath9k_set_antenna, | 2134 | .set_antenna = ath9k_set_antenna, |
2419 | .get_antenna = ath9k_get_antenna, | 2135 | .get_antenna = ath9k_get_antenna, |
2136 | |||
2137 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
2138 | .get_et_sset_count = ath9k_get_et_sset_count, | ||
2139 | .get_et_stats = ath9k_get_et_stats, | ||
2140 | .get_et_strings = ath9k_get_et_strings, | ||
2141 | #endif | ||
2420 | }; | 2142 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 29fe52d69973..49137f477b05 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -116,42 +116,58 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
116 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 116 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
117 | struct ath_btcoex *btcoex = &sc->btcoex; | 117 | struct ath_btcoex *btcoex = &sc->btcoex; |
118 | struct ath_mci_profile *mci = &btcoex->mci; | 118 | struct ath_mci_profile *mci = &btcoex->mci; |
119 | struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; | ||
119 | struct ath_mci_profile_info *info; | 120 | struct ath_mci_profile_info *info; |
120 | u32 num_profile = NUM_PROF(mci); | 121 | u32 num_profile = NUM_PROF(mci); |
121 | 122 | ||
123 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) | ||
124 | goto skip_tuning; | ||
125 | |||
122 | if (num_profile == 1) { | 126 | if (num_profile == 1) { |
123 | info = list_first_entry(&mci->info, | 127 | info = list_first_entry(&mci->info, |
124 | struct ath_mci_profile_info, | 128 | struct ath_mci_profile_info, |
125 | list); | 129 | list); |
126 | if (mci->num_sco && info->T == 12) { | 130 | if (mci->num_sco) { |
127 | mci->aggr_limit = 8; | 131 | if (info->T == 12) |
132 | mci->aggr_limit = 8; | ||
133 | else if (info->T == 6) { | ||
134 | mci->aggr_limit = 6; | ||
135 | btcoex->duty_cycle = 30; | ||
136 | } | ||
128 | ath_dbg(common, MCI, | 137 | ath_dbg(common, MCI, |
129 | "Single SCO, aggregation limit 2 ms\n"); | 138 | "Single SCO, aggregation limit %d 1/4 ms\n", |
130 | } else if ((info->type == MCI_GPM_COEX_PROFILE_BNEP) && | 139 | mci->aggr_limit); |
131 | !info->master) { | 140 | } else if (mci->num_pan || mci->num_other_acl) { |
132 | btcoex->btcoex_period = 60; | 141 | /* |
142 | * For single PAN/FTP profile, allocate 35% for BT | ||
143 | * to improve WLAN throughput. | ||
144 | */ | ||
145 | btcoex->duty_cycle = 35; | ||
146 | btcoex->btcoex_period = 53; | ||
133 | ath_dbg(common, MCI, | 147 | ath_dbg(common, MCI, |
134 | "Single slave PAN/FTP, bt period 60 ms\n"); | 148 | "Single PAN/FTP bt period %d ms dutycycle %d\n", |
135 | } else if ((info->type == MCI_GPM_COEX_PROFILE_HID) && | 149 | btcoex->duty_cycle, btcoex->btcoex_period); |
136 | (info->T > 0 && info->T < 50) && | 150 | } else if (mci->num_hid) { |
137 | (info->A > 1 || info->W > 1)) { | ||
138 | btcoex->duty_cycle = 30; | 151 | btcoex->duty_cycle = 30; |
139 | mci->aggr_limit = 8; | 152 | mci->aggr_limit = 6; |
140 | ath_dbg(common, MCI, | 153 | ath_dbg(common, MCI, |
141 | "Multiple attempt/timeout single HID " | 154 | "Multiple attempt/timeout single HID " |
142 | "aggregation limit 2 ms dutycycle 30%%\n"); | 155 | "aggregation limit 1.5 ms dutycycle 30%%\n"); |
143 | } | 156 | } |
144 | } else if ((num_profile == 2) && (mci->num_hid == 2)) { | 157 | } else if (num_profile == 2) { |
145 | btcoex->duty_cycle = 30; | 158 | if (mci->num_hid == 2) |
146 | mci->aggr_limit = 8; | 159 | btcoex->duty_cycle = 30; |
147 | ath_dbg(common, MCI, | ||
148 | "Two HIDs aggregation limit 2 ms dutycycle 30%%\n"); | ||
149 | } else if (num_profile > 3) { | ||
150 | mci->aggr_limit = 6; | 160 | mci->aggr_limit = 6; |
151 | ath_dbg(common, MCI, | 161 | ath_dbg(common, MCI, |
152 | "Three or more profiles aggregation limit 1.5 ms\n"); | 162 | "Two BT profiles aggr limit 1.5 ms dutycycle %d%%\n", |
163 | btcoex->duty_cycle); | ||
164 | } else if (num_profile >= 3) { | ||
165 | mci->aggr_limit = 4; | ||
166 | ath_dbg(common, MCI, | ||
167 | "Three or more profiles aggregation limit 1 ms\n"); | ||
153 | } | 168 | } |
154 | 169 | ||
170 | skip_tuning: | ||
155 | if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) { | 171 | if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) { |
156 | if (IS_CHAN_HT(sc->sc_ah->curchan)) | 172 | if (IS_CHAN_HT(sc->sc_ah->curchan)) |
157 | ath_mci_adjust_aggr_limit(btcoex); | 173 | ath_mci_adjust_aggr_limit(btcoex); |
@@ -538,3 +554,14 @@ void ath_mci_intr(struct ath_softc *sc) | |||
538 | mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | | 554 | mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | |
539 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); | 555 | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); |
540 | } | 556 | } |
557 | |||
558 | void ath_mci_enable(struct ath_softc *sc) | ||
559 | { | ||
560 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
561 | |||
562 | if (!common->btcoex_enabled) | ||
563 | return; | ||
564 | |||
565 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | ||
566 | sc->sc_ah->imask |= ATH9K_INT_MCI; | ||
567 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h index c841444f53c2..fc14eea034eb 100644 --- a/drivers/net/wireless/ath/ath9k/mci.h +++ b/drivers/net/wireless/ath/ath9k/mci.h | |||
@@ -130,4 +130,13 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci); | |||
130 | int ath_mci_setup(struct ath_softc *sc); | 130 | int ath_mci_setup(struct ath_softc *sc); |
131 | void ath_mci_cleanup(struct ath_softc *sc); | 131 | void ath_mci_cleanup(struct ath_softc *sc); |
132 | void ath_mci_intr(struct ath_softc *sc); | 132 | void ath_mci_intr(struct ath_softc *sc); |
133 | #endif | 133 | |
134 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
135 | void ath_mci_enable(struct ath_softc *sc); | ||
136 | #else | ||
137 | static inline void ath_mci_enable(struct ath_softc *sc) | ||
138 | { | ||
139 | } | ||
140 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | ||
141 | |||
142 | #endif /* MCI_H*/ | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index a856b51255f4..aa0e83ac51f4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -115,6 +115,9 @@ static void ath_pci_aspm_init(struct ath_common *common) | |||
115 | int pos; | 115 | int pos; |
116 | u8 aspm; | 116 | u8 aspm; |
117 | 117 | ||
118 | if (!ah->is_pciexpress) | ||
119 | return; | ||
120 | |||
118 | pos = pci_pcie_cap(pdev); | 121 | pos = pci_pcie_cap(pdev); |
119 | if (!pos) | 122 | if (!pos) |
120 | return; | 123 | return; |
@@ -138,6 +141,7 @@ static void ath_pci_aspm_init(struct ath_common *common) | |||
138 | aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); | 141 | aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); |
139 | pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); | 142 | pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); |
140 | 143 | ||
144 | ath_info(common, "Disabling ASPM since BTCOEX is enabled\n"); | ||
141 | return; | 145 | return; |
142 | } | 146 | } |
143 | 147 | ||
@@ -147,6 +151,7 @@ static void ath_pci_aspm_init(struct ath_common *common) | |||
147 | ah->aspm_enabled = true; | 151 | ah->aspm_enabled = true; |
148 | /* Initialize PCIe PM and SERDES registers. */ | 152 | /* Initialize PCIe PM and SERDES registers. */ |
149 | ath9k_hw_configpcipowersave(ah, false); | 153 | ath9k_hw_configpcipowersave(ah, false); |
154 | ath_info(common, "ASPM enabled: 0x%x\n", aspm); | ||
150 | } | 155 | } |
151 | } | 156 | } |
152 | 157 | ||
@@ -246,7 +251,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
246 | sc->mem = mem; | 251 | sc->mem = mem; |
247 | 252 | ||
248 | /* Will be cleared in ath9k_start() */ | 253 | /* Will be cleared in ath9k_start() */ |
249 | sc->sc_flags |= SC_OP_INVALID; | 254 | set_bit(SC_OP_INVALID, &sc->sc_flags); |
250 | 255 | ||
251 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 256 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
252 | if (ret) { | 257 | if (ret) { |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index e1fcc68124dc..fbdcc80437fe 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -20,43 +20,6 @@ | |||
20 | 20 | ||
21 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 21 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
22 | 22 | ||
23 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | ||
24 | int mindelta, int main_rssi_avg, | ||
25 | int alt_rssi_avg, int pkt_count) | ||
26 | { | ||
27 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
28 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | ||
29 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
30 | } | ||
31 | |||
32 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | ||
33 | int curr_main_set, int curr_alt_set, | ||
34 | int alt_rssi_avg, int main_rssi_avg) | ||
35 | { | ||
36 | bool result = false; | ||
37 | switch (div_group) { | ||
38 | case 0: | ||
39 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
40 | result = true; | ||
41 | break; | ||
42 | case 1: | ||
43 | case 2: | ||
44 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | ||
45 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | ||
46 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | ||
47 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | ||
48 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | ||
49 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | ||
50 | (alt_rssi_avg >= 4)) | ||
51 | result = true; | ||
52 | else | ||
53 | result = false; | ||
54 | break; | ||
55 | } | ||
56 | |||
57 | return result; | ||
58 | } | ||
59 | |||
60 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 23 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
61 | { | 24 | { |
62 | return sc->ps_enabled && | 25 | return sc->ps_enabled && |
@@ -303,7 +266,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
303 | 266 | ||
304 | ath_opmode_init(sc); | 267 | ath_opmode_init(sc); |
305 | 268 | ||
306 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); | 269 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
307 | 270 | ||
308 | spin_unlock_bh(&sc->rx.rxbuflock); | 271 | spin_unlock_bh(&sc->rx.rxbuflock); |
309 | } | 272 | } |
@@ -322,8 +285,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
322 | int error = 0; | 285 | int error = 0; |
323 | 286 | ||
324 | spin_lock_init(&sc->sc_pcu_lock); | 287 | spin_lock_init(&sc->sc_pcu_lock); |
325 | sc->sc_flags &= ~SC_OP_RXFLUSH; | ||
326 | spin_lock_init(&sc->rx.rxbuflock); | 288 | spin_lock_init(&sc->rx.rxbuflock); |
289 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
327 | 290 | ||
328 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | 291 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + |
329 | sc->sc_ah->caps.rx_status_len; | 292 | sc->sc_ah->caps.rx_status_len; |
@@ -500,7 +463,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
500 | 463 | ||
501 | start_recv: | 464 | start_recv: |
502 | ath_opmode_init(sc); | 465 | ath_opmode_init(sc); |
503 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); | 466 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
504 | 467 | ||
505 | spin_unlock_bh(&sc->rx.rxbuflock); | 468 | spin_unlock_bh(&sc->rx.rxbuflock); |
506 | 469 | ||
@@ -535,11 +498,11 @@ bool ath_stoprecv(struct ath_softc *sc) | |||
535 | 498 | ||
536 | void ath_flushrecv(struct ath_softc *sc) | 499 | void ath_flushrecv(struct ath_softc *sc) |
537 | { | 500 | { |
538 | sc->sc_flags |= SC_OP_RXFLUSH; | 501 | set_bit(SC_OP_RXFLUSH, &sc->sc_flags); |
539 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 502 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
540 | ath_rx_tasklet(sc, 1, true); | 503 | ath_rx_tasklet(sc, 1, true); |
541 | ath_rx_tasklet(sc, 1, false); | 504 | ath_rx_tasklet(sc, 1, false); |
542 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 505 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); |
543 | } | 506 | } |
544 | 507 | ||
545 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | 508 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) |
@@ -624,13 +587,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) | |||
624 | 587 | ||
625 | /* Process Beacon and CAB receive in PS state */ | 588 | /* Process Beacon and CAB receive in PS state */ |
626 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) | 589 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) |
627 | && mybeacon) | 590 | && mybeacon) { |
628 | ath_rx_ps_beacon(sc, skb); | 591 | ath_rx_ps_beacon(sc, skb); |
629 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && | 592 | } else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && |
630 | (ieee80211_is_data(hdr->frame_control) || | 593 | (ieee80211_is_data(hdr->frame_control) || |
631 | ieee80211_is_action(hdr->frame_control)) && | 594 | ieee80211_is_action(hdr->frame_control)) && |
632 | is_multicast_ether_addr(hdr->addr1) && | 595 | is_multicast_ether_addr(hdr->addr1) && |
633 | !ieee80211_has_moredata(hdr->frame_control)) { | 596 | !ieee80211_has_moredata(hdr->frame_control)) { |
634 | /* | 597 | /* |
635 | * No more broadcast/multicast frames to be received at this | 598 | * No more broadcast/multicast frames to be received at this |
636 | * point. | 599 | * point. |
@@ -1067,709 +1030,6 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1067 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1030 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1068 | } | 1031 | } |
1069 | 1032 | ||
1070 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
1071 | struct ath_hw_antcomb_conf ant_conf, | ||
1072 | int main_rssi_avg) | ||
1073 | { | ||
1074 | antcomb->quick_scan_cnt = 0; | ||
1075 | |||
1076 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1077 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1078 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1079 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1080 | |||
1081 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
1082 | case 0x10: /* LNA2 A-B */ | ||
1083 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1084 | antcomb->first_quick_scan_conf = | ||
1085 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1086 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1087 | break; | ||
1088 | case 0x20: /* LNA1 A-B */ | ||
1089 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1090 | antcomb->first_quick_scan_conf = | ||
1091 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1092 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1093 | break; | ||
1094 | case 0x21: /* LNA1 LNA2 */ | ||
1095 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1096 | antcomb->first_quick_scan_conf = | ||
1097 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1098 | antcomb->second_quick_scan_conf = | ||
1099 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1100 | break; | ||
1101 | case 0x12: /* LNA2 LNA1 */ | ||
1102 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1103 | antcomb->first_quick_scan_conf = | ||
1104 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1105 | antcomb->second_quick_scan_conf = | ||
1106 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1107 | break; | ||
1108 | case 0x13: /* LNA2 A+B */ | ||
1109 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1110 | antcomb->first_quick_scan_conf = | ||
1111 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1112 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1113 | break; | ||
1114 | case 0x23: /* LNA1 A+B */ | ||
1115 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1116 | antcomb->first_quick_scan_conf = | ||
1117 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1118 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1119 | break; | ||
1120 | default: | ||
1121 | break; | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
1126 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
1127 | int main_rssi_avg, int alt_rssi_avg, | ||
1128 | int alt_ratio) | ||
1129 | { | ||
1130 | /* alt_good */ | ||
1131 | switch (antcomb->quick_scan_cnt) { | ||
1132 | case 0: | ||
1133 | /* set alt to main, and alt to first conf */ | ||
1134 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1135 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
1136 | break; | ||
1137 | case 1: | ||
1138 | /* set alt to main, and alt to first conf */ | ||
1139 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1140 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
1141 | antcomb->rssi_first = main_rssi_avg; | ||
1142 | antcomb->rssi_second = alt_rssi_avg; | ||
1143 | |||
1144 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1145 | /* main is LNA1 */ | ||
1146 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1147 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1148 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1149 | main_rssi_avg, alt_rssi_avg, | ||
1150 | antcomb->total_pkt_count)) | ||
1151 | antcomb->first_ratio = true; | ||
1152 | else | ||
1153 | antcomb->first_ratio = false; | ||
1154 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1155 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1156 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1157 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1158 | main_rssi_avg, alt_rssi_avg, | ||
1159 | antcomb->total_pkt_count)) | ||
1160 | antcomb->first_ratio = true; | ||
1161 | else | ||
1162 | antcomb->first_ratio = false; | ||
1163 | } else { | ||
1164 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1165 | (alt_rssi_avg > main_rssi_avg + | ||
1166 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1167 | (alt_rssi_avg > main_rssi_avg)) && | ||
1168 | (antcomb->total_pkt_count > 50)) | ||
1169 | antcomb->first_ratio = true; | ||
1170 | else | ||
1171 | antcomb->first_ratio = false; | ||
1172 | } | ||
1173 | break; | ||
1174 | case 2: | ||
1175 | antcomb->alt_good = false; | ||
1176 | antcomb->scan_not_start = false; | ||
1177 | antcomb->scan = false; | ||
1178 | antcomb->rssi_first = main_rssi_avg; | ||
1179 | antcomb->rssi_third = alt_rssi_avg; | ||
1180 | |||
1181 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1182 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1183 | else if (antcomb->second_quick_scan_conf == | ||
1184 | ATH_ANT_DIV_COMB_LNA2) | ||
1185 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1186 | else if (antcomb->second_quick_scan_conf == | ||
1187 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
1188 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1189 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1190 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1191 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1192 | } | ||
1193 | |||
1194 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
1195 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
1196 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1197 | else | ||
1198 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1199 | |||
1200 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1201 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1202 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1203 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1204 | main_rssi_avg, alt_rssi_avg, | ||
1205 | antcomb->total_pkt_count)) | ||
1206 | antcomb->second_ratio = true; | ||
1207 | else | ||
1208 | antcomb->second_ratio = false; | ||
1209 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1210 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1211 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1212 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1213 | main_rssi_avg, alt_rssi_avg, | ||
1214 | antcomb->total_pkt_count)) | ||
1215 | antcomb->second_ratio = true; | ||
1216 | else | ||
1217 | antcomb->second_ratio = false; | ||
1218 | } else { | ||
1219 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1220 | (alt_rssi_avg > main_rssi_avg + | ||
1221 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1222 | (alt_rssi_avg > main_rssi_avg)) && | ||
1223 | (antcomb->total_pkt_count > 50)) | ||
1224 | antcomb->second_ratio = true; | ||
1225 | else | ||
1226 | antcomb->second_ratio = false; | ||
1227 | } | ||
1228 | |||
1229 | /* set alt to the conf with maximun ratio */ | ||
1230 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
1231 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
1232 | /* first alt*/ | ||
1233 | if ((antcomb->first_quick_scan_conf == | ||
1234 | ATH_ANT_DIV_COMB_LNA1) || | ||
1235 | (antcomb->first_quick_scan_conf == | ||
1236 | ATH_ANT_DIV_COMB_LNA2)) | ||
1237 | /* Set alt LNA1 or LNA2*/ | ||
1238 | if (div_ant_conf->main_lna_conf == | ||
1239 | ATH_ANT_DIV_COMB_LNA2) | ||
1240 | div_ant_conf->alt_lna_conf = | ||
1241 | ATH_ANT_DIV_COMB_LNA1; | ||
1242 | else | ||
1243 | div_ant_conf->alt_lna_conf = | ||
1244 | ATH_ANT_DIV_COMB_LNA2; | ||
1245 | else | ||
1246 | /* Set alt to A+B or A-B */ | ||
1247 | div_ant_conf->alt_lna_conf = | ||
1248 | antcomb->first_quick_scan_conf; | ||
1249 | } else if ((antcomb->second_quick_scan_conf == | ||
1250 | ATH_ANT_DIV_COMB_LNA1) || | ||
1251 | (antcomb->second_quick_scan_conf == | ||
1252 | ATH_ANT_DIV_COMB_LNA2)) { | ||
1253 | /* Set alt LNA1 or LNA2 */ | ||
1254 | if (div_ant_conf->main_lna_conf == | ||
1255 | ATH_ANT_DIV_COMB_LNA2) | ||
1256 | div_ant_conf->alt_lna_conf = | ||
1257 | ATH_ANT_DIV_COMB_LNA1; | ||
1258 | else | ||
1259 | div_ant_conf->alt_lna_conf = | ||
1260 | ATH_ANT_DIV_COMB_LNA2; | ||
1261 | } else { | ||
1262 | /* Set alt to A+B or A-B */ | ||
1263 | div_ant_conf->alt_lna_conf = | ||
1264 | antcomb->second_quick_scan_conf; | ||
1265 | } | ||
1266 | } else if (antcomb->first_ratio) { | ||
1267 | /* first alt */ | ||
1268 | if ((antcomb->first_quick_scan_conf == | ||
1269 | ATH_ANT_DIV_COMB_LNA1) || | ||
1270 | (antcomb->first_quick_scan_conf == | ||
1271 | ATH_ANT_DIV_COMB_LNA2)) | ||
1272 | /* Set alt LNA1 or LNA2 */ | ||
1273 | if (div_ant_conf->main_lna_conf == | ||
1274 | ATH_ANT_DIV_COMB_LNA2) | ||
1275 | div_ant_conf->alt_lna_conf = | ||
1276 | ATH_ANT_DIV_COMB_LNA1; | ||
1277 | else | ||
1278 | div_ant_conf->alt_lna_conf = | ||
1279 | ATH_ANT_DIV_COMB_LNA2; | ||
1280 | else | ||
1281 | /* Set alt to A+B or A-B */ | ||
1282 | div_ant_conf->alt_lna_conf = | ||
1283 | antcomb->first_quick_scan_conf; | ||
1284 | } else if (antcomb->second_ratio) { | ||
1285 | /* second alt */ | ||
1286 | if ((antcomb->second_quick_scan_conf == | ||
1287 | ATH_ANT_DIV_COMB_LNA1) || | ||
1288 | (antcomb->second_quick_scan_conf == | ||
1289 | ATH_ANT_DIV_COMB_LNA2)) | ||
1290 | /* Set alt LNA1 or LNA2 */ | ||
1291 | if (div_ant_conf->main_lna_conf == | ||
1292 | ATH_ANT_DIV_COMB_LNA2) | ||
1293 | div_ant_conf->alt_lna_conf = | ||
1294 | ATH_ANT_DIV_COMB_LNA1; | ||
1295 | else | ||
1296 | div_ant_conf->alt_lna_conf = | ||
1297 | ATH_ANT_DIV_COMB_LNA2; | ||
1298 | else | ||
1299 | /* Set alt to A+B or A-B */ | ||
1300 | div_ant_conf->alt_lna_conf = | ||
1301 | antcomb->second_quick_scan_conf; | ||
1302 | } else { | ||
1303 | /* main is largest */ | ||
1304 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
1305 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
1306 | /* Set alt LNA1 or LNA2 */ | ||
1307 | if (div_ant_conf->main_lna_conf == | ||
1308 | ATH_ANT_DIV_COMB_LNA2) | ||
1309 | div_ant_conf->alt_lna_conf = | ||
1310 | ATH_ANT_DIV_COMB_LNA1; | ||
1311 | else | ||
1312 | div_ant_conf->alt_lna_conf = | ||
1313 | ATH_ANT_DIV_COMB_LNA2; | ||
1314 | else | ||
1315 | /* Set alt to A+B or A-B */ | ||
1316 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
1317 | } | ||
1318 | break; | ||
1319 | default: | ||
1320 | break; | ||
1321 | } | ||
1322 | } | ||
1323 | |||
1324 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | ||
1325 | struct ath_ant_comb *antcomb, int alt_ratio) | ||
1326 | { | ||
1327 | if (ant_conf->div_group == 0) { | ||
1328 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
1329 | switch ((ant_conf->main_lna_conf << 4) | | ||
1330 | ant_conf->alt_lna_conf) { | ||
1331 | case 0x01: /* A-B LNA2 */ | ||
1332 | ant_conf->fast_div_bias = 0x3b; | ||
1333 | break; | ||
1334 | case 0x02: /* A-B LNA1 */ | ||
1335 | ant_conf->fast_div_bias = 0x3d; | ||
1336 | break; | ||
1337 | case 0x03: /* A-B A+B */ | ||
1338 | ant_conf->fast_div_bias = 0x1; | ||
1339 | break; | ||
1340 | case 0x10: /* LNA2 A-B */ | ||
1341 | ant_conf->fast_div_bias = 0x7; | ||
1342 | break; | ||
1343 | case 0x12: /* LNA2 LNA1 */ | ||
1344 | ant_conf->fast_div_bias = 0x2; | ||
1345 | break; | ||
1346 | case 0x13: /* LNA2 A+B */ | ||
1347 | ant_conf->fast_div_bias = 0x7; | ||
1348 | break; | ||
1349 | case 0x20: /* LNA1 A-B */ | ||
1350 | ant_conf->fast_div_bias = 0x6; | ||
1351 | break; | ||
1352 | case 0x21: /* LNA1 LNA2 */ | ||
1353 | ant_conf->fast_div_bias = 0x0; | ||
1354 | break; | ||
1355 | case 0x23: /* LNA1 A+B */ | ||
1356 | ant_conf->fast_div_bias = 0x6; | ||
1357 | break; | ||
1358 | case 0x30: /* A+B A-B */ | ||
1359 | ant_conf->fast_div_bias = 0x1; | ||
1360 | break; | ||
1361 | case 0x31: /* A+B LNA2 */ | ||
1362 | ant_conf->fast_div_bias = 0x3b; | ||
1363 | break; | ||
1364 | case 0x32: /* A+B LNA1 */ | ||
1365 | ant_conf->fast_div_bias = 0x3d; | ||
1366 | break; | ||
1367 | default: | ||
1368 | break; | ||
1369 | } | ||
1370 | } else if (ant_conf->div_group == 1) { | ||
1371 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1372 | switch ((ant_conf->main_lna_conf << 4) | | ||
1373 | ant_conf->alt_lna_conf) { | ||
1374 | case 0x01: /* A-B LNA2 */ | ||
1375 | ant_conf->fast_div_bias = 0x1; | ||
1376 | ant_conf->main_gaintb = 0; | ||
1377 | ant_conf->alt_gaintb = 0; | ||
1378 | break; | ||
1379 | case 0x02: /* A-B LNA1 */ | ||
1380 | ant_conf->fast_div_bias = 0x1; | ||
1381 | ant_conf->main_gaintb = 0; | ||
1382 | ant_conf->alt_gaintb = 0; | ||
1383 | break; | ||
1384 | case 0x03: /* A-B A+B */ | ||
1385 | ant_conf->fast_div_bias = 0x1; | ||
1386 | ant_conf->main_gaintb = 0; | ||
1387 | ant_conf->alt_gaintb = 0; | ||
1388 | break; | ||
1389 | case 0x10: /* LNA2 A-B */ | ||
1390 | if (!(antcomb->scan) && | ||
1391 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1392 | ant_conf->fast_div_bias = 0x3f; | ||
1393 | else | ||
1394 | ant_conf->fast_div_bias = 0x1; | ||
1395 | ant_conf->main_gaintb = 0; | ||
1396 | ant_conf->alt_gaintb = 0; | ||
1397 | break; | ||
1398 | case 0x12: /* LNA2 LNA1 */ | ||
1399 | ant_conf->fast_div_bias = 0x1; | ||
1400 | ant_conf->main_gaintb = 0; | ||
1401 | ant_conf->alt_gaintb = 0; | ||
1402 | break; | ||
1403 | case 0x13: /* LNA2 A+B */ | ||
1404 | if (!(antcomb->scan) && | ||
1405 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1406 | ant_conf->fast_div_bias = 0x3f; | ||
1407 | else | ||
1408 | ant_conf->fast_div_bias = 0x1; | ||
1409 | ant_conf->main_gaintb = 0; | ||
1410 | ant_conf->alt_gaintb = 0; | ||
1411 | break; | ||
1412 | case 0x20: /* LNA1 A-B */ | ||
1413 | if (!(antcomb->scan) && | ||
1414 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1415 | ant_conf->fast_div_bias = 0x3f; | ||
1416 | else | ||
1417 | ant_conf->fast_div_bias = 0x1; | ||
1418 | ant_conf->main_gaintb = 0; | ||
1419 | ant_conf->alt_gaintb = 0; | ||
1420 | break; | ||
1421 | case 0x21: /* LNA1 LNA2 */ | ||
1422 | ant_conf->fast_div_bias = 0x1; | ||
1423 | ant_conf->main_gaintb = 0; | ||
1424 | ant_conf->alt_gaintb = 0; | ||
1425 | break; | ||
1426 | case 0x23: /* LNA1 A+B */ | ||
1427 | if (!(antcomb->scan) && | ||
1428 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1429 | ant_conf->fast_div_bias = 0x3f; | ||
1430 | else | ||
1431 | ant_conf->fast_div_bias = 0x1; | ||
1432 | ant_conf->main_gaintb = 0; | ||
1433 | ant_conf->alt_gaintb = 0; | ||
1434 | break; | ||
1435 | case 0x30: /* A+B A-B */ | ||
1436 | ant_conf->fast_div_bias = 0x1; | ||
1437 | ant_conf->main_gaintb = 0; | ||
1438 | ant_conf->alt_gaintb = 0; | ||
1439 | break; | ||
1440 | case 0x31: /* A+B LNA2 */ | ||
1441 | ant_conf->fast_div_bias = 0x1; | ||
1442 | ant_conf->main_gaintb = 0; | ||
1443 | ant_conf->alt_gaintb = 0; | ||
1444 | break; | ||
1445 | case 0x32: /* A+B LNA1 */ | ||
1446 | ant_conf->fast_div_bias = 0x1; | ||
1447 | ant_conf->main_gaintb = 0; | ||
1448 | ant_conf->alt_gaintb = 0; | ||
1449 | break; | ||
1450 | default: | ||
1451 | break; | ||
1452 | } | ||
1453 | } else if (ant_conf->div_group == 2) { | ||
1454 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1455 | switch ((ant_conf->main_lna_conf << 4) | | ||
1456 | ant_conf->alt_lna_conf) { | ||
1457 | case 0x01: /* A-B LNA2 */ | ||
1458 | ant_conf->fast_div_bias = 0x1; | ||
1459 | ant_conf->main_gaintb = 0; | ||
1460 | ant_conf->alt_gaintb = 0; | ||
1461 | break; | ||
1462 | case 0x02: /* A-B LNA1 */ | ||
1463 | ant_conf->fast_div_bias = 0x1; | ||
1464 | ant_conf->main_gaintb = 0; | ||
1465 | ant_conf->alt_gaintb = 0; | ||
1466 | break; | ||
1467 | case 0x03: /* A-B A+B */ | ||
1468 | ant_conf->fast_div_bias = 0x1; | ||
1469 | ant_conf->main_gaintb = 0; | ||
1470 | ant_conf->alt_gaintb = 0; | ||
1471 | break; | ||
1472 | case 0x10: /* LNA2 A-B */ | ||
1473 | if (!(antcomb->scan) && | ||
1474 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1475 | ant_conf->fast_div_bias = 0x1; | ||
1476 | else | ||
1477 | ant_conf->fast_div_bias = 0x2; | ||
1478 | ant_conf->main_gaintb = 0; | ||
1479 | ant_conf->alt_gaintb = 0; | ||
1480 | break; | ||
1481 | case 0x12: /* LNA2 LNA1 */ | ||
1482 | ant_conf->fast_div_bias = 0x1; | ||
1483 | ant_conf->main_gaintb = 0; | ||
1484 | ant_conf->alt_gaintb = 0; | ||
1485 | break; | ||
1486 | case 0x13: /* LNA2 A+B */ | ||
1487 | if (!(antcomb->scan) && | ||
1488 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1489 | ant_conf->fast_div_bias = 0x1; | ||
1490 | else | ||
1491 | ant_conf->fast_div_bias = 0x2; | ||
1492 | ant_conf->main_gaintb = 0; | ||
1493 | ant_conf->alt_gaintb = 0; | ||
1494 | break; | ||
1495 | case 0x20: /* LNA1 A-B */ | ||
1496 | if (!(antcomb->scan) && | ||
1497 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1498 | ant_conf->fast_div_bias = 0x1; | ||
1499 | else | ||
1500 | ant_conf->fast_div_bias = 0x2; | ||
1501 | ant_conf->main_gaintb = 0; | ||
1502 | ant_conf->alt_gaintb = 0; | ||
1503 | break; | ||
1504 | case 0x21: /* LNA1 LNA2 */ | ||
1505 | ant_conf->fast_div_bias = 0x1; | ||
1506 | ant_conf->main_gaintb = 0; | ||
1507 | ant_conf->alt_gaintb = 0; | ||
1508 | break; | ||
1509 | case 0x23: /* LNA1 A+B */ | ||
1510 | if (!(antcomb->scan) && | ||
1511 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1512 | ant_conf->fast_div_bias = 0x1; | ||
1513 | else | ||
1514 | ant_conf->fast_div_bias = 0x2; | ||
1515 | ant_conf->main_gaintb = 0; | ||
1516 | ant_conf->alt_gaintb = 0; | ||
1517 | break; | ||
1518 | case 0x30: /* A+B A-B */ | ||
1519 | ant_conf->fast_div_bias = 0x1; | ||
1520 | ant_conf->main_gaintb = 0; | ||
1521 | ant_conf->alt_gaintb = 0; | ||
1522 | break; | ||
1523 | case 0x31: /* A+B LNA2 */ | ||
1524 | ant_conf->fast_div_bias = 0x1; | ||
1525 | ant_conf->main_gaintb = 0; | ||
1526 | ant_conf->alt_gaintb = 0; | ||
1527 | break; | ||
1528 | case 0x32: /* A+B LNA1 */ | ||
1529 | ant_conf->fast_div_bias = 0x1; | ||
1530 | ant_conf->main_gaintb = 0; | ||
1531 | ant_conf->alt_gaintb = 0; | ||
1532 | break; | ||
1533 | default: | ||
1534 | break; | ||
1535 | } | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | /* Antenna diversity and combining */ | ||
1540 | static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
1541 | { | ||
1542 | struct ath_hw_antcomb_conf div_ant_conf; | ||
1543 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
1544 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
1545 | int curr_main_set; | ||
1546 | int main_rssi = rs->rs_rssi_ctl0; | ||
1547 | int alt_rssi = rs->rs_rssi_ctl1; | ||
1548 | int rx_ant_conf, main_ant_conf; | ||
1549 | bool short_scan = false; | ||
1550 | |||
1551 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
1552 | ATH_ANT_RX_MASK; | ||
1553 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
1554 | ATH_ANT_RX_MASK; | ||
1555 | |||
1556 | /* Record packet only when both main_rssi and alt_rssi is positive */ | ||
1557 | if (main_rssi > 0 && alt_rssi > 0) { | ||
1558 | antcomb->total_pkt_count++; | ||
1559 | antcomb->main_total_rssi += main_rssi; | ||
1560 | antcomb->alt_total_rssi += alt_rssi; | ||
1561 | if (main_ant_conf == rx_ant_conf) | ||
1562 | antcomb->main_recv_cnt++; | ||
1563 | else | ||
1564 | antcomb->alt_recv_cnt++; | ||
1565 | } | ||
1566 | |||
1567 | /* Short scan check */ | ||
1568 | if (antcomb->scan && antcomb->alt_good) { | ||
1569 | if (time_after(jiffies, antcomb->scan_start_time + | ||
1570 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
1571 | short_scan = true; | ||
1572 | else | ||
1573 | if (antcomb->total_pkt_count == | ||
1574 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
1575 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1576 | antcomb->total_pkt_count); | ||
1577 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
1578 | short_scan = true; | ||
1579 | } | ||
1580 | } | ||
1581 | |||
1582 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
1583 | rs->rs_moreaggr) && !short_scan) | ||
1584 | return; | ||
1585 | |||
1586 | if (antcomb->total_pkt_count) { | ||
1587 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1588 | antcomb->total_pkt_count); | ||
1589 | main_rssi_avg = (antcomb->main_total_rssi / | ||
1590 | antcomb->total_pkt_count); | ||
1591 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
1592 | antcomb->total_pkt_count); | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
1597 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
1598 | curr_main_set = div_ant_conf.main_lna_conf; | ||
1599 | |||
1600 | antcomb->count++; | ||
1601 | |||
1602 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
1603 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1604 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
1605 | main_rssi_avg); | ||
1606 | antcomb->alt_good = true; | ||
1607 | } else { | ||
1608 | antcomb->alt_good = false; | ||
1609 | } | ||
1610 | |||
1611 | antcomb->count = 0; | ||
1612 | antcomb->scan = true; | ||
1613 | antcomb->scan_not_start = true; | ||
1614 | } | ||
1615 | |||
1616 | if (!antcomb->scan) { | ||
1617 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | ||
1618 | alt_ratio, curr_main_set, curr_alt_set, | ||
1619 | alt_rssi_avg, main_rssi_avg)) { | ||
1620 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1621 | /* Switch main and alt LNA */ | ||
1622 | div_ant_conf.main_lna_conf = | ||
1623 | ATH_ANT_DIV_COMB_LNA2; | ||
1624 | div_ant_conf.alt_lna_conf = | ||
1625 | ATH_ANT_DIV_COMB_LNA1; | ||
1626 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1627 | div_ant_conf.main_lna_conf = | ||
1628 | ATH_ANT_DIV_COMB_LNA1; | ||
1629 | div_ant_conf.alt_lna_conf = | ||
1630 | ATH_ANT_DIV_COMB_LNA2; | ||
1631 | } | ||
1632 | |||
1633 | goto div_comb_done; | ||
1634 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
1635 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
1636 | /* Set alt to another LNA */ | ||
1637 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
1638 | div_ant_conf.alt_lna_conf = | ||
1639 | ATH_ANT_DIV_COMB_LNA1; | ||
1640 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
1641 | div_ant_conf.alt_lna_conf = | ||
1642 | ATH_ANT_DIV_COMB_LNA2; | ||
1643 | |||
1644 | goto div_comb_done; | ||
1645 | } | ||
1646 | |||
1647 | if ((alt_rssi_avg < (main_rssi_avg + | ||
1648 | div_ant_conf.lna1_lna2_delta))) | ||
1649 | goto div_comb_done; | ||
1650 | } | ||
1651 | |||
1652 | if (!antcomb->scan_not_start) { | ||
1653 | switch (curr_alt_set) { | ||
1654 | case ATH_ANT_DIV_COMB_LNA2: | ||
1655 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1656 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1657 | antcomb->scan = true; | ||
1658 | /* set to A+B */ | ||
1659 | div_ant_conf.main_lna_conf = | ||
1660 | ATH_ANT_DIV_COMB_LNA1; | ||
1661 | div_ant_conf.alt_lna_conf = | ||
1662 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1663 | break; | ||
1664 | case ATH_ANT_DIV_COMB_LNA1: | ||
1665 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1666 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1667 | antcomb->scan = true; | ||
1668 | /* set to A+B */ | ||
1669 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1670 | div_ant_conf.alt_lna_conf = | ||
1671 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1672 | break; | ||
1673 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
1674 | antcomb->rssi_add = alt_rssi_avg; | ||
1675 | antcomb->scan = true; | ||
1676 | /* set to A-B */ | ||
1677 | div_ant_conf.alt_lna_conf = | ||
1678 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1679 | break; | ||
1680 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
1681 | antcomb->rssi_sub = alt_rssi_avg; | ||
1682 | antcomb->scan = false; | ||
1683 | if (antcomb->rssi_lna2 > | ||
1684 | (antcomb->rssi_lna1 + | ||
1685 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
1686 | /* use LNA2 as main LNA */ | ||
1687 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
1688 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1689 | /* set to A+B */ | ||
1690 | div_ant_conf.main_lna_conf = | ||
1691 | ATH_ANT_DIV_COMB_LNA2; | ||
1692 | div_ant_conf.alt_lna_conf = | ||
1693 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1694 | } else if (antcomb->rssi_sub > | ||
1695 | antcomb->rssi_lna1) { | ||
1696 | /* set to A-B */ | ||
1697 | div_ant_conf.main_lna_conf = | ||
1698 | ATH_ANT_DIV_COMB_LNA2; | ||
1699 | div_ant_conf.alt_lna_conf = | ||
1700 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1701 | } else { | ||
1702 | /* set to LNA1 */ | ||
1703 | div_ant_conf.main_lna_conf = | ||
1704 | ATH_ANT_DIV_COMB_LNA2; | ||
1705 | div_ant_conf.alt_lna_conf = | ||
1706 | ATH_ANT_DIV_COMB_LNA1; | ||
1707 | } | ||
1708 | } else { | ||
1709 | /* use LNA1 as main LNA */ | ||
1710 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
1711 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1712 | /* set to A+B */ | ||
1713 | div_ant_conf.main_lna_conf = | ||
1714 | ATH_ANT_DIV_COMB_LNA1; | ||
1715 | div_ant_conf.alt_lna_conf = | ||
1716 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1717 | } else if (antcomb->rssi_sub > | ||
1718 | antcomb->rssi_lna1) { | ||
1719 | /* set to A-B */ | ||
1720 | div_ant_conf.main_lna_conf = | ||
1721 | ATH_ANT_DIV_COMB_LNA1; | ||
1722 | div_ant_conf.alt_lna_conf = | ||
1723 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1724 | } else { | ||
1725 | /* set to LNA2 */ | ||
1726 | div_ant_conf.main_lna_conf = | ||
1727 | ATH_ANT_DIV_COMB_LNA1; | ||
1728 | div_ant_conf.alt_lna_conf = | ||
1729 | ATH_ANT_DIV_COMB_LNA2; | ||
1730 | } | ||
1731 | } | ||
1732 | break; | ||
1733 | default: | ||
1734 | break; | ||
1735 | } | ||
1736 | } else { | ||
1737 | if (!antcomb->alt_good) { | ||
1738 | antcomb->scan_not_start = false; | ||
1739 | /* Set alt to another LNA */ | ||
1740 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1741 | div_ant_conf.main_lna_conf = | ||
1742 | ATH_ANT_DIV_COMB_LNA2; | ||
1743 | div_ant_conf.alt_lna_conf = | ||
1744 | ATH_ANT_DIV_COMB_LNA1; | ||
1745 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1746 | div_ant_conf.main_lna_conf = | ||
1747 | ATH_ANT_DIV_COMB_LNA1; | ||
1748 | div_ant_conf.alt_lna_conf = | ||
1749 | ATH_ANT_DIV_COMB_LNA2; | ||
1750 | } | ||
1751 | goto div_comb_done; | ||
1752 | } | ||
1753 | } | ||
1754 | |||
1755 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
1756 | main_rssi_avg, alt_rssi_avg, | ||
1757 | alt_ratio); | ||
1758 | |||
1759 | antcomb->quick_scan_cnt++; | ||
1760 | |||
1761 | div_comb_done: | ||
1762 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | ||
1763 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
1764 | |||
1765 | antcomb->scan_start_time = jiffies; | ||
1766 | antcomb->total_pkt_count = 0; | ||
1767 | antcomb->main_total_rssi = 0; | ||
1768 | antcomb->alt_total_rssi = 0; | ||
1769 | antcomb->main_recv_cnt = 0; | ||
1770 | antcomb->alt_recv_cnt = 0; | ||
1771 | } | ||
1772 | |||
1773 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1033 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1774 | { | 1034 | { |
1775 | struct ath_buf *bf; | 1035 | struct ath_buf *bf; |
@@ -1803,7 +1063,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1803 | 1063 | ||
1804 | do { | 1064 | do { |
1805 | /* If handling rx interrupt and flush is in progress => exit */ | 1065 | /* If handling rx interrupt and flush is in progress => exit */ |
1806 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) | 1066 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) |
1807 | break; | 1067 | break; |
1808 | 1068 | ||
1809 | memset(&rs, 0, sizeof(rs)); | 1069 | memset(&rs, 0, sizeof(rs)); |
@@ -1841,13 +1101,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1841 | else | 1101 | else |
1842 | rs.is_mybeacon = false; | 1102 | rs.is_mybeacon = false; |
1843 | 1103 | ||
1104 | sc->rx.num_pkts++; | ||
1844 | ath_debug_stat_rx(sc, &rs); | 1105 | ath_debug_stat_rx(sc, &rs); |
1845 | 1106 | ||
1846 | /* | 1107 | /* |
1847 | * If we're asked to flush receive queue, directly | 1108 | * If we're asked to flush receive queue, directly |
1848 | * chain it back at the queue without processing it. | 1109 | * chain it back at the queue without processing it. |
1849 | */ | 1110 | */ |
1850 | if (sc->sc_flags & SC_OP_RXFLUSH) { | 1111 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { |
1851 | RX_STAT_INC(rx_drop_rxflush); | 1112 | RX_STAT_INC(rx_drop_rxflush); |
1852 | goto requeue_drop_frag; | 1113 | goto requeue_drop_frag; |
1853 | } | 1114 | } |
@@ -1968,7 +1229,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1968 | skb_trim(skb, skb->len - 8); | 1229 | skb_trim(skb, skb->len - 8); |
1969 | 1230 | ||
1970 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 1231 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1971 | |||
1972 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1232 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1973 | PS_WAIT_FOR_CAB | | 1233 | PS_WAIT_FOR_CAB | |
1974 | PS_WAIT_FOR_PSPOLL_DATA)) || | 1234 | PS_WAIT_FOR_PSPOLL_DATA)) || |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 458f81b4a7cb..560d6effac7a 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -2211,5 +2211,7 @@ enum { | |||
2211 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff | 2211 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff |
2212 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 | 2212 | #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 |
2213 | 2213 | ||
2214 | #define AR_GLB_SWREG_DISCONT_MODE 0x2002c | ||
2215 | #define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3 | ||
2214 | 2216 | ||
2215 | #endif | 2217 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index d59dd01d6cde..f777ddcd1172 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -105,19 +105,19 @@ static int ath_max_4ms_framelen[4][32] = { | |||
105 | /* Aggregation logic */ | 105 | /* Aggregation logic */ |
106 | /*********************/ | 106 | /*********************/ |
107 | 107 | ||
108 | static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) | 108 | void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) |
109 | __acquires(&txq->axq_lock) | 109 | __acquires(&txq->axq_lock) |
110 | { | 110 | { |
111 | spin_lock_bh(&txq->axq_lock); | 111 | spin_lock_bh(&txq->axq_lock); |
112 | } | 112 | } |
113 | 113 | ||
114 | static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) | 114 | void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) |
115 | __releases(&txq->axq_lock) | 115 | __releases(&txq->axq_lock) |
116 | { | 116 | { |
117 | spin_unlock_bh(&txq->axq_lock); | 117 | spin_unlock_bh(&txq->axq_lock); |
118 | } | 118 | } |
119 | 119 | ||
120 | static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) | 120 | void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) |
121 | __releases(&txq->axq_lock) | 121 | __releases(&txq->axq_lock) |
122 | { | 122 | { |
123 | struct sk_buff_head q; | 123 | struct sk_buff_head q; |
@@ -1536,7 +1536,7 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1536 | int i; | 1536 | int i; |
1537 | u32 npend = 0; | 1537 | u32 npend = 0; |
1538 | 1538 | ||
1539 | if (sc->sc_flags & SC_OP_INVALID) | 1539 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
1540 | return true; | 1540 | return true; |
1541 | 1541 | ||
1542 | ath9k_hw_abort_tx_dma(ah); | 1542 | ath9k_hw_abort_tx_dma(ah); |
@@ -1994,6 +1994,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1994 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1994 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1995 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | 1995 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1996 | int q, padpos, padsize; | 1996 | int q, padpos, padsize; |
1997 | unsigned long flags; | ||
1997 | 1998 | ||
1998 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); | 1999 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); |
1999 | 2000 | ||
@@ -2012,6 +2013,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2012 | skb_pull(skb, padsize); | 2013 | skb_pull(skb, padsize); |
2013 | } | 2014 | } |
2014 | 2015 | ||
2016 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
2015 | if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { | 2017 | if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { |
2016 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; | 2018 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; |
2017 | ath_dbg(common, PS, | 2019 | ath_dbg(common, PS, |
@@ -2021,6 +2023,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2021 | PS_WAIT_FOR_PSPOLL_DATA | | 2023 | PS_WAIT_FOR_PSPOLL_DATA | |
2022 | PS_WAIT_FOR_TX_ACK)); | 2024 | PS_WAIT_FOR_TX_ACK)); |
2023 | } | 2025 | } |
2026 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
2024 | 2027 | ||
2025 | q = skb_get_queue_mapping(skb); | 2028 | q = skb_get_queue_mapping(skb); |
2026 | if (txq == sc->tx.txq_map[q]) { | 2029 | if (txq == sc->tx.txq_map[q]) { |
@@ -2231,46 +2234,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2231 | ath_txq_unlock_complete(sc, txq); | 2234 | ath_txq_unlock_complete(sc, txq); |
2232 | } | 2235 | } |
2233 | 2236 | ||
2234 | static void ath_tx_complete_poll_work(struct work_struct *work) | ||
2235 | { | ||
2236 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
2237 | tx_complete_work.work); | ||
2238 | struct ath_txq *txq; | ||
2239 | int i; | ||
2240 | bool needreset = false; | ||
2241 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
2242 | sc->tx_complete_poll_work_seen++; | ||
2243 | #endif | ||
2244 | |||
2245 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
2246 | if (ATH_TXQ_SETUP(sc, i)) { | ||
2247 | txq = &sc->tx.txq[i]; | ||
2248 | ath_txq_lock(sc, txq); | ||
2249 | if (txq->axq_depth) { | ||
2250 | if (txq->axq_tx_inprogress) { | ||
2251 | needreset = true; | ||
2252 | ath_txq_unlock(sc, txq); | ||
2253 | break; | ||
2254 | } else { | ||
2255 | txq->axq_tx_inprogress = true; | ||
2256 | } | ||
2257 | } | ||
2258 | ath_txq_unlock_complete(sc, txq); | ||
2259 | } | ||
2260 | |||
2261 | if (needreset) { | ||
2262 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | ||
2263 | "tx hung, resetting the chip\n"); | ||
2264 | RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); | ||
2265 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
2266 | } | ||
2267 | |||
2268 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | ||
2269 | msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); | ||
2270 | } | ||
2271 | |||
2272 | |||
2273 | |||
2274 | void ath_tx_tasklet(struct ath_softc *sc) | 2237 | void ath_tx_tasklet(struct ath_softc *sc) |
2275 | { | 2238 | { |
2276 | struct ath_hw *ah = sc->sc_ah; | 2239 | struct ath_hw *ah = sc->sc_ah; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index cd9c9bc186d9..8b06ca56125e 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -1508,7 +1508,7 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev) | |||
1508 | 1508 | ||
1509 | static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) | 1509 | static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) |
1510 | { | 1510 | { |
1511 | b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" | 1511 | b43legacyerr(wl, "You must go to http://wireless.kernel.org/en/users/" |
1512 | "Drivers/b43#devicefirmware " | 1512 | "Drivers/b43#devicefirmware " |
1513 | "and download the correct firmware (version 3).\n"); | 1513 | "and download the correct firmware (version 3).\n"); |
1514 | } | 1514 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index 6d8b7213643a..3c6f9b1e8d05 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -631,9 +631,8 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) | |||
631 | cc = sii->icbus->drv_cc.core; | 631 | cc = sii->icbus->drv_cc.core; |
632 | 632 | ||
633 | /* mask and set */ | 633 | /* mask and set */ |
634 | if (mask || val) { | 634 | if (mask || val) |
635 | bcma_maskset32(cc, regoff, ~mask, val); | 635 | bcma_maskset32(cc, regoff, ~mask, val); |
636 | } | ||
637 | 636 | ||
638 | /* readback */ | 637 | /* readback */ |
639 | w = bcma_read32(cc, regoff); | 638 | w = bcma_read32(cc, regoff); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index d9f04a683bdb..d6fa9829af9a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h | |||
@@ -193,7 +193,7 @@ extern void ai_detach(struct si_pub *sih); | |||
193 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); | 193 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); |
194 | extern void ai_clkctl_init(struct si_pub *sih); | 194 | extern void ai_clkctl_init(struct si_pub *sih); |
195 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); | 195 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); |
196 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); | 196 | extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode); |
197 | extern bool ai_deviceremoved(struct si_pub *sih); | 197 | extern bool ai_deviceremoved(struct si_pub *sih); |
198 | 198 | ||
199 | extern void ai_pci_down(struct si_pub *sih); | 199 | extern void ai_pci_down(struct si_pub *sih); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 13b261517cce..366718146418 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -14358,7 +14358,7 @@ void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) | |||
14358 | 14358 | ||
14359 | wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); | 14359 | wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); |
14360 | 14360 | ||
14361 | if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) | 14361 | if (pi->sh && (pi->sh->_rifs_phy != rifs)) |
14362 | pi->sh->_rifs_phy = rifs; | 14362 | pi->sh->_rifs_phy = rifs; |
14363 | } | 14363 | } |
14364 | 14364 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index b45ab34cdfdc..3e6405e06ac0 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
@@ -43,6 +43,8 @@ EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); | |||
43 | /* Free the driver packet. Free the tag if present */ | 43 | /* Free the driver packet. Free the tag if present */ |
44 | void brcmu_pkt_buf_free_skb(struct sk_buff *skb) | 44 | void brcmu_pkt_buf_free_skb(struct sk_buff *skb) |
45 | { | 45 | { |
46 | if (!skb) | ||
47 | return; | ||
46 | WARN_ON(skb->next); | 48 | WARN_ON(skb->next); |
47 | if (skb->destructor) | 49 | if (skb->destructor) |
48 | /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if | 50 | /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index afdec4a0d9a0..0df459147394 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -2701,6 +2701,20 @@ static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) | |||
2701 | memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6); | 2701 | memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6); |
2702 | } | 2702 | } |
2703 | 2703 | ||
2704 | static void ipw_read_eeprom(struct ipw_priv *priv) | ||
2705 | { | ||
2706 | int i; | ||
2707 | __le16 *eeprom = (__le16 *) priv->eeprom; | ||
2708 | |||
2709 | IPW_DEBUG_TRACE(">>\n"); | ||
2710 | |||
2711 | /* read entire contents of eeprom into private buffer */ | ||
2712 | for (i = 0; i < 128; i++) | ||
2713 | eeprom[i] = cpu_to_le16(eeprom_read_u16(priv, (u8) i)); | ||
2714 | |||
2715 | IPW_DEBUG_TRACE("<<\n"); | ||
2716 | } | ||
2717 | |||
2704 | /* | 2718 | /* |
2705 | * Either the device driver (i.e. the host) or the firmware can | 2719 | * Either the device driver (i.e. the host) or the firmware can |
2706 | * load eeprom data into the designated region in SRAM. If neither | 2720 | * load eeprom data into the designated region in SRAM. If neither |
@@ -2712,14 +2726,9 @@ static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) | |||
2712 | static void ipw_eeprom_init_sram(struct ipw_priv *priv) | 2726 | static void ipw_eeprom_init_sram(struct ipw_priv *priv) |
2713 | { | 2727 | { |
2714 | int i; | 2728 | int i; |
2715 | __le16 *eeprom = (__le16 *) priv->eeprom; | ||
2716 | 2729 | ||
2717 | IPW_DEBUG_TRACE(">>\n"); | 2730 | IPW_DEBUG_TRACE(">>\n"); |
2718 | 2731 | ||
2719 | /* read entire contents of eeprom into private buffer */ | ||
2720 | for (i = 0; i < 128; i++) | ||
2721 | eeprom[i] = cpu_to_le16(eeprom_read_u16(priv, (u8) i)); | ||
2722 | |||
2723 | /* | 2732 | /* |
2724 | If the data looks correct, then copy it to our private | 2733 | If the data looks correct, then copy it to our private |
2725 | copy. Otherwise let the firmware know to perform the operation | 2734 | copy. Otherwise let the firmware know to perform the operation |
@@ -3643,8 +3652,10 @@ static int ipw_load(struct ipw_priv *priv) | |||
3643 | /* ack fw init done interrupt */ | 3652 | /* ack fw init done interrupt */ |
3644 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); | 3653 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
3645 | 3654 | ||
3646 | /* read eeprom data and initialize the eeprom region of sram */ | 3655 | /* read eeprom data */ |
3647 | priv->eeprom_delay = 1; | 3656 | priv->eeprom_delay = 1; |
3657 | ipw_read_eeprom(priv); | ||
3658 | /* initialize the eeprom region of sram */ | ||
3648 | ipw_eeprom_init_sram(priv); | 3659 | ipw_eeprom_init_sram(priv); |
3649 | 3660 | ||
3650 | /* enable interrupts */ | 3661 | /* enable interrupts */ |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 509301a5e7e2..d24eaf89ffb5 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -5724,7 +5724,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
5724 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | 5724 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); |
5725 | 5725 | ||
5726 | hw->wiphy->flags |= | 5726 | hw->wiphy->flags |= |
5727 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 5727 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
5728 | WIPHY_FLAG_IBSS_RSN; | ||
5728 | 5729 | ||
5729 | /* | 5730 | /* |
5730 | * For now, disable PS by default because it affects | 5731 | * For now, disable PS by default because it affects |
@@ -5873,6 +5874,16 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
5873 | return -EOPNOTSUPP; | 5874 | return -EOPNOTSUPP; |
5874 | } | 5875 | } |
5875 | 5876 | ||
5877 | /* | ||
5878 | * To support IBSS RSN, don't program group keys in IBSS, the | ||
5879 | * hardware will then not attempt to decrypt the frames. | ||
5880 | */ | ||
5881 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
5882 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
5883 | D_MAC80211("leave - ad-hoc group key\n"); | ||
5884 | return -EOPNOTSUPP; | ||
5885 | } | ||
5886 | |||
5876 | sta_id = il_sta_id_or_broadcast(il, sta); | 5887 | sta_id = il_sta_id_or_broadcast(il, sta); |
5877 | if (sta_id == IL_INVALID_STATION) | 5888 | if (sta_id == IL_INVALID_STATION) |
5878 | return -EINVAL; | 5889 | return -EINVAL; |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 2463c0626438..727fbb5db9da 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -6,6 +6,7 @@ config IWLWIFI | |||
6 | select LEDS_CLASS | 6 | select LEDS_CLASS |
7 | select LEDS_TRIGGERS | 7 | select LEDS_TRIGGERS |
8 | select MAC80211_LEDS | 8 | select MAC80211_LEDS |
9 | select IWLDVM | ||
9 | ---help--- | 10 | ---help--- |
10 | Select to build the driver supporting the: | 11 | Select to build the driver supporting the: |
11 | 12 | ||
@@ -41,6 +42,10 @@ config IWLWIFI | |||
41 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 42 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
42 | module will be called iwlwifi. | 43 | module will be called iwlwifi. |
43 | 44 | ||
45 | config IWLDVM | ||
46 | tristate "Intel Wireless WiFi" | ||
47 | depends on IWLWIFI | ||
48 | |||
44 | menu "Debugging Options" | 49 | menu "Debugging Options" |
45 | depends on IWLWIFI | 50 | depends on IWLWIFI |
46 | 51 | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index d615eacbf050..98c8f6449649 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,27 +1,17 @@ | |||
1 | # WIFI | 1 | obj-$(CONFIG_IWLDVM) += dvm/ |
2 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o | 2 | |
3 | iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o | 3 | CFLAGS_iwl-devtrace.o := -I$(src) |
4 | iwlwifi-objs += iwl-ucode.o iwl-agn-tx.o iwl-debug.o | ||
5 | iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o | ||
6 | iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o | ||
7 | 4 | ||
8 | iwlwifi-objs += iwl-eeprom.o iwl-power.o | 5 | # common |
9 | iwlwifi-objs += iwl-scan.o iwl-led.o | 6 | obj-$(CONFIG_IWLWIFI) += iwlwifi.o |
10 | iwlwifi-objs += iwl-agn-rxon.o iwl-agn-devices.o | 7 | iwlwifi-objs += iwl-io.o |
11 | iwlwifi-objs += iwl-5000.o | ||
12 | iwlwifi-objs += iwl-6000.o | ||
13 | iwlwifi-objs += iwl-1000.o | ||
14 | iwlwifi-objs += iwl-2000.o | ||
15 | iwlwifi-objs += iwl-pci.o | ||
16 | iwlwifi-objs += iwl-drv.o | 8 | iwlwifi-objs += iwl-drv.o |
9 | iwlwifi-objs += iwl-debug.o | ||
17 | iwlwifi-objs += iwl-notif-wait.o | 10 | iwlwifi-objs += iwl-notif-wait.o |
18 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | 11 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o |
12 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | ||
13 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | ||
19 | 14 | ||
20 | |||
21 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | ||
22 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 15 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
23 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o | ||
24 | |||
25 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
26 | 16 | ||
27 | ccflags-y += -D__CHECK_ENDIAN__ | 17 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile new file mode 100644 index 000000000000..5ff76b204141 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/dvm/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # DVM | ||
2 | obj-$(CONFIG_IWLDVM) += iwldvm.o | ||
3 | iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o | ||
4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o | ||
5 | |||
6 | iwldvm-objs += power.o | ||
7 | iwldvm-objs += scan.o led.o | ||
8 | iwldvm-objs += rxon.o devices.o | ||
9 | |||
10 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | ||
11 | iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o | ||
12 | |||
13 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 79c0fe06f4db..2ae3608472a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -63,9 +63,10 @@ | |||
63 | #ifndef __iwl_agn_h__ | 63 | #ifndef __iwl_agn_h__ |
64 | #define __iwl_agn_h__ | 64 | #define __iwl_agn_h__ |
65 | 65 | ||
66 | #include "iwl-dev.h" | ||
67 | #include "iwl-config.h" | 66 | #include "iwl-config.h" |
68 | 67 | ||
68 | #include "dev.h" | ||
69 | |||
69 | /* The first 11 queues (0-10) are used otherwise */ | 70 | /* The first 11 queues (0-10) are used otherwise */ |
70 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 | 71 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 |
71 | 72 | ||
@@ -91,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib; | |||
91 | #define STATUS_CT_KILL 1 | 92 | #define STATUS_CT_KILL 1 |
92 | #define STATUS_ALIVE 2 | 93 | #define STATUS_ALIVE 2 |
93 | #define STATUS_READY 3 | 94 | #define STATUS_READY 3 |
94 | #define STATUS_GEO_CONFIGURED 4 | ||
95 | #define STATUS_EXIT_PENDING 5 | 95 | #define STATUS_EXIT_PENDING 5 |
96 | #define STATUS_STATISTICS 6 | 96 | #define STATUS_STATISTICS 6 |
97 | #define STATUS_SCANNING 7 | 97 | #define STATUS_SCANNING 7 |
@@ -101,6 +101,7 @@ extern struct iwl_lib_ops iwl6030_lib; | |||
101 | #define STATUS_CHANNEL_SWITCH_PENDING 11 | 101 | #define STATUS_CHANNEL_SWITCH_PENDING 11 |
102 | #define STATUS_SCAN_COMPLETE 12 | 102 | #define STATUS_SCAN_COMPLETE 12 |
103 | #define STATUS_POWER_PMI 13 | 103 | #define STATUS_POWER_PMI 13 |
104 | #define STATUS_SCAN_ROC_EXPIRED 14 | ||
104 | 105 | ||
105 | struct iwl_ucode_capabilities; | 106 | struct iwl_ucode_capabilities; |
106 | 107 | ||
@@ -255,6 +256,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
255 | enum iwl_scan_type scan_type, | 256 | enum iwl_scan_type scan_type, |
256 | enum ieee80211_band band); | 257 | enum ieee80211_band band); |
257 | 258 | ||
259 | void iwl_scan_roc_expired(struct iwl_priv *priv); | ||
260 | void iwl_scan_offchannel_skb(struct iwl_priv *priv); | ||
261 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv); | ||
262 | |||
258 | /* For faster active scanning, scan will move to the next channel if fewer than | 263 | /* For faster active scanning, scan will move to the next channel if fewer than |
259 | * PLCP_QUIET_THRESH packets are heard on this channel within | 264 | * PLCP_QUIET_THRESH packets are heard on this channel within |
260 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell | 265 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell |
@@ -437,10 +442,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
437 | 442 | ||
438 | static inline int iwl_is_ready(struct iwl_priv *priv) | 443 | static inline int iwl_is_ready(struct iwl_priv *priv) |
439 | { | 444 | { |
440 | /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are | 445 | /* The adapter is 'ready' if READY EXIT_PENDING is not set */ |
441 | * set but EXIT_PENDING is not */ | ||
442 | return test_bit(STATUS_READY, &priv->status) && | 446 | return test_bit(STATUS_READY, &priv->status) && |
443 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) && | ||
444 | !test_bit(STATUS_EXIT_PENDING, &priv->status); | 447 | !test_bit(STATUS_EXIT_PENDING, &priv->status); |
445 | } | 448 | } |
446 | 449 | ||
@@ -518,85 +521,4 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd) | |||
518 | return s; | 521 | return s; |
519 | return "UNKNOWN"; | 522 | return "UNKNOWN"; |
520 | } | 523 | } |
521 | |||
522 | /* API method exported for mvm hybrid state */ | ||
523 | void iwl_setup_deferred_work(struct iwl_priv *priv); | ||
524 | int iwl_send_wimax_coex(struct iwl_priv *priv); | ||
525 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | ||
526 | void iwl_option_config(struct iwl_priv *priv); | ||
527 | void iwl_set_hw_params(struct iwl_priv *priv); | ||
528 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); | ||
529 | int iwl_init_drv(struct iwl_priv *priv); | ||
530 | void iwl_uninit_drv(struct iwl_priv *priv); | ||
531 | void iwl_send_bt_config(struct iwl_priv *priv); | ||
532 | void iwl_rf_kill_ct_config(struct iwl_priv *priv); | ||
533 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
534 | void iwl_teardown_interface(struct iwl_priv *priv, | ||
535 | struct ieee80211_vif *vif, | ||
536 | bool mode_change); | ||
537 | int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
538 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
539 | void iwlagn_check_needed_chains(struct iwl_priv *priv, | ||
540 | struct iwl_rxon_context *ctx, | ||
541 | struct ieee80211_bss_conf *bss_conf); | ||
542 | void iwlagn_chain_noise_reset(struct iwl_priv *priv); | ||
543 | int iwlagn_update_beacon(struct iwl_priv *priv, | ||
544 | struct ieee80211_vif *vif); | ||
545 | void iwl_tt_handler(struct iwl_priv *priv); | ||
546 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode); | ||
547 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
548 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); | ||
549 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
550 | void iwl_nic_error(struct iwl_op_mode *op_mode); | ||
551 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode); | ||
552 | void iwl_nic_config(struct iwl_op_mode *op_mode); | ||
553 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||
554 | struct ieee80211_sta *sta, bool set); | ||
555 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||
556 | enum ieee80211_rssi_event rssi_event); | ||
557 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw); | ||
558 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw); | ||
559 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); | ||
560 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
561 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
562 | struct ieee80211_channel_switch *ch_switch); | ||
563 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | ||
564 | struct ieee80211_vif *vif, | ||
565 | struct ieee80211_sta *sta, | ||
566 | enum ieee80211_sta_state old_state, | ||
567 | enum ieee80211_sta_state new_state); | ||
568 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||
569 | struct ieee80211_vif *vif, | ||
570 | enum ieee80211_ampdu_mlme_action action, | ||
571 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
572 | u8 buf_size); | ||
573 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | ||
574 | struct ieee80211_vif *vif, | ||
575 | struct cfg80211_scan_request *req); | ||
576 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | ||
577 | struct ieee80211_vif *vif, | ||
578 | enum sta_notify_cmd cmd, | ||
579 | struct ieee80211_sta *sta); | ||
580 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
581 | unsigned int changed_flags, | ||
582 | unsigned int *total_flags, | ||
583 | u64 multicast); | ||
584 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | ||
585 | struct ieee80211_vif *vif, u16 queue, | ||
586 | const struct ieee80211_tx_queue_params *params); | ||
587 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||
588 | struct ieee80211_vif *vif, | ||
589 | struct cfg80211_gtk_rekey_data *data); | ||
590 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||
591 | struct ieee80211_vif *vif, | ||
592 | struct ieee80211_key_conf *keyconf, | ||
593 | struct ieee80211_sta *sta, | ||
594 | u32 iv32, u16 *phase1key); | ||
595 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
596 | struct ieee80211_vif *vif, | ||
597 | struct ieee80211_sta *sta, | ||
598 | struct ieee80211_key_conf *key); | ||
599 | void iwlagn_mac_stop(struct ieee80211_hw *hw); | ||
600 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
601 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | ||
602 | #endif /* __iwl_agn_h__ */ | 524 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 95f27f1a423b..f2dd671d7dc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -63,10 +63,11 @@ | |||
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <net/mac80211.h> | 64 | #include <net/mac80211.h> |
65 | 65 | ||
66 | #include "iwl-dev.h" | ||
67 | #include "iwl-agn-calib.h" | ||
68 | #include "iwl-trans.h" | 66 | #include "iwl-trans.h" |
69 | #include "iwl-agn.h" | 67 | |
68 | #include "dev.h" | ||
69 | #include "calib.h" | ||
70 | #include "agn.h" | ||
70 | 71 | ||
71 | /***************************************************************************** | 72 | /***************************************************************************** |
72 | * INIT calibrations framework | 73 | * INIT calibrations framework |
@@ -832,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
832 | * To be safe, simply mask out any chains that we know | 833 | * To be safe, simply mask out any chains that we know |
833 | * are not on the device. | 834 | * are not on the device. |
834 | */ | 835 | */ |
835 | active_chains &= priv->hw_params.valid_rx_ant; | 836 | active_chains &= priv->eeprom_data->valid_rx_ant; |
836 | 837 | ||
837 | num_tx_chains = 0; | 838 | num_tx_chains = 0; |
838 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 839 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
839 | /* loops on all the bits of | 840 | /* loops on all the bits of |
840 | * priv->hw_setting.valid_tx_ant */ | 841 | * priv->hw_setting.valid_tx_ant */ |
841 | u8 ant_msk = (1 << i); | 842 | u8 ant_msk = (1 << i); |
842 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | 843 | if (!(priv->eeprom_data->valid_tx_ant & ant_msk)) |
843 | continue; | 844 | continue; |
844 | 845 | ||
845 | num_tx_chains++; | 846 | num_tx_chains++; |
@@ -853,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
853 | * connect the first valid tx chain | 854 | * connect the first valid tx chain |
854 | */ | 855 | */ |
855 | first_chain = | 856 | first_chain = |
856 | find_first_chain(priv->hw_params.valid_tx_ant); | 857 | find_first_chain(priv->eeprom_data->valid_tx_ant); |
857 | data->disconn_array[first_chain] = 0; | 858 | data->disconn_array[first_chain] = 0; |
858 | active_chains |= BIT(first_chain); | 859 | active_chains |= BIT(first_chain); |
859 | IWL_DEBUG_CALIB(priv, | 860 | IWL_DEBUG_CALIB(priv, |
@@ -863,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
863 | } | 864 | } |
864 | } | 865 | } |
865 | 866 | ||
866 | if (active_chains != priv->hw_params.valid_rx_ant && | 867 | if (active_chains != priv->eeprom_data->valid_rx_ant && |
867 | active_chains != priv->chain_noise_data.active_chains) | 868 | active_chains != priv->chain_noise_data.active_chains) |
868 | IWL_DEBUG_CALIB(priv, | 869 | IWL_DEBUG_CALIB(priv, |
869 | "Detected that not all antennas are connected! " | 870 | "Detected that not all antennas are connected! " |
870 | "Connected: %#x, valid: %#x.\n", | 871 | "Connected: %#x, valid: %#x.\n", |
871 | active_chains, | 872 | active_chains, |
872 | priv->hw_params.valid_rx_ant); | 873 | priv->eeprom_data->valid_rx_ant); |
873 | 874 | ||
874 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 875 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
875 | data->active_chains = active_chains; | 876 | data->active_chains = active_chains; |
@@ -1054,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1054 | priv->cfg->bt_params->advanced_bt_coexist) { | 1055 | priv->cfg->bt_params->advanced_bt_coexist) { |
1055 | /* Disable disconnected antenna algorithm for advanced | 1056 | /* Disable disconnected antenna algorithm for advanced |
1056 | bt coex, assuming valid antennas are connected */ | 1057 | bt coex, assuming valid antennas are connected */ |
1057 | data->active_chains = priv->hw_params.valid_rx_ant; | 1058 | data->active_chains = priv->eeprom_data->valid_rx_ant; |
1058 | for (i = 0; i < NUM_RX_CHAINS; i++) | 1059 | for (i = 0; i < NUM_RX_CHAINS; i++) |
1059 | if (!(data->active_chains & (1<<i))) | 1060 | if (!(data->active_chains & (1<<i))) |
1060 | data->disconn_array[i] = 1; | 1061 | data->disconn_array[i] = 1; |
@@ -1083,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1083 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", | 1084 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", |
1084 | min_average_noise, min_average_noise_antenna_i); | 1085 | min_average_noise, min_average_noise_antenna_i); |
1085 | 1086 | ||
1086 | iwlagn_gain_computation(priv, average_noise, | 1087 | iwlagn_gain_computation( |
1087 | find_first_chain(priv->hw_params.valid_rx_ant)); | 1088 | priv, average_noise, |
1089 | find_first_chain(priv->eeprom_data->valid_rx_ant)); | ||
1088 | 1090 | ||
1089 | /* Some power changes may have been made during the calibration. | 1091 | /* Some power changes may have been made during the calibration. |
1090 | * Update and commit the RXON | 1092 | * Update and commit the RXON |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/dvm/calib.h index dbe13787f272..2349f393cc42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/dvm/calib.h | |||
@@ -62,8 +62,8 @@ | |||
62 | #ifndef __iwl_calib_h__ | 62 | #ifndef __iwl_calib_h__ |
63 | #define __iwl_calib_h__ | 63 | #define __iwl_calib_h__ |
64 | 64 | ||
65 | #include "iwl-dev.h" | 65 | #include "dev.h" |
66 | #include "iwl-commands.h" | 66 | #include "commands.h" |
67 | 67 | ||
68 | void iwl_chain_noise_calibration(struct iwl_priv *priv); | 68 | void iwl_chain_noise_calibration(struct iwl_priv *priv); |
69 | void iwl_sensitivity_calibration(struct iwl_priv *priv); | 69 | void iwl_sensitivity_calibration(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 9af6a239b384..64811cd91635 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -61,9 +61,9 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | /* | 63 | /* |
64 | * Please use this file (iwl-commands.h) only for uCode API definitions. | 64 | * Please use this file (commands.h) only for uCode API definitions. |
65 | * Please use iwl-xxxx-hw.h for hardware-related definitions. | 65 | * Please use iwl-xxxx-hw.h for hardware-related definitions. |
66 | * Please use iwl-dev.h for driver implementation definitions. | 66 | * Please use dev.h for driver implementation definitions. |
67 | */ | 67 | */ |
68 | 68 | ||
69 | #ifndef __iwl_commands_h__ | 69 | #ifndef __iwl_commands_h__ |
@@ -197,9 +197,6 @@ enum { | |||
197 | * | 197 | * |
198 | *****************************************************************************/ | 198 | *****************************************************************************/ |
199 | 199 | ||
200 | /* iwl_cmd_header flags value */ | ||
201 | #define IWL_CMD_FAILED_MSK 0x40 | ||
202 | |||
203 | /** | 200 | /** |
204 | * iwlagn rate_n_flags bit fields | 201 | * iwlagn rate_n_flags bit fields |
205 | * | 202 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index e7c157e5ebeb..8a2d9e643b14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -30,16 +30,12 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | |||
34 | #include <linux/ieee80211.h> | 33 | #include <linux/ieee80211.h> |
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | |||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
40 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
41 | #include "iwl-agn.h" | 37 | #include "dev.h" |
42 | #include "iwl-modparams.h" | 38 | #include "agn.h" |
43 | 39 | ||
44 | /* create and remove of files */ | 40 | /* create and remove of files */ |
45 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | 41 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
@@ -307,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
307 | const u8 *ptr; | 303 | const u8 *ptr; |
308 | char *buf; | 304 | char *buf; |
309 | u16 eeprom_ver; | 305 | u16 eeprom_ver; |
310 | size_t eeprom_len = priv->cfg->base_params->eeprom_size; | 306 | size_t eeprom_len = priv->eeprom_blob_size; |
311 | buf_size = 4 * eeprom_len + 256; | 307 | buf_size = 4 * eeprom_len + 256; |
312 | 308 | ||
313 | if (eeprom_len % 16) | 309 | if (eeprom_len % 16) |
314 | return -ENODATA; | 310 | return -ENODATA; |
315 | 311 | ||
316 | ptr = priv->eeprom; | 312 | ptr = priv->eeprom_blob; |
317 | if (!ptr) | 313 | if (!ptr) |
318 | return -ENOMEM; | 314 | return -ENOMEM; |
319 | 315 | ||
@@ -322,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
322 | if (!buf) | 318 | if (!buf) |
323 | return -ENOMEM; | 319 | return -ENOMEM; |
324 | 320 | ||
325 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 321 | eeprom_ver = priv->eeprom_data->eeprom_version; |
326 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 322 | pos += scnprintf(buf + pos, buf_size - pos, |
327 | "version: 0x%x\n", | 323 | "NVM version: 0x%x\n", eeprom_ver); |
328 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
329 | ? "OTP" : "EEPROM", eeprom_ver); | ||
330 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 324 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
331 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 325 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
332 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 326 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -351,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
351 | char *buf; | 345 | char *buf; |
352 | ssize_t ret; | 346 | ssize_t ret; |
353 | 347 | ||
354 | if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | ||
355 | return -EAGAIN; | ||
356 | |||
357 | buf = kzalloc(bufsz, GFP_KERNEL); | 348 | buf = kzalloc(bufsz, GFP_KERNEL); |
358 | if (!buf) | 349 | if (!buf) |
359 | return -ENOMEM; | 350 | return -ENOMEM; |
@@ -426,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
426 | test_bit(STATUS_ALIVE, &priv->status)); | 417 | test_bit(STATUS_ALIVE, &priv->status)); |
427 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | 418 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", |
428 | test_bit(STATUS_READY, &priv->status)); | 419 | test_bit(STATUS_READY, &priv->status)); |
429 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", | ||
430 | test_bit(STATUS_GEO_CONFIGURED, &priv->status)); | ||
431 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 420 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", |
432 | test_bit(STATUS_EXIT_PENDING, &priv->status)); | 421 | test_bit(STATUS_EXIT_PENDING, &priv->status)); |
433 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 422 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", |
@@ -1341,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1341 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | 1330 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { |
1342 | pos += scnprintf(buf + pos, bufsz - pos, | 1331 | pos += scnprintf(buf + pos, bufsz - pos, |
1343 | "tx power: (1/2 dB step)\n"); | 1332 | "tx power: (1/2 dB step)\n"); |
1344 | if ((priv->hw_params.valid_tx_ant & ANT_A) && | 1333 | if ((priv->eeprom_data->valid_tx_ant & ANT_A) && |
1345 | tx->tx_power.ant_a) | 1334 | tx->tx_power.ant_a) |
1346 | pos += scnprintf(buf + pos, bufsz - pos, | 1335 | pos += scnprintf(buf + pos, bufsz - pos, |
1347 | fmt_hex, "antenna A:", | 1336 | fmt_hex, "antenna A:", |
1348 | tx->tx_power.ant_a); | 1337 | tx->tx_power.ant_a); |
1349 | if ((priv->hw_params.valid_tx_ant & ANT_B) && | 1338 | if ((priv->eeprom_data->valid_tx_ant & ANT_B) && |
1350 | tx->tx_power.ant_b) | 1339 | tx->tx_power.ant_b) |
1351 | pos += scnprintf(buf + pos, bufsz - pos, | 1340 | pos += scnprintf(buf + pos, bufsz - pos, |
1352 | fmt_hex, "antenna B:", | 1341 | fmt_hex, "antenna B:", |
1353 | tx->tx_power.ant_b); | 1342 | tx->tx_power.ant_b); |
1354 | if ((priv->hw_params.valid_tx_ant & ANT_C) && | 1343 | if ((priv->eeprom_data->valid_tx_ant & ANT_C) && |
1355 | tx->tx_power.ant_c) | 1344 | tx->tx_power.ant_c) |
1356 | pos += scnprintf(buf + pos, bufsz - pos, | 1345 | pos += scnprintf(buf + pos, bufsz - pos, |
1357 | fmt_hex, "antenna C:", | 1346 | fmt_hex, "antenna C:", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 70062379d0ec..89f2e1040e7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
@@ -24,8 +24,8 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | /* | 26 | /* |
27 | * Please use this file (iwl-dev.h) for driver implementation definitions. | 27 | * Please use this file (dev.h) for driver implementation definitions. |
28 | * Please use iwl-commands.h for uCode API definitions. | 28 | * Please use commands.h for uCode API definitions. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #ifndef __iwl_dev_h__ | 31 | #ifndef __iwl_dev_h__ |
@@ -39,17 +39,18 @@ | |||
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | 40 | ||
41 | #include "iwl-fw.h" | 41 | #include "iwl-fw.h" |
42 | #include "iwl-eeprom.h" | 42 | #include "iwl-eeprom-parse.h" |
43 | #include "iwl-csr.h" | 43 | #include "iwl-csr.h" |
44 | #include "iwl-debug.h" | 44 | #include "iwl-debug.h" |
45 | #include "iwl-agn-hw.h" | 45 | #include "iwl-agn-hw.h" |
46 | #include "iwl-led.h" | ||
47 | #include "iwl-power.h" | ||
48 | #include "iwl-agn-rs.h" | ||
49 | #include "iwl-agn-tt.h" | ||
50 | #include "iwl-trans.h" | ||
51 | #include "iwl-op-mode.h" | 46 | #include "iwl-op-mode.h" |
52 | #include "iwl-notif-wait.h" | 47 | #include "iwl-notif-wait.h" |
48 | #include "iwl-trans.h" | ||
49 | |||
50 | #include "led.h" | ||
51 | #include "power.h" | ||
52 | #include "rs.h" | ||
53 | #include "tt.h" | ||
53 | 54 | ||
54 | /* CT-KILL constants */ | 55 | /* CT-KILL constants */ |
55 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 56 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
@@ -88,33 +89,6 @@ | |||
88 | #define IWL_NUM_SCAN_RATES (2) | 89 | #define IWL_NUM_SCAN_RATES (2) |
89 | 90 | ||
90 | /* | 91 | /* |
91 | * One for each channel, holds all channel setup data | ||
92 | * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant | ||
93 | * with one another! | ||
94 | */ | ||
95 | struct iwl_channel_info { | ||
96 | struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ | ||
97 | struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for | ||
98 | * HT40 channel */ | ||
99 | |||
100 | u8 channel; /* channel number */ | ||
101 | u8 flags; /* flags copied from EEPROM */ | ||
102 | s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
103 | s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */ | ||
104 | s8 min_power; /* always 0 */ | ||
105 | s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ | ||
106 | |||
107 | u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ | ||
108 | u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ | ||
109 | enum ieee80211_band band; | ||
110 | |||
111 | /* HT40 channel info */ | ||
112 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
113 | u8 ht40_flags; /* flags copied from EEPROM */ | ||
114 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ | ||
115 | }; | ||
116 | |||
117 | /* | ||
118 | * Minimum number of queues. MAX_NUM is defined in hw specific files. | 92 | * Minimum number of queues. MAX_NUM is defined in hw specific files. |
119 | * Set the minimum to accommodate | 93 | * Set the minimum to accommodate |
120 | * - 4 standard TX queues | 94 | * - 4 standard TX queues |
@@ -153,29 +127,6 @@ union iwl_ht_rate_supp { | |||
153 | }; | 127 | }; |
154 | }; | 128 | }; |
155 | 129 | ||
156 | #define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) | ||
157 | #define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) | ||
158 | #define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) | ||
159 | #define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) | ||
160 | #define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K | ||
161 | #define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K | ||
162 | #define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K | ||
163 | |||
164 | /* | ||
165 | * Maximal MPDU density for TX aggregation | ||
166 | * 4 - 2us density | ||
167 | * 5 - 4us density | ||
168 | * 6 - 8us density | ||
169 | * 7 - 16us density | ||
170 | */ | ||
171 | #define CFG_HT_MPDU_DENSITY_2USEC (0x4) | ||
172 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | ||
173 | #define CFG_HT_MPDU_DENSITY_8USEC (0x6) | ||
174 | #define CFG_HT_MPDU_DENSITY_16USEC (0x7) | ||
175 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | ||
176 | #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC | ||
177 | #define CFG_HT_MPDU_DENSITY_MIN (0x1) | ||
178 | |||
179 | struct iwl_ht_config { | 130 | struct iwl_ht_config { |
180 | bool single_chain_sufficient; | 131 | bool single_chain_sufficient; |
181 | enum ieee80211_smps_mode smps; /* current smps mode */ | 132 | enum ieee80211_smps_mode smps; /* current smps mode */ |
@@ -445,23 +396,6 @@ enum { | |||
445 | MEASUREMENT_ACTIVE = (1 << 1), | 396 | MEASUREMENT_ACTIVE = (1 << 1), |
446 | }; | 397 | }; |
447 | 398 | ||
448 | enum iwl_nvm_type { | ||
449 | NVM_DEVICE_TYPE_EEPROM = 0, | ||
450 | NVM_DEVICE_TYPE_OTP, | ||
451 | }; | ||
452 | |||
453 | /* | ||
454 | * Two types of OTP memory access modes | ||
455 | * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, | ||
456 | * based on physical memory addressing | ||
457 | * IWL_OTP_ACCESS_RELATIVE - relative address mode, | ||
458 | * based on logical memory addressing | ||
459 | */ | ||
460 | enum iwl_access_mode { | ||
461 | IWL_OTP_ACCESS_ABSOLUTE, | ||
462 | IWL_OTP_ACCESS_RELATIVE, | ||
463 | }; | ||
464 | |||
465 | /* reply_tx_statistics (for _agn devices) */ | 399 | /* reply_tx_statistics (for _agn devices) */ |
466 | struct reply_tx_error_statistics { | 400 | struct reply_tx_error_statistics { |
467 | u32 pp_delay; | 401 | u32 pp_delay; |
@@ -632,9 +566,6 @@ enum iwl_scan_type { | |||
632 | * | 566 | * |
633 | * @tx_chains_num: Number of TX chains | 567 | * @tx_chains_num: Number of TX chains |
634 | * @rx_chains_num: Number of RX chains | 568 | * @rx_chains_num: Number of RX chains |
635 | * @valid_tx_ant: usable antennas for TX | ||
636 | * @valid_rx_ant: usable antennas for RX | ||
637 | * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) | ||
638 | * @sku: sku read from EEPROM | 569 | * @sku: sku read from EEPROM |
639 | * @ct_kill_threshold: temperature threshold - in hw dependent unit | 570 | * @ct_kill_threshold: temperature threshold - in hw dependent unit |
640 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | 571 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit |
@@ -645,9 +576,6 @@ enum iwl_scan_type { | |||
645 | struct iwl_hw_params { | 576 | struct iwl_hw_params { |
646 | u8 tx_chains_num; | 577 | u8 tx_chains_num; |
647 | u8 rx_chains_num; | 578 | u8 rx_chains_num; |
648 | u8 valid_tx_ant; | ||
649 | u8 valid_rx_ant; | ||
650 | u8 ht40_channel; | ||
651 | bool use_rts_for_aggregation; | 579 | bool use_rts_for_aggregation; |
652 | u16 sku; | 580 | u16 sku; |
653 | u32 ct_kill_threshold; | 581 | u32 ct_kill_threshold; |
@@ -664,9 +592,6 @@ struct iwl_lib_ops { | |||
664 | /* device specific configuration */ | 592 | /* device specific configuration */ |
665 | void (*nic_config)(struct iwl_priv *priv); | 593 | void (*nic_config)(struct iwl_priv *priv); |
666 | 594 | ||
667 | /* eeprom operations (as defined in iwl-eeprom.h) */ | ||
668 | struct iwl_eeprom_ops eeprom_ops; | ||
669 | |||
670 | /* temperature */ | 595 | /* temperature */ |
671 | void (*temperature)(struct iwl_priv *priv); | 596 | void (*temperature)(struct iwl_priv *priv); |
672 | }; | 597 | }; |
@@ -735,8 +660,6 @@ struct iwl_priv { | |||
735 | 660 | ||
736 | /* ieee device used by generic ieee processing code */ | 661 | /* ieee device used by generic ieee processing code */ |
737 | struct ieee80211_hw *hw; | 662 | struct ieee80211_hw *hw; |
738 | struct ieee80211_channel *ieee_channels; | ||
739 | struct ieee80211_rate *ieee_rates; | ||
740 | 663 | ||
741 | struct list_head calib_results; | 664 | struct list_head calib_results; |
742 | 665 | ||
@@ -755,8 +678,6 @@ struct iwl_priv { | |||
755 | 678 | ||
756 | struct iwl_notif_wait_data notif_wait; | 679 | struct iwl_notif_wait_data notif_wait; |
757 | 680 | ||
758 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
759 | |||
760 | /* spectrum measurement report caching */ | 681 | /* spectrum measurement report caching */ |
761 | struct iwl_spectrum_notification measure_report; | 682 | struct iwl_spectrum_notification measure_report; |
762 | u8 measurement_status; | 683 | u8 measurement_status; |
@@ -787,11 +708,6 @@ struct iwl_priv { | |||
787 | bool ucode_loaded; | 708 | bool ucode_loaded; |
788 | bool init_ucode_run; /* Don't run init uCode again */ | 709 | bool init_ucode_run; /* Don't run init uCode again */ |
789 | 710 | ||
790 | /* we allocate array of iwl_channel_info for NIC's valid channels. | ||
791 | * Access via channel # using indirect index array */ | ||
792 | struct iwl_channel_info *channel_info; /* channel info array */ | ||
793 | u8 channel_count; /* # of channels */ | ||
794 | |||
795 | u8 plcp_delta_threshold; | 711 | u8 plcp_delta_threshold; |
796 | 712 | ||
797 | /* thermal calibration */ | 713 | /* thermal calibration */ |
@@ -846,6 +762,7 @@ struct iwl_priv { | |||
846 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; | 762 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; |
847 | unsigned long ucode_key_table; | 763 | unsigned long ucode_key_table; |
848 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | 764 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; |
765 | atomic_t num_aux_in_flight; | ||
849 | 766 | ||
850 | u8 mac80211_registered; | 767 | u8 mac80211_registered; |
851 | 768 | ||
@@ -950,10 +867,8 @@ struct iwl_priv { | |||
950 | 867 | ||
951 | struct delayed_work scan_check; | 868 | struct delayed_work scan_check; |
952 | 869 | ||
953 | /* TX Power */ | 870 | /* TX Power settings */ |
954 | s8 tx_power_user_lmt; | 871 | s8 tx_power_user_lmt; |
955 | s8 tx_power_device_lmt; | ||
956 | s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ | ||
957 | s8 tx_power_next; | 872 | s8 tx_power_next; |
958 | 873 | ||
959 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 874 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -964,9 +879,10 @@ struct iwl_priv { | |||
964 | void *wowlan_sram; | 879 | void *wowlan_sram; |
965 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 880 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
966 | 881 | ||
967 | /* eeprom -- this is in the card's little endian byte order */ | 882 | struct iwl_eeprom_data *eeprom_data; |
968 | u8 *eeprom; | 883 | /* eeprom blob for debugfs/testmode */ |
969 | enum iwl_nvm_type nvm_device_type; | 884 | u8 *eeprom_blob; |
885 | size_t eeprom_blob_size; | ||
970 | 886 | ||
971 | struct work_struct txpower_work; | 887 | struct work_struct txpower_work; |
972 | u32 calib_disabled; | 888 | u32 calib_disabled; |
@@ -1001,8 +917,6 @@ struct iwl_priv { | |||
1001 | enum iwl_ucode_type cur_ucode; | 917 | enum iwl_ucode_type cur_ucode; |
1002 | }; /*iwl_priv */ | 918 | }; /*iwl_priv */ |
1003 | 919 | ||
1004 | extern struct kmem_cache *iwl_tx_cmd_pool; | ||
1005 | |||
1006 | static inline struct iwl_rxon_context * | 920 | static inline struct iwl_rxon_context * |
1007 | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | 921 | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) |
1008 | { | 922 | { |
@@ -1036,36 +950,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv) | |||
1036 | return false; | 950 | return false; |
1037 | } | 951 | } |
1038 | 952 | ||
1039 | static inline int is_channel_valid(const struct iwl_channel_info *ch_info) | ||
1040 | { | ||
1041 | if (ch_info == NULL) | ||
1042 | return 0; | ||
1043 | return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; | ||
1044 | } | ||
1045 | |||
1046 | static inline int is_channel_radar(const struct iwl_channel_info *ch_info) | ||
1047 | { | ||
1048 | return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; | ||
1049 | } | ||
1050 | |||
1051 | static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) | ||
1052 | { | ||
1053 | return ch_info->band == IEEE80211_BAND_5GHZ; | ||
1054 | } | ||
1055 | |||
1056 | static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) | ||
1057 | { | ||
1058 | return ch_info->band == IEEE80211_BAND_2GHZ; | ||
1059 | } | ||
1060 | |||
1061 | static inline int is_channel_passive(const struct iwl_channel_info *ch) | ||
1062 | { | ||
1063 | return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; | ||
1064 | } | ||
1065 | |||
1066 | static inline int is_channel_ibss(const struct iwl_channel_info *ch) | ||
1067 | { | ||
1068 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | ||
1069 | } | ||
1070 | |||
1071 | #endif /* __iwl_dev_h__ */ | 953 | #endif /* __iwl_dev_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 48533b3a0f9a..0521a6be09d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -27,11 +27,14 @@ | |||
27 | /* | 27 | /* |
28 | * DVM device-specific data & functions | 28 | * DVM device-specific data & functions |
29 | */ | 29 | */ |
30 | #include "iwl-agn.h" | ||
31 | #include "iwl-dev.h" | ||
32 | #include "iwl-commands.h" | ||
33 | #include "iwl-io.h" | 30 | #include "iwl-io.h" |
34 | #include "iwl-prph.h" | 31 | #include "iwl-prph.h" |
32 | #include "iwl-eeprom-parse.h" | ||
33 | |||
34 | #include "agn.h" | ||
35 | #include "dev.h" | ||
36 | #include "commands.h" | ||
37 | |||
35 | 38 | ||
36 | /* | 39 | /* |
37 | * 1000 series | 40 | * 1000 series |
@@ -58,11 +61,6 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
58 | /* NIC configuration for 1000 series */ | 61 | /* NIC configuration for 1000 series */ |
59 | static void iwl1000_nic_config(struct iwl_priv *priv) | 62 | static void iwl1000_nic_config(struct iwl_priv *priv) |
60 | { | 63 | { |
61 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
62 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
63 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
64 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
65 | |||
66 | /* Setting digital SVR for 1000 card to 1.32V */ | 64 | /* Setting digital SVR for 1000 card to 1.32V */ |
67 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | 65 | /* locking is acquired in iwl_set_bits_mask_prph() function */ |
68 | iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, | 66 | iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, |
@@ -170,16 +168,6 @@ static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { | |||
170 | 168 | ||
171 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | 169 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) |
172 | { | 170 | { |
173 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
174 | |||
175 | priv->hw_params.tx_chains_num = | ||
176 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
177 | if (priv->cfg->rx_with_siso_diversity) | ||
178 | priv->hw_params.rx_chains_num = 1; | ||
179 | else | ||
180 | priv->hw_params.rx_chains_num = | ||
181 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
182 | |||
183 | iwl1000_set_ct_threshold(priv); | 171 | iwl1000_set_ct_threshold(priv); |
184 | 172 | ||
185 | /* Set initial sensitivity parameters */ | 173 | /* Set initial sensitivity parameters */ |
@@ -189,17 +177,6 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
189 | struct iwl_lib_ops iwl1000_lib = { | 177 | struct iwl_lib_ops iwl1000_lib = { |
190 | .set_hw_params = iwl1000_hw_set_hw_params, | 178 | .set_hw_params = iwl1000_hw_set_hw_params, |
191 | .nic_config = iwl1000_nic_config, | 179 | .nic_config = iwl1000_nic_config, |
192 | .eeprom_ops = { | ||
193 | .regulatory_bands = { | ||
194 | EEPROM_REG_BAND_1_CHANNELS, | ||
195 | EEPROM_REG_BAND_2_CHANNELS, | ||
196 | EEPROM_REG_BAND_3_CHANNELS, | ||
197 | EEPROM_REG_BAND_4_CHANNELS, | ||
198 | EEPROM_REG_BAND_5_CHANNELS, | ||
199 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
200 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
201 | }, | ||
202 | }, | ||
203 | .temperature = iwlagn_temperature, | 180 | .temperature = iwlagn_temperature, |
204 | }; | 181 | }; |
205 | 182 | ||
@@ -219,8 +196,6 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | |||
219 | /* NIC configuration for 2000 series */ | 196 | /* NIC configuration for 2000 series */ |
220 | static void iwl2000_nic_config(struct iwl_priv *priv) | 197 | static void iwl2000_nic_config(struct iwl_priv *priv) |
221 | { | 198 | { |
222 | iwl_rf_config(priv); | ||
223 | |||
224 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 199 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
225 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | 200 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); |
226 | } | 201 | } |
@@ -251,16 +226,6 @@ static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | |||
251 | 226 | ||
252 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | 227 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) |
253 | { | 228 | { |
254 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
255 | |||
256 | priv->hw_params.tx_chains_num = | ||
257 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
258 | if (priv->cfg->rx_with_siso_diversity) | ||
259 | priv->hw_params.rx_chains_num = 1; | ||
260 | else | ||
261 | priv->hw_params.rx_chains_num = | ||
262 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
263 | |||
264 | iwl2000_set_ct_threshold(priv); | 229 | iwl2000_set_ct_threshold(priv); |
265 | 230 | ||
266 | /* Set initial sensitivity parameters */ | 231 | /* Set initial sensitivity parameters */ |
@@ -270,36 +235,12 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
270 | struct iwl_lib_ops iwl2000_lib = { | 235 | struct iwl_lib_ops iwl2000_lib = { |
271 | .set_hw_params = iwl2000_hw_set_hw_params, | 236 | .set_hw_params = iwl2000_hw_set_hw_params, |
272 | .nic_config = iwl2000_nic_config, | 237 | .nic_config = iwl2000_nic_config, |
273 | .eeprom_ops = { | ||
274 | .regulatory_bands = { | ||
275 | EEPROM_REG_BAND_1_CHANNELS, | ||
276 | EEPROM_REG_BAND_2_CHANNELS, | ||
277 | EEPROM_REG_BAND_3_CHANNELS, | ||
278 | EEPROM_REG_BAND_4_CHANNELS, | ||
279 | EEPROM_REG_BAND_5_CHANNELS, | ||
280 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
281 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
282 | }, | ||
283 | .enhanced_txpower = true, | ||
284 | }, | ||
285 | .temperature = iwlagn_temperature, | 238 | .temperature = iwlagn_temperature, |
286 | }; | 239 | }; |
287 | 240 | ||
288 | struct iwl_lib_ops iwl2030_lib = { | 241 | struct iwl_lib_ops iwl2030_lib = { |
289 | .set_hw_params = iwl2000_hw_set_hw_params, | 242 | .set_hw_params = iwl2000_hw_set_hw_params, |
290 | .nic_config = iwl2000_nic_config, | 243 | .nic_config = iwl2000_nic_config, |
291 | .eeprom_ops = { | ||
292 | .regulatory_bands = { | ||
293 | EEPROM_REG_BAND_1_CHANNELS, | ||
294 | EEPROM_REG_BAND_2_CHANNELS, | ||
295 | EEPROM_REG_BAND_3_CHANNELS, | ||
296 | EEPROM_REG_BAND_4_CHANNELS, | ||
297 | EEPROM_REG_BAND_5_CHANNELS, | ||
298 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
299 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
300 | }, | ||
301 | .enhanced_txpower = true, | ||
302 | }, | ||
303 | .temperature = iwlagn_temperature, | 244 | .temperature = iwlagn_temperature, |
304 | }; | 245 | }; |
305 | 246 | ||
@@ -311,8 +252,6 @@ struct iwl_lib_ops iwl2030_lib = { | |||
311 | /* NIC configuration for 5000 series */ | 252 | /* NIC configuration for 5000 series */ |
312 | static void iwl5000_nic_config(struct iwl_priv *priv) | 253 | static void iwl5000_nic_config(struct iwl_priv *priv) |
313 | { | 254 | { |
314 | iwl_rf_config(priv); | ||
315 | |||
316 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | 255 | /* W/A : NIC is stuck in a reset state after Early PCIe power off |
317 | * (PCIe power is lost before PERST# is asserted), | 256 | * (PCIe power is lost before PERST# is asserted), |
318 | * causing ME FW to lose ownership and not being able to obtain it back. | 257 | * causing ME FW to lose ownership and not being able to obtain it back. |
@@ -376,11 +315,9 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
376 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 315 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) |
377 | { | 316 | { |
378 | u16 temperature, voltage; | 317 | u16 temperature, voltage; |
379 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, | ||
380 | EEPROM_KELVIN_TEMPERATURE); | ||
381 | 318 | ||
382 | temperature = le16_to_cpu(temp_calib[0]); | 319 | temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature); |
383 | voltage = le16_to_cpu(temp_calib[1]); | 320 | voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage); |
384 | 321 | ||
385 | /* offset = temp - volt / coeff */ | 322 | /* offset = temp - volt / coeff */ |
386 | return (s32)(temperature - | 323 | return (s32)(temperature - |
@@ -404,14 +341,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
404 | 341 | ||
405 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | 342 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
406 | { | 343 | { |
407 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
408 | BIT(IEEE80211_BAND_5GHZ); | ||
409 | |||
410 | priv->hw_params.tx_chains_num = | ||
411 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
412 | priv->hw_params.rx_chains_num = | ||
413 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
414 | |||
415 | iwl5000_set_ct_threshold(priv); | 344 | iwl5000_set_ct_threshold(priv); |
416 | 345 | ||
417 | /* Set initial sensitivity parameters */ | 346 | /* Set initial sensitivity parameters */ |
@@ -420,14 +349,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
420 | 349 | ||
421 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | 350 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) |
422 | { | 351 | { |
423 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
424 | BIT(IEEE80211_BAND_5GHZ); | ||
425 | |||
426 | priv->hw_params.tx_chains_num = | ||
427 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
428 | priv->hw_params.rx_chains_num = | ||
429 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
430 | |||
431 | iwl5150_set_ct_threshold(priv); | 352 | iwl5150_set_ct_threshold(priv); |
432 | 353 | ||
433 | /* Set initial sensitivity parameters */ | 354 | /* Set initial sensitivity parameters */ |
@@ -455,7 +376,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
455 | */ | 376 | */ |
456 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 377 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
457 | struct iwl5000_channel_switch_cmd cmd; | 378 | struct iwl5000_channel_switch_cmd cmd; |
458 | const struct iwl_channel_info *ch_info; | ||
459 | u32 switch_time_in_usec, ucode_switch_time; | 379 | u32 switch_time_in_usec, ucode_switch_time; |
460 | u16 ch; | 380 | u16 ch; |
461 | u32 tsf_low; | 381 | u32 tsf_low; |
@@ -505,14 +425,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
505 | } | 425 | } |
506 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 426 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", |
507 | cmd.switch_time); | 427 | cmd.switch_time); |
508 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | 428 | cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; |
509 | if (ch_info) | ||
510 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
511 | else { | ||
512 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
513 | ctx->active.channel, ch); | ||
514 | return -EFAULT; | ||
515 | } | ||
516 | 429 | ||
517 | return iwl_dvm_send_cmd(priv, &hcmd); | 430 | return iwl_dvm_send_cmd(priv, &hcmd); |
518 | } | 431 | } |
@@ -521,17 +434,6 @@ struct iwl_lib_ops iwl5000_lib = { | |||
521 | .set_hw_params = iwl5000_hw_set_hw_params, | 434 | .set_hw_params = iwl5000_hw_set_hw_params, |
522 | .set_channel_switch = iwl5000_hw_channel_switch, | 435 | .set_channel_switch = iwl5000_hw_channel_switch, |
523 | .nic_config = iwl5000_nic_config, | 436 | .nic_config = iwl5000_nic_config, |
524 | .eeprom_ops = { | ||
525 | .regulatory_bands = { | ||
526 | EEPROM_REG_BAND_1_CHANNELS, | ||
527 | EEPROM_REG_BAND_2_CHANNELS, | ||
528 | EEPROM_REG_BAND_3_CHANNELS, | ||
529 | EEPROM_REG_BAND_4_CHANNELS, | ||
530 | EEPROM_REG_BAND_5_CHANNELS, | ||
531 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
532 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
533 | }, | ||
534 | }, | ||
535 | .temperature = iwlagn_temperature, | 437 | .temperature = iwlagn_temperature, |
536 | }; | 438 | }; |
537 | 439 | ||
@@ -539,17 +441,6 @@ struct iwl_lib_ops iwl5150_lib = { | |||
539 | .set_hw_params = iwl5150_hw_set_hw_params, | 441 | .set_hw_params = iwl5150_hw_set_hw_params, |
540 | .set_channel_switch = iwl5000_hw_channel_switch, | 442 | .set_channel_switch = iwl5000_hw_channel_switch, |
541 | .nic_config = iwl5000_nic_config, | 443 | .nic_config = iwl5000_nic_config, |
542 | .eeprom_ops = { | ||
543 | .regulatory_bands = { | ||
544 | EEPROM_REG_BAND_1_CHANNELS, | ||
545 | EEPROM_REG_BAND_2_CHANNELS, | ||
546 | EEPROM_REG_BAND_3_CHANNELS, | ||
547 | EEPROM_REG_BAND_4_CHANNELS, | ||
548 | EEPROM_REG_BAND_5_CHANNELS, | ||
549 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
550 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
551 | }, | ||
552 | }, | ||
553 | .temperature = iwl5150_temperature, | 444 | .temperature = iwl5150_temperature, |
554 | }; | 445 | }; |
555 | 446 | ||
@@ -570,8 +461,6 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
570 | /* NIC configuration for 6000 series */ | 461 | /* NIC configuration for 6000 series */ |
571 | static void iwl6000_nic_config(struct iwl_priv *priv) | 462 | static void iwl6000_nic_config(struct iwl_priv *priv) |
572 | { | 463 | { |
573 | iwl_rf_config(priv); | ||
574 | |||
575 | switch (priv->cfg->device_family) { | 464 | switch (priv->cfg->device_family) { |
576 | case IWL_DEVICE_FAMILY_6005: | 465 | case IWL_DEVICE_FAMILY_6005: |
577 | case IWL_DEVICE_FAMILY_6030: | 466 | case IWL_DEVICE_FAMILY_6030: |
@@ -584,13 +473,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
584 | break; | 473 | break; |
585 | case IWL_DEVICE_FAMILY_6050: | 474 | case IWL_DEVICE_FAMILY_6050: |
586 | /* Indicate calibration version to uCode. */ | 475 | /* Indicate calibration version to uCode. */ |
587 | if (iwl_eeprom_calib_version(priv) >= 6) | 476 | if (priv->eeprom_data->calib_version >= 6) |
588 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 477 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
589 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 478 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
590 | break; | 479 | break; |
591 | case IWL_DEVICE_FAMILY_6150: | 480 | case IWL_DEVICE_FAMILY_6150: |
592 | /* Indicate calibration version to uCode. */ | 481 | /* Indicate calibration version to uCode. */ |
593 | if (iwl_eeprom_calib_version(priv) >= 6) | 482 | if (priv->eeprom_data->calib_version >= 6) |
594 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 483 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
595 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 484 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
596 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 485 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
@@ -627,17 +516,6 @@ static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
627 | 516 | ||
628 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 517 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
629 | { | 518 | { |
630 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
631 | BIT(IEEE80211_BAND_5GHZ); | ||
632 | |||
633 | priv->hw_params.tx_chains_num = | ||
634 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
635 | if (priv->cfg->rx_with_siso_diversity) | ||
636 | priv->hw_params.rx_chains_num = 1; | ||
637 | else | ||
638 | priv->hw_params.rx_chains_num = | ||
639 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
640 | |||
641 | iwl6000_set_ct_threshold(priv); | 519 | iwl6000_set_ct_threshold(priv); |
642 | 520 | ||
643 | /* Set initial sensitivity parameters */ | 521 | /* Set initial sensitivity parameters */ |
@@ -654,7 +532,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
654 | */ | 532 | */ |
655 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 533 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
656 | struct iwl6000_channel_switch_cmd cmd; | 534 | struct iwl6000_channel_switch_cmd cmd; |
657 | const struct iwl_channel_info *ch_info; | ||
658 | u32 switch_time_in_usec, ucode_switch_time; | 535 | u32 switch_time_in_usec, ucode_switch_time; |
659 | u16 ch; | 536 | u16 ch; |
660 | u32 tsf_low; | 537 | u32 tsf_low; |
@@ -704,14 +581,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
704 | } | 581 | } |
705 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 582 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", |
706 | cmd.switch_time); | 583 | cmd.switch_time); |
707 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | 584 | cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; |
708 | if (ch_info) | ||
709 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
710 | else { | ||
711 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
712 | ctx->active.channel, ch); | ||
713 | return -EFAULT; | ||
714 | } | ||
715 | 585 | ||
716 | return iwl_dvm_send_cmd(priv, &hcmd); | 586 | return iwl_dvm_send_cmd(priv, &hcmd); |
717 | } | 587 | } |
@@ -720,18 +590,6 @@ struct iwl_lib_ops iwl6000_lib = { | |||
720 | .set_hw_params = iwl6000_hw_set_hw_params, | 590 | .set_hw_params = iwl6000_hw_set_hw_params, |
721 | .set_channel_switch = iwl6000_hw_channel_switch, | 591 | .set_channel_switch = iwl6000_hw_channel_switch, |
722 | .nic_config = iwl6000_nic_config, | 592 | .nic_config = iwl6000_nic_config, |
723 | .eeprom_ops = { | ||
724 | .regulatory_bands = { | ||
725 | EEPROM_REG_BAND_1_CHANNELS, | ||
726 | EEPROM_REG_BAND_2_CHANNELS, | ||
727 | EEPROM_REG_BAND_3_CHANNELS, | ||
728 | EEPROM_REG_BAND_4_CHANNELS, | ||
729 | EEPROM_REG_BAND_5_CHANNELS, | ||
730 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
731 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
732 | }, | ||
733 | .enhanced_txpower = true, | ||
734 | }, | ||
735 | .temperature = iwlagn_temperature, | 593 | .temperature = iwlagn_temperature, |
736 | }; | 594 | }; |
737 | 595 | ||
@@ -739,17 +597,5 @@ struct iwl_lib_ops iwl6030_lib = { | |||
739 | .set_hw_params = iwl6000_hw_set_hw_params, | 597 | .set_hw_params = iwl6000_hw_set_hw_params, |
740 | .set_channel_switch = iwl6000_hw_channel_switch, | 598 | .set_channel_switch = iwl6000_hw_channel_switch, |
741 | .nic_config = iwl6000_nic_config, | 599 | .nic_config = iwl6000_nic_config, |
742 | .eeprom_ops = { | ||
743 | .regulatory_bands = { | ||
744 | EEPROM_REG_BAND_1_CHANNELS, | ||
745 | EEPROM_REG_BAND_2_CHANNELS, | ||
746 | EEPROM_REG_BAND_3_CHANNELS, | ||
747 | EEPROM_REG_BAND_4_CHANNELS, | ||
748 | EEPROM_REG_BAND_5_CHANNELS, | ||
749 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
750 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
751 | }, | ||
752 | .enhanced_txpower = true, | ||
753 | }, | ||
754 | .temperature = iwlagn_temperature, | 600 | .temperature = iwlagn_temperature, |
755 | }; | 601 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/dvm/led.c index 47000419f916..bf479f709091 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/dvm/led.c | |||
@@ -34,12 +34,11 @@ | |||
34 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
35 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
36 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
37 | |||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
41 | #include "iwl-trans.h" | 38 | #include "iwl-trans.h" |
42 | #include "iwl-modparams.h" | 39 | #include "iwl-modparams.h" |
40 | #include "dev.h" | ||
41 | #include "agn.h" | ||
43 | 42 | ||
44 | /* Throughput OFF time(ms) ON time (ms) | 43 | /* Throughput OFF time(ms) ON time (ms) |
45 | * >300 25 25 | 44 | * >300 25 25 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/dvm/led.h index b02a853103d3..b02a853103d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/dvm/led.h | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index e55ec6c8a920..cb1ca7a25dd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -33,13 +33,14 @@ | |||
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
35 | 35 | ||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
38 | #include "iwl-agn-hw.h" | 37 | #include "iwl-agn-hw.h" |
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-trans.h" | 38 | #include "iwl-trans.h" |
41 | #include "iwl-modparams.h" | 39 | #include "iwl-modparams.h" |
42 | 40 | ||
41 | #include "dev.h" | ||
42 | #include "agn.h" | ||
43 | |||
43 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | 44 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) |
44 | { | 45 | { |
45 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | 46 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && |
@@ -58,8 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
58 | /* half dBm need to multiply */ | 59 | /* half dBm need to multiply */ |
59 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 60 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); |
60 | 61 | ||
61 | if (priv->tx_power_lmt_in_half_dbm && | 62 | if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) { |
62 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
63 | /* | 63 | /* |
64 | * For the newer devices which using enhanced/extend tx power | 64 | * For the newer devices which using enhanced/extend tx power |
65 | * table in EEPROM, the format is in half dBm. driver need to | 65 | * table in EEPROM, the format is in half dBm. driver need to |
@@ -71,7 +71,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
71 | * "tx_power_user_lmt" is higher than EEPROM value (in | 71 | * "tx_power_user_lmt" is higher than EEPROM value (in |
72 | * half-dBm format), lower the tx power based on EEPROM | 72 | * half-dBm format), lower the tx power based on EEPROM |
73 | */ | 73 | */ |
74 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | 74 | tx_power_cmd.global_lmt = |
75 | priv->eeprom_data->max_tx_pwr_half_dbm; | ||
75 | } | 76 | } |
76 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; | 77 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; |
77 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; | 78 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; |
@@ -617,6 +618,11 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | |||
617 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 618 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
618 | int ave_rssi; | 619 | int ave_rssi; |
619 | 620 | ||
621 | if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) { | ||
622 | IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n"); | ||
623 | return false; | ||
624 | } | ||
625 | |||
620 | ave_rssi = ieee80211_ave_rssi(ctx->vif); | 626 | ave_rssi = ieee80211_ave_rssi(ctx->vif); |
621 | if (!ave_rssi) { | 627 | if (!ave_rssi) { |
622 | /* no rssi data, no changes to reduce tx power */ | 628 | /* no rssi data, no changes to reduce tx power */ |
@@ -818,7 +824,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
818 | if (priv->chain_noise_data.active_chains) | 824 | if (priv->chain_noise_data.active_chains) |
819 | active_chains = priv->chain_noise_data.active_chains; | 825 | active_chains = priv->chain_noise_data.active_chains; |
820 | else | 826 | else |
821 | active_chains = priv->hw_params.valid_rx_ant; | 827 | active_chains = priv->eeprom_data->valid_rx_ant; |
822 | 828 | ||
823 | if (priv->cfg->bt_params && | 829 | if (priv->cfg->bt_params && |
824 | priv->cfg->bt_params->advanced_bt_coexist && | 830 | priv->cfg->bt_params->advanced_bt_coexist && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 3ee23134c02b..599e8b41f5a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -38,19 +38,20 @@ | |||
38 | #include <linux/etherdevice.h> | 38 | #include <linux/etherdevice.h> |
39 | #include <linux/if_arp.h> | 39 | #include <linux/if_arp.h> |
40 | 40 | ||
41 | #include <net/ieee80211_radiotap.h> | ||
41 | #include <net/mac80211.h> | 42 | #include <net/mac80211.h> |
42 | 43 | ||
43 | #include <asm/div64.h> | 44 | #include <asm/div64.h> |
44 | 45 | ||
45 | #include "iwl-eeprom.h" | ||
46 | #include "iwl-dev.h" | ||
47 | #include "iwl-io.h" | 46 | #include "iwl-io.h" |
48 | #include "iwl-agn-calib.h" | ||
49 | #include "iwl-agn.h" | ||
50 | #include "iwl-trans.h" | 47 | #include "iwl-trans.h" |
51 | #include "iwl-op-mode.h" | 48 | #include "iwl-op-mode.h" |
52 | #include "iwl-modparams.h" | 49 | #include "iwl-modparams.h" |
53 | 50 | ||
51 | #include "dev.h" | ||
52 | #include "calib.h" | ||
53 | #include "agn.h" | ||
54 | |||
54 | /***************************************************************************** | 55 | /***************************************************************************** |
55 | * | 56 | * |
56 | * mac80211 entry point functions | 57 | * mac80211 entry point functions |
@@ -154,6 +155,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
154 | IEEE80211_HW_SCAN_WHILE_IDLE; | 155 | IEEE80211_HW_SCAN_WHILE_IDLE; |
155 | 156 | ||
156 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 157 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; |
158 | hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; | ||
157 | 159 | ||
158 | /* | 160 | /* |
159 | * Including the following line will crash some AP's. This | 161 | * Including the following line will crash some AP's. This |
@@ -237,12 +239,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
237 | 239 | ||
238 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 240 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
239 | 241 | ||
240 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | 242 | if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
241 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 243 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
242 | &priv->bands[IEEE80211_BAND_2GHZ]; | 244 | &priv->eeprom_data->bands[IEEE80211_BAND_2GHZ]; |
243 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | 245 | if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels) |
244 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 246 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
245 | &priv->bands[IEEE80211_BAND_5GHZ]; | 247 | &priv->eeprom_data->bands[IEEE80211_BAND_5GHZ]; |
246 | 248 | ||
247 | hw->wiphy->hw_version = priv->trans->hw_id; | 249 | hw->wiphy->hw_version = priv->trans->hw_id; |
248 | 250 | ||
@@ -341,7 +343,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) | |||
341 | return 0; | 343 | return 0; |
342 | } | 344 | } |
343 | 345 | ||
344 | void iwlagn_mac_stop(struct ieee80211_hw *hw) | 346 | static void iwlagn_mac_stop(struct ieee80211_hw *hw) |
345 | { | 347 | { |
346 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 348 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
347 | 349 | ||
@@ -369,9 +371,9 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
369 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 371 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
370 | } | 372 | } |
371 | 373 | ||
372 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | 374 | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, |
373 | struct ieee80211_vif *vif, | 375 | struct ieee80211_vif *vif, |
374 | struct cfg80211_gtk_rekey_data *data) | 376 | struct cfg80211_gtk_rekey_data *data) |
375 | { | 377 | { |
376 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 378 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
377 | 379 | ||
@@ -397,7 +399,8 @@ void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | |||
397 | 399 | ||
398 | #ifdef CONFIG_PM_SLEEP | 400 | #ifdef CONFIG_PM_SLEEP |
399 | 401 | ||
400 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 402 | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, |
403 | struct cfg80211_wowlan *wowlan) | ||
401 | { | 404 | { |
402 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 405 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
403 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 406 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
@@ -420,8 +423,6 @@ int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
420 | if (ret) | 423 | if (ret) |
421 | goto error; | 424 | goto error; |
422 | 425 | ||
423 | device_set_wakeup_enable(priv->trans->dev, true); | ||
424 | |||
425 | iwl_trans_wowlan_suspend(priv->trans); | 426 | iwl_trans_wowlan_suspend(priv->trans); |
426 | 427 | ||
427 | goto out; | 428 | goto out; |
@@ -488,8 +489,6 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
488 | 489 | ||
489 | priv->wowlan = false; | 490 | priv->wowlan = false; |
490 | 491 | ||
491 | device_set_wakeup_enable(priv->trans->dev, false); | ||
492 | |||
493 | iwlagn_prepare_restart(priv); | 492 | iwlagn_prepare_restart(priv); |
494 | 493 | ||
495 | memset((void *)&ctx->active, 0, sizeof(ctx->active)); | 494 | memset((void *)&ctx->active, 0, sizeof(ctx->active)); |
@@ -504,9 +503,15 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
504 | return 1; | 503 | return 1; |
505 | } | 504 | } |
506 | 505 | ||
506 | static void iwlagn_mac_set_wakeup(struct ieee80211_hw *hw, bool enabled) | ||
507 | { | ||
508 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||
509 | |||
510 | device_set_wakeup_enable(priv->trans->dev, enabled); | ||
511 | } | ||
507 | #endif | 512 | #endif |
508 | 513 | ||
509 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 514 | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
510 | { | 515 | { |
511 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 516 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
512 | 517 | ||
@@ -517,21 +522,21 @@ void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
517 | dev_kfree_skb_any(skb); | 522 | dev_kfree_skb_any(skb); |
518 | } | 523 | } |
519 | 524 | ||
520 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | 525 | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, |
521 | struct ieee80211_vif *vif, | 526 | struct ieee80211_vif *vif, |
522 | struct ieee80211_key_conf *keyconf, | 527 | struct ieee80211_key_conf *keyconf, |
523 | struct ieee80211_sta *sta, | 528 | struct ieee80211_sta *sta, |
524 | u32 iv32, u16 *phase1key) | 529 | u32 iv32, u16 *phase1key) |
525 | { | 530 | { |
526 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 531 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
527 | 532 | ||
528 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | 533 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); |
529 | } | 534 | } |
530 | 535 | ||
531 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 536 | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
532 | struct ieee80211_vif *vif, | 537 | struct ieee80211_vif *vif, |
533 | struct ieee80211_sta *sta, | 538 | struct ieee80211_sta *sta, |
534 | struct ieee80211_key_conf *key) | 539 | struct ieee80211_key_conf *key) |
535 | { | 540 | { |
536 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 541 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
537 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 542 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -631,11 +636,11 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
631 | return ret; | 636 | return ret; |
632 | } | 637 | } |
633 | 638 | ||
634 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | 639 | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |
635 | struct ieee80211_vif *vif, | 640 | struct ieee80211_vif *vif, |
636 | enum ieee80211_ampdu_mlme_action action, | 641 | enum ieee80211_ampdu_mlme_action action, |
637 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 642 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
638 | u8 buf_size) | 643 | u8 buf_size) |
639 | { | 644 | { |
640 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 645 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
641 | int ret = -EINVAL; | 646 | int ret = -EINVAL; |
@@ -662,7 +667,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
662 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | 667 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
663 | break; | 668 | break; |
664 | case IEEE80211_AMPDU_TX_START: | 669 | case IEEE80211_AMPDU_TX_START: |
665 | if (!priv->trans->ops->tx_agg_setup) | 670 | if (!priv->trans->ops->txq_enable) |
666 | break; | 671 | break; |
667 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | 672 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) |
668 | break; | 673 | break; |
@@ -757,11 +762,11 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, | |||
757 | return ret; | 762 | return ret; |
758 | } | 763 | } |
759 | 764 | ||
760 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | 765 | static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, |
761 | struct ieee80211_vif *vif, | 766 | struct ieee80211_vif *vif, |
762 | struct ieee80211_sta *sta, | 767 | struct ieee80211_sta *sta, |
763 | enum ieee80211_sta_state old_state, | 768 | enum ieee80211_sta_state old_state, |
764 | enum ieee80211_sta_state new_state) | 769 | enum ieee80211_sta_state new_state) |
765 | { | 770 | { |
766 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 771 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
767 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 772 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -840,11 +845,10 @@ int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | |||
840 | return ret; | 845 | return ret; |
841 | } | 846 | } |
842 | 847 | ||
843 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | 848 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, |
844 | struct ieee80211_channel_switch *ch_switch) | 849 | struct ieee80211_channel_switch *ch_switch) |
845 | { | 850 | { |
846 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 851 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
847 | const struct iwl_channel_info *ch_info; | ||
848 | struct ieee80211_conf *conf = &hw->conf; | 852 | struct ieee80211_conf *conf = &hw->conf; |
849 | struct ieee80211_channel *channel = ch_switch->channel; | 853 | struct ieee80211_channel *channel = ch_switch->channel; |
850 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 854 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
@@ -881,12 +885,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | |||
881 | if (le16_to_cpu(ctx->active.channel) == ch) | 885 | if (le16_to_cpu(ctx->active.channel) == ch) |
882 | goto out; | 886 | goto out; |
883 | 887 | ||
884 | ch_info = iwl_get_channel_info(priv, channel->band, ch); | ||
885 | if (!is_channel_valid(ch_info)) { | ||
886 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | ||
887 | goto out; | ||
888 | } | ||
889 | |||
890 | priv->current_ht_config.smps = conf->smps_mode; | 888 | priv->current_ht_config.smps = conf->smps_mode; |
891 | 889 | ||
892 | /* Configure HT40 channels */ | 890 | /* Configure HT40 channels */ |
@@ -935,10 +933,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | |||
935 | ieee80211_chswitch_done(ctx->vif, is_success); | 933 | ieee80211_chswitch_done(ctx->vif, is_success); |
936 | } | 934 | } |
937 | 935 | ||
938 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | 936 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, |
939 | unsigned int changed_flags, | 937 | unsigned int changed_flags, |
940 | unsigned int *total_flags, | 938 | unsigned int *total_flags, |
941 | u64 multicast) | 939 | u64 multicast) |
942 | { | 940 | { |
943 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 941 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
944 | __le32 filter_or = 0, filter_nand = 0; | 942 | __le32 filter_or = 0, filter_nand = 0; |
@@ -985,7 +983,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
985 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 983 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
986 | } | 984 | } |
987 | 985 | ||
988 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | 986 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) |
989 | { | 987 | { |
990 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 988 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
991 | 989 | ||
@@ -1112,7 +1110,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
1112 | return err; | 1110 | return err; |
1113 | } | 1111 | } |
1114 | 1112 | ||
1115 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | 1113 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) |
1116 | { | 1114 | { |
1117 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1115 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1118 | 1116 | ||
@@ -1129,8 +1127,8 @@ int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
1129 | return 0; | 1127 | return 0; |
1130 | } | 1128 | } |
1131 | 1129 | ||
1132 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | 1130 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, |
1133 | enum ieee80211_rssi_event rssi_event) | 1131 | enum ieee80211_rssi_event rssi_event) |
1134 | { | 1132 | { |
1135 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1133 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1136 | 1134 | ||
@@ -1154,8 +1152,8 @@ void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | |||
1154 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1152 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1155 | } | 1153 | } |
1156 | 1154 | ||
1157 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | 1155 | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, |
1158 | struct ieee80211_sta *sta, bool set) | 1156 | struct ieee80211_sta *sta, bool set) |
1159 | { | 1157 | { |
1160 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1158 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1161 | 1159 | ||
@@ -1164,9 +1162,9 @@ int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | |||
1164 | return 0; | 1162 | return 0; |
1165 | } | 1163 | } |
1166 | 1164 | ||
1167 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | 1165 | static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, |
1168 | struct ieee80211_vif *vif, u16 queue, | 1166 | struct ieee80211_vif *vif, u16 queue, |
1169 | const struct ieee80211_tx_queue_params *params) | 1167 | const struct ieee80211_tx_queue_params *params) |
1170 | { | 1168 | { |
1171 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1169 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1172 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1170 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -1208,7 +1206,7 @@ int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | |||
1208 | return 0; | 1206 | return 0; |
1209 | } | 1207 | } |
1210 | 1208 | ||
1211 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) | 1209 | static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) |
1212 | { | 1210 | { |
1213 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1211 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1214 | 1212 | ||
@@ -1224,7 +1222,8 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
1224 | return iwlagn_commit_rxon(priv, ctx); | 1222 | return iwlagn_commit_rxon(priv, ctx); |
1225 | } | 1223 | } |
1226 | 1224 | ||
1227 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 1225 | static int iwl_setup_interface(struct iwl_priv *priv, |
1226 | struct iwl_rxon_context *ctx) | ||
1228 | { | 1227 | { |
1229 | struct ieee80211_vif *vif = ctx->vif; | 1228 | struct ieee80211_vif *vif = ctx->vif; |
1230 | int err, ac; | 1229 | int err, ac; |
@@ -1344,9 +1343,9 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, | |||
1344 | return err; | 1343 | return err; |
1345 | } | 1344 | } |
1346 | 1345 | ||
1347 | void iwl_teardown_interface(struct iwl_priv *priv, | 1346 | static void iwl_teardown_interface(struct iwl_priv *priv, |
1348 | struct ieee80211_vif *vif, | 1347 | struct ieee80211_vif *vif, |
1349 | bool mode_change) | 1348 | bool mode_change) |
1350 | { | 1349 | { |
1351 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1350 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
1352 | 1351 | ||
@@ -1487,9 +1486,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1487 | return err; | 1486 | return err; |
1488 | } | 1487 | } |
1489 | 1488 | ||
1490 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | 1489 | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, |
1491 | struct ieee80211_vif *vif, | 1490 | struct ieee80211_vif *vif, |
1492 | struct cfg80211_scan_request *req) | 1491 | struct cfg80211_scan_request *req) |
1493 | { | 1492 | { |
1494 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1493 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1495 | int ret; | 1494 | int ret; |
@@ -1544,10 +1543,10 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1544 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); | 1543 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); |
1545 | } | 1544 | } |
1546 | 1545 | ||
1547 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | 1546 | static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, |
1548 | struct ieee80211_vif *vif, | 1547 | struct ieee80211_vif *vif, |
1549 | enum sta_notify_cmd cmd, | 1548 | enum sta_notify_cmd cmd, |
1550 | struct ieee80211_sta *sta) | 1549 | struct ieee80211_sta *sta) |
1551 | { | 1550 | { |
1552 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1551 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1553 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 1552 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
@@ -1584,6 +1583,7 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
1584 | #ifdef CONFIG_PM_SLEEP | 1583 | #ifdef CONFIG_PM_SLEEP |
1585 | .suspend = iwlagn_mac_suspend, | 1584 | .suspend = iwlagn_mac_suspend, |
1586 | .resume = iwlagn_mac_resume, | 1585 | .resume = iwlagn_mac_resume, |
1586 | .set_wakeup = iwlagn_mac_set_wakeup, | ||
1587 | #endif | 1587 | #endif |
1588 | .add_interface = iwlagn_mac_add_interface, | 1588 | .add_interface = iwlagn_mac_add_interface, |
1589 | .remove_interface = iwlagn_mac_remove_interface, | 1589 | .remove_interface = iwlagn_mac_remove_interface, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/dvm/main.c index ec36e2b020b6..1c2d0233a405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -44,16 +44,18 @@ | |||
44 | 44 | ||
45 | #include <asm/div64.h> | 45 | #include <asm/div64.h> |
46 | 46 | ||
47 | #include "iwl-eeprom.h" | 47 | #include "iwl-eeprom-read.h" |
48 | #include "iwl-dev.h" | 48 | #include "iwl-eeprom-parse.h" |
49 | #include "iwl-io.h" | 49 | #include "iwl-io.h" |
50 | #include "iwl-agn-calib.h" | ||
51 | #include "iwl-agn.h" | ||
52 | #include "iwl-trans.h" | 50 | #include "iwl-trans.h" |
53 | #include "iwl-op-mode.h" | 51 | #include "iwl-op-mode.h" |
54 | #include "iwl-drv.h" | 52 | #include "iwl-drv.h" |
55 | #include "iwl-modparams.h" | 53 | #include "iwl-modparams.h" |
56 | 54 | ||
55 | #include "dev.h" | ||
56 | #include "calib.h" | ||
57 | #include "agn.h" | ||
58 | |||
57 | /****************************************************************************** | 59 | /****************************************************************************** |
58 | * | 60 | * |
59 | * module boiler plate | 61 | * module boiler plate |
@@ -78,7 +80,8 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
78 | MODULE_VERSION(DRV_VERSION); | 80 | MODULE_VERSION(DRV_VERSION); |
79 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 81 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
80 | MODULE_LICENSE("GPL"); | 82 | MODULE_LICENSE("GPL"); |
81 | MODULE_ALIAS("iwlagn"); | 83 | |
84 | static const struct iwl_op_mode_ops iwl_dvm_ops; | ||
82 | 85 | ||
83 | void iwl_update_chain_flags(struct iwl_priv *priv) | 86 | void iwl_update_chain_flags(struct iwl_priv *priv) |
84 | { | 87 | { |
@@ -180,7 +183,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
180 | rate = info->control.rates[0].idx; | 183 | rate = info->control.rates[0].idx; |
181 | 184 | ||
182 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 185 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
183 | priv->hw_params.valid_tx_ant); | 186 | priv->eeprom_data->valid_tx_ant); |
184 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 187 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
185 | 188 | ||
186 | /* In mac80211, rates for 5 GHz start at 0 */ | 189 | /* In mac80211, rates for 5 GHz start at 0 */ |
@@ -578,7 +581,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = { | |||
578 | 7, 6, 5, 4, | 581 | 7, 6, 5, 4, |
579 | }; | 582 | }; |
580 | 583 | ||
581 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 584 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
582 | { | 585 | { |
583 | int i; | 586 | int i; |
584 | 587 | ||
@@ -645,7 +648,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
645 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 648 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
646 | } | 649 | } |
647 | 650 | ||
648 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 651 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
649 | { | 652 | { |
650 | struct iwl_ct_kill_config cmd; | 653 | struct iwl_ct_kill_config cmd; |
651 | struct iwl_ct_kill_throttling_config adv_cmd; | 654 | struct iwl_ct_kill_throttling_config adv_cmd; |
@@ -726,7 +729,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
726 | } | 729 | } |
727 | } | 730 | } |
728 | 731 | ||
729 | void iwl_send_bt_config(struct iwl_priv *priv) | 732 | static void iwl_send_bt_config(struct iwl_priv *priv) |
730 | { | 733 | { |
731 | struct iwl_bt_cmd bt_cmd = { | 734 | struct iwl_bt_cmd bt_cmd = { |
732 | .lead_time = BT_LEAD_TIME_DEF, | 735 | .lead_time = BT_LEAD_TIME_DEF, |
@@ -814,7 +817,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
814 | ieee80211_wake_queues(priv->hw); | 817 | ieee80211_wake_queues(priv->hw); |
815 | 818 | ||
816 | /* Configure Tx antenna selection based on H/W config */ | 819 | /* Configure Tx antenna selection based on H/W config */ |
817 | iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant); | 820 | iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant); |
818 | 821 | ||
819 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | 822 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { |
820 | struct iwl_rxon_cmd *active_rxon = | 823 | struct iwl_rxon_cmd *active_rxon = |
@@ -932,11 +935,12 @@ void iwl_down(struct iwl_priv *priv) | |||
932 | priv->ucode_loaded = false; | 935 | priv->ucode_loaded = false; |
933 | iwl_trans_stop_device(priv->trans); | 936 | iwl_trans_stop_device(priv->trans); |
934 | 937 | ||
938 | /* Set num_aux_in_flight must be done after the transport is stopped */ | ||
939 | atomic_set(&priv->num_aux_in_flight, 0); | ||
940 | |||
935 | /* Clear out all status bits but a few that are stable across reset */ | 941 | /* Clear out all status bits but a few that are stable across reset */ |
936 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | 942 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << |
937 | STATUS_RF_KILL_HW | | 943 | STATUS_RF_KILL_HW | |
938 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | ||
939 | STATUS_GEO_CONFIGURED | | ||
940 | test_bit(STATUS_FW_ERROR, &priv->status) << | 944 | test_bit(STATUS_FW_ERROR, &priv->status) << |
941 | STATUS_FW_ERROR | | 945 | STATUS_FW_ERROR | |
942 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 946 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
@@ -1078,7 +1082,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work) | |||
1078 | * | 1082 | * |
1079 | *****************************************************************************/ | 1083 | *****************************************************************************/ |
1080 | 1084 | ||
1081 | void iwl_setup_deferred_work(struct iwl_priv *priv) | 1085 | static void iwl_setup_deferred_work(struct iwl_priv *priv) |
1082 | { | 1086 | { |
1083 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); | 1087 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); |
1084 | 1088 | ||
@@ -1123,224 +1127,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
1123 | del_timer_sync(&priv->ucode_trace); | 1127 | del_timer_sync(&priv->ucode_trace); |
1124 | } | 1128 | } |
1125 | 1129 | ||
1126 | static void iwl_init_hw_rates(struct ieee80211_rate *rates) | 1130 | static int iwl_init_drv(struct iwl_priv *priv) |
1127 | { | ||
1128 | int i; | ||
1129 | |||
1130 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
1131 | rates[i].bitrate = iwl_rates[i].ieee * 5; | ||
1132 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
1133 | rates[i].hw_value_short = i; | ||
1134 | rates[i].flags = 0; | ||
1135 | if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { | ||
1136 | /* | ||
1137 | * If CCK != 1M then set short preamble rate flag. | ||
1138 | */ | ||
1139 | rates[i].flags |= | ||
1140 | (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? | ||
1141 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
1142 | } | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
1147 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
1148 | static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | ||
1149 | struct ieee80211_sta_ht_cap *ht_info, | ||
1150 | enum ieee80211_band band) | ||
1151 | { | ||
1152 | u16 max_bit_rate = 0; | ||
1153 | u8 rx_chains_num = priv->hw_params.rx_chains_num; | ||
1154 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||
1155 | |||
1156 | ht_info->cap = 0; | ||
1157 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
1158 | |||
1159 | ht_info->ht_supported = true; | ||
1160 | |||
1161 | if (priv->cfg->ht_params && | ||
1162 | priv->cfg->ht_params->ht_greenfield_support) | ||
1163 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1164 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
1165 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
1166 | if (priv->hw_params.ht40_channel & BIT(band)) { | ||
1167 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1168 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
1169 | ht_info->mcs.rx_mask[4] = 0x01; | ||
1170 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
1171 | } | ||
1172 | |||
1173 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
1174 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1175 | |||
1176 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
1177 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
1178 | |||
1179 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
1180 | if (rx_chains_num >= 2) | ||
1181 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
1182 | if (rx_chains_num >= 3) | ||
1183 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
1184 | |||
1185 | /* Highest supported Rx data rate */ | ||
1186 | max_bit_rate *= rx_chains_num; | ||
1187 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
1188 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
1189 | |||
1190 | /* Tx MCS capabilities */ | ||
1191 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1192 | if (tx_chains_num != rx_chains_num) { | ||
1193 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1194 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
1195 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | /** | ||
1200 | * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
1201 | */ | ||
1202 | static int iwl_init_geos(struct iwl_priv *priv) | ||
1203 | { | ||
1204 | struct iwl_channel_info *ch; | ||
1205 | struct ieee80211_supported_band *sband; | ||
1206 | struct ieee80211_channel *channels; | ||
1207 | struct ieee80211_channel *geo_ch; | ||
1208 | struct ieee80211_rate *rates; | ||
1209 | int i = 0; | ||
1210 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
1211 | |||
1212 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
1213 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
1214 | IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); | ||
1215 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | channels = kcalloc(priv->channel_count, | ||
1220 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
1221 | if (!channels) | ||
1222 | return -ENOMEM; | ||
1223 | |||
1224 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), | ||
1225 | GFP_KERNEL); | ||
1226 | if (!rates) { | ||
1227 | kfree(channels); | ||
1228 | return -ENOMEM; | ||
1229 | } | ||
1230 | |||
1231 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
1232 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1233 | sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; | ||
1234 | /* just OFDM */ | ||
1235 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | ||
1236 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | ||
1237 | |||
1238 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1239 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1240 | IEEE80211_BAND_5GHZ); | ||
1241 | |||
1242 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1243 | sband->channels = channels; | ||
1244 | /* OFDM & CCK */ | ||
1245 | sband->bitrates = rates; | ||
1246 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | ||
1247 | |||
1248 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1249 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1250 | IEEE80211_BAND_2GHZ); | ||
1251 | |||
1252 | priv->ieee_channels = channels; | ||
1253 | priv->ieee_rates = rates; | ||
1254 | |||
1255 | for (i = 0; i < priv->channel_count; i++) { | ||
1256 | ch = &priv->channel_info[i]; | ||
1257 | |||
1258 | /* FIXME: might be removed if scan is OK */ | ||
1259 | if (!is_channel_valid(ch)) | ||
1260 | continue; | ||
1261 | |||
1262 | sband = &priv->bands[ch->band]; | ||
1263 | |||
1264 | geo_ch = &sband->channels[sband->n_channels++]; | ||
1265 | |||
1266 | geo_ch->center_freq = | ||
1267 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
1268 | geo_ch->max_power = ch->max_power_avg; | ||
1269 | geo_ch->max_antenna_gain = 0xff; | ||
1270 | geo_ch->hw_value = ch->channel; | ||
1271 | |||
1272 | if (is_channel_valid(ch)) { | ||
1273 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
1274 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
1275 | |||
1276 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
1277 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
1278 | |||
1279 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
1280 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
1281 | |||
1282 | geo_ch->flags |= ch->ht40_extension_channel; | ||
1283 | |||
1284 | if (ch->max_power_avg > max_tx_power) | ||
1285 | max_tx_power = ch->max_power_avg; | ||
1286 | } else { | ||
1287 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
1288 | } | ||
1289 | |||
1290 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
1291 | ch->channel, geo_ch->center_freq, | ||
1292 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
1293 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
1294 | "restricted" : "valid", | ||
1295 | geo_ch->flags); | ||
1296 | } | ||
1297 | |||
1298 | priv->tx_power_device_lmt = max_tx_power; | ||
1299 | priv->tx_power_user_lmt = max_tx_power; | ||
1300 | priv->tx_power_next = max_tx_power; | ||
1301 | |||
1302 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | ||
1303 | priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) { | ||
1304 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | ||
1305 | "Please send your %s to maintainer.\n", | ||
1306 | priv->trans->hw_id_str); | ||
1307 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | ||
1308 | } | ||
1309 | |||
1310 | if (iwlwifi_mod_params.disable_5ghz) | ||
1311 | priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0; | ||
1312 | |||
1313 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
1314 | priv->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
1315 | priv->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
1316 | |||
1317 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1318 | |||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1322 | /* | ||
1323 | * iwl_free_geos - undo allocations in iwl_init_geos | ||
1324 | */ | ||
1325 | static void iwl_free_geos(struct iwl_priv *priv) | ||
1326 | { | 1131 | { |
1327 | kfree(priv->ieee_channels); | ||
1328 | kfree(priv->ieee_rates); | ||
1329 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1330 | } | ||
1331 | |||
1332 | int iwl_init_drv(struct iwl_priv *priv) | ||
1333 | { | ||
1334 | int ret; | ||
1335 | |||
1336 | spin_lock_init(&priv->sta_lock); | 1132 | spin_lock_init(&priv->sta_lock); |
1337 | 1133 | ||
1338 | mutex_init(&priv->mutex); | 1134 | mutex_init(&priv->mutex); |
1339 | 1135 | ||
1340 | INIT_LIST_HEAD(&priv->calib_results); | 1136 | INIT_LIST_HEAD(&priv->calib_results); |
1341 | 1137 | ||
1342 | priv->ieee_channels = NULL; | ||
1343 | priv->ieee_rates = NULL; | ||
1344 | priv->band = IEEE80211_BAND_2GHZ; | 1138 | priv->band = IEEE80211_BAND_2GHZ; |
1345 | 1139 | ||
1346 | priv->plcp_delta_threshold = | 1140 | priv->plcp_delta_threshold = |
@@ -1371,31 +1165,11 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
1371 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | 1165 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; |
1372 | } | 1166 | } |
1373 | 1167 | ||
1374 | ret = iwl_init_channel_map(priv); | ||
1375 | if (ret) { | ||
1376 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
1377 | goto err; | ||
1378 | } | ||
1379 | |||
1380 | ret = iwl_init_geos(priv); | ||
1381 | if (ret) { | ||
1382 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
1383 | goto err_free_channel_map; | ||
1384 | } | ||
1385 | iwl_init_hw_rates(priv->ieee_rates); | ||
1386 | |||
1387 | return 0; | 1168 | return 0; |
1388 | |||
1389 | err_free_channel_map: | ||
1390 | iwl_free_channel_map(priv); | ||
1391 | err: | ||
1392 | return ret; | ||
1393 | } | 1169 | } |
1394 | 1170 | ||
1395 | void iwl_uninit_drv(struct iwl_priv *priv) | 1171 | static void iwl_uninit_drv(struct iwl_priv *priv) |
1396 | { | 1172 | { |
1397 | iwl_free_geos(priv); | ||
1398 | iwl_free_channel_map(priv); | ||
1399 | kfree(priv->scan_cmd); | 1173 | kfree(priv->scan_cmd); |
1400 | kfree(priv->beacon_cmd); | 1174 | kfree(priv->beacon_cmd); |
1401 | kfree(rcu_dereference_raw(priv->noa_data)); | 1175 | kfree(rcu_dereference_raw(priv->noa_data)); |
@@ -1405,7 +1179,7 @@ void iwl_uninit_drv(struct iwl_priv *priv) | |||
1405 | #endif | 1179 | #endif |
1406 | } | 1180 | } |
1407 | 1181 | ||
1408 | void iwl_set_hw_params(struct iwl_priv *priv) | 1182 | static void iwl_set_hw_params(struct iwl_priv *priv) |
1409 | { | 1183 | { |
1410 | if (priv->cfg->ht_params) | 1184 | if (priv->cfg->ht_params) |
1411 | priv->hw_params.use_rts_for_aggregation = | 1185 | priv->hw_params.use_rts_for_aggregation = |
@@ -1421,7 +1195,7 @@ void iwl_set_hw_params(struct iwl_priv *priv) | |||
1421 | 1195 | ||
1422 | 1196 | ||
1423 | /* show what optional capabilities we have */ | 1197 | /* show what optional capabilities we have */ |
1424 | void iwl_option_config(struct iwl_priv *priv) | 1198 | static void iwl_option_config(struct iwl_priv *priv) |
1425 | { | 1199 | { |
1426 | #ifdef CONFIG_IWLWIFI_DEBUG | 1200 | #ifdef CONFIG_IWLWIFI_DEBUG |
1427 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); | 1201 | IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); |
@@ -1454,6 +1228,42 @@ void iwl_option_config(struct iwl_priv *priv) | |||
1454 | #endif | 1228 | #endif |
1455 | } | 1229 | } |
1456 | 1230 | ||
1231 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
1232 | { | ||
1233 | u16 radio_cfg; | ||
1234 | |||
1235 | priv->hw_params.sku = priv->eeprom_data->sku; | ||
1236 | |||
1237 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
1238 | !priv->cfg->ht_params) { | ||
1239 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
1240 | return -EINVAL; | ||
1241 | } | ||
1242 | |||
1243 | if (!priv->hw_params.sku) { | ||
1244 | IWL_ERR(priv, "Invalid device sku\n"); | ||
1245 | return -EINVAL; | ||
1246 | } | ||
1247 | |||
1248 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||
1249 | |||
1250 | radio_cfg = priv->eeprom_data->radio_cfg; | ||
1251 | |||
1252 | priv->hw_params.tx_chains_num = | ||
1253 | num_of_ant(priv->eeprom_data->valid_tx_ant); | ||
1254 | if (priv->cfg->rx_with_siso_diversity) | ||
1255 | priv->hw_params.rx_chains_num = 1; | ||
1256 | else | ||
1257 | priv->hw_params.rx_chains_num = | ||
1258 | num_of_ant(priv->eeprom_data->valid_rx_ant); | ||
1259 | |||
1260 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
1261 | priv->eeprom_data->valid_tx_ant, | ||
1262 | priv->eeprom_data->valid_rx_ant); | ||
1263 | |||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1457 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | 1267 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, |
1458 | const struct iwl_cfg *cfg, | 1268 | const struct iwl_cfg *cfg, |
1459 | const struct iwl_fw *fw) | 1269 | const struct iwl_fw *fw) |
@@ -1539,7 +1349,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1539 | trans_cfg.queue_watchdog_timeout = | 1349 | trans_cfg.queue_watchdog_timeout = |
1540 | priv->cfg->base_params->wd_timeout; | 1350 | priv->cfg->base_params->wd_timeout; |
1541 | else | 1351 | else |
1542 | trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED; | 1352 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; |
1543 | trans_cfg.command_names = iwl_dvm_cmd_strings; | 1353 | trans_cfg.command_names = iwl_dvm_cmd_strings; |
1544 | 1354 | ||
1545 | ucode_flags = fw->ucode_capa.flags; | 1355 | ucode_flags = fw->ucode_capa.flags; |
@@ -1599,25 +1409,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1599 | goto out_free_hw; | 1409 | goto out_free_hw; |
1600 | 1410 | ||
1601 | /* Read the EEPROM */ | 1411 | /* Read the EEPROM */ |
1602 | if (iwl_eeprom_init(priv, priv->trans->hw_rev)) { | 1412 | if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob, |
1413 | &priv->eeprom_blob_size)) { | ||
1603 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1414 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1604 | goto out_free_hw; | 1415 | goto out_free_hw; |
1605 | } | 1416 | } |
1417 | |||
1606 | /* Reset chip to save power until we load uCode during "up". */ | 1418 | /* Reset chip to save power until we load uCode during "up". */ |
1607 | iwl_trans_stop_hw(priv->trans, false); | 1419 | iwl_trans_stop_hw(priv->trans, false); |
1608 | 1420 | ||
1609 | if (iwl_eeprom_check_version(priv)) | 1421 | priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, |
1422 | priv->eeprom_blob, | ||
1423 | priv->eeprom_blob_size); | ||
1424 | if (!priv->eeprom_data) | ||
1425 | goto out_free_eeprom_blob; | ||
1426 | |||
1427 | if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans)) | ||
1610 | goto out_free_eeprom; | 1428 | goto out_free_eeprom; |
1611 | 1429 | ||
1612 | if (iwl_eeprom_init_hw_params(priv)) | 1430 | if (iwl_eeprom_init_hw_params(priv)) |
1613 | goto out_free_eeprom; | 1431 | goto out_free_eeprom; |
1614 | 1432 | ||
1615 | /* extract MAC Address */ | 1433 | /* extract MAC Address */ |
1616 | iwl_eeprom_get_mac(priv, priv->addresses[0].addr); | 1434 | memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN); |
1617 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 1435 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); |
1618 | priv->hw->wiphy->addresses = priv->addresses; | 1436 | priv->hw->wiphy->addresses = priv->addresses; |
1619 | priv->hw->wiphy->n_addresses = 1; | 1437 | priv->hw->wiphy->n_addresses = 1; |
1620 | num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); | 1438 | num_mac = priv->eeprom_data->n_hw_addrs; |
1621 | if (num_mac > 1) { | 1439 | if (num_mac > 1) { |
1622 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 1440 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, |
1623 | ETH_ALEN); | 1441 | ETH_ALEN); |
@@ -1711,8 +1529,10 @@ out_destroy_workqueue: | |||
1711 | destroy_workqueue(priv->workqueue); | 1529 | destroy_workqueue(priv->workqueue); |
1712 | priv->workqueue = NULL; | 1530 | priv->workqueue = NULL; |
1713 | iwl_uninit_drv(priv); | 1531 | iwl_uninit_drv(priv); |
1532 | out_free_eeprom_blob: | ||
1533 | kfree(priv->eeprom_blob); | ||
1714 | out_free_eeprom: | 1534 | out_free_eeprom: |
1715 | iwl_eeprom_free(priv); | 1535 | iwl_free_eeprom_data(priv->eeprom_data); |
1716 | out_free_hw: | 1536 | out_free_hw: |
1717 | ieee80211_free_hw(priv->hw); | 1537 | ieee80211_free_hw(priv->hw); |
1718 | out: | 1538 | out: |
@@ -1720,7 +1540,7 @@ out: | |||
1720 | return op_mode; | 1540 | return op_mode; |
1721 | } | 1541 | } |
1722 | 1542 | ||
1723 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | 1543 | static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) |
1724 | { | 1544 | { |
1725 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 1545 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
1726 | 1546 | ||
@@ -1737,7 +1557,8 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1737 | priv->ucode_loaded = false; | 1557 | priv->ucode_loaded = false; |
1738 | iwl_trans_stop_device(priv->trans); | 1558 | iwl_trans_stop_device(priv->trans); |
1739 | 1559 | ||
1740 | iwl_eeprom_free(priv); | 1560 | kfree(priv->eeprom_blob); |
1561 | iwl_free_eeprom_data(priv->eeprom_data); | ||
1741 | 1562 | ||
1742 | /*netif_stop_queue(dev); */ | 1563 | /*netif_stop_queue(dev); */ |
1743 | flush_workqueue(priv->workqueue); | 1564 | flush_workqueue(priv->workqueue); |
@@ -2185,7 +2006,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
2185 | } | 2006 | } |
2186 | } | 2007 | } |
2187 | 2008 | ||
2188 | void iwl_nic_error(struct iwl_op_mode *op_mode) | 2009 | static void iwl_nic_error(struct iwl_op_mode *op_mode) |
2189 | { | 2010 | { |
2190 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2011 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2191 | 2012 | ||
@@ -2198,7 +2019,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode) | |||
2198 | iwlagn_fw_error(priv, false); | 2019 | iwlagn_fw_error(priv, false); |
2199 | } | 2020 | } |
2200 | 2021 | ||
2201 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | 2022 | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) |
2202 | { | 2023 | { |
2203 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2024 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2204 | 2025 | ||
@@ -2208,9 +2029,49 @@ void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | |||
2208 | } | 2029 | } |
2209 | } | 2030 | } |
2210 | 2031 | ||
2211 | void iwl_nic_config(struct iwl_op_mode *op_mode) | 2032 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 |
2033 | |||
2034 | static void iwl_nic_config(struct iwl_op_mode *op_mode) | ||
2212 | { | 2035 | { |
2213 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2036 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2037 | u16 radio_cfg = priv->eeprom_data->radio_cfg; | ||
2038 | |||
2039 | /* SKU Control */ | ||
2040 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2041 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | | ||
2042 | CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP, | ||
2043 | (CSR_HW_REV_STEP(priv->trans->hw_rev) << | ||
2044 | CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) | | ||
2045 | (CSR_HW_REV_DASH(priv->trans->hw_rev) << | ||
2046 | CSR_HW_IF_CONFIG_REG_POS_MAC_DASH)); | ||
2047 | |||
2048 | /* write radio config values to register */ | ||
2049 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
2050 | u32 reg_val = | ||
2051 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) << | ||
2052 | CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE | | ||
2053 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) << | ||
2054 | CSR_HW_IF_CONFIG_REG_POS_PHY_STEP | | ||
2055 | EEPROM_RF_CFG_DASH_MSK(radio_cfg) << | ||
2056 | CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; | ||
2057 | |||
2058 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2059 | CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | | ||
2060 | CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | | ||
2061 | CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); | ||
2062 | |||
2063 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
2064 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
2065 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
2066 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
2067 | } else { | ||
2068 | WARN_ON(1); | ||
2069 | } | ||
2070 | |||
2071 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
2072 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
2073 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
2074 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
2214 | 2075 | ||
2215 | priv->lib->nic_config(priv); | 2076 | priv->lib->nic_config(priv); |
2216 | } | 2077 | } |
@@ -2223,7 +2084,7 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode) | |||
2223 | IWL_ERR(priv, "RF is used by WiMAX\n"); | 2084 | IWL_ERR(priv, "RF is used by WiMAX\n"); |
2224 | } | 2085 | } |
2225 | 2086 | ||
2226 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2087 | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) |
2227 | { | 2088 | { |
2228 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2089 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2229 | int mq = priv->queue_to_mac80211[queue]; | 2090 | int mq = priv->queue_to_mac80211[queue]; |
@@ -2242,7 +2103,7 @@ void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | |||
2242 | ieee80211_stop_queue(priv->hw, mq); | 2103 | ieee80211_stop_queue(priv->hw, mq); |
2243 | } | 2104 | } |
2244 | 2105 | ||
2245 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2106 | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) |
2246 | { | 2107 | { |
2247 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2108 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2248 | int mq = priv->queue_to_mac80211[queue]; | 2109 | int mq = priv->queue_to_mac80211[queue]; |
@@ -2282,16 +2143,17 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) | |||
2282 | priv->passive_no_rx = false; | 2143 | priv->passive_no_rx = false; |
2283 | } | 2144 | } |
2284 | 2145 | ||
2285 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 2146 | static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) |
2286 | { | 2147 | { |
2148 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2287 | struct ieee80211_tx_info *info; | 2149 | struct ieee80211_tx_info *info; |
2288 | 2150 | ||
2289 | info = IEEE80211_SKB_CB(skb); | 2151 | info = IEEE80211_SKB_CB(skb); |
2290 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 2152 | iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); |
2291 | dev_kfree_skb_any(skb); | 2153 | dev_kfree_skb_any(skb); |
2292 | } | 2154 | } |
2293 | 2155 | ||
2294 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 2156 | static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
2295 | { | 2157 | { |
2296 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2158 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2297 | 2159 | ||
@@ -2303,7 +2165,7 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
2303 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | 2165 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); |
2304 | } | 2166 | } |
2305 | 2167 | ||
2306 | const struct iwl_op_mode_ops iwl_dvm_ops = { | 2168 | static const struct iwl_op_mode_ops iwl_dvm_ops = { |
2307 | .start = iwl_op_mode_dvm_start, | 2169 | .start = iwl_op_mode_dvm_start, |
2308 | .stop = iwl_op_mode_dvm_stop, | 2170 | .stop = iwl_op_mode_dvm_stop, |
2309 | .rx = iwl_rx_dispatch, | 2171 | .rx = iwl_rx_dispatch, |
@@ -2322,9 +2184,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { | |||
2322 | * driver and module entry point | 2184 | * driver and module entry point |
2323 | * | 2185 | * |
2324 | *****************************************************************************/ | 2186 | *****************************************************************************/ |
2325 | |||
2326 | struct kmem_cache *iwl_tx_cmd_pool; | ||
2327 | |||
2328 | static int __init iwl_init(void) | 2187 | static int __init iwl_init(void) |
2329 | { | 2188 | { |
2330 | 2189 | ||
@@ -2332,36 +2191,25 @@ static int __init iwl_init(void) | |||
2332 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 2191 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); |
2333 | pr_info(DRV_COPYRIGHT "\n"); | 2192 | pr_info(DRV_COPYRIGHT "\n"); |
2334 | 2193 | ||
2335 | iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd", | ||
2336 | sizeof(struct iwl_device_cmd), | ||
2337 | sizeof(void *), 0, NULL); | ||
2338 | if (!iwl_tx_cmd_pool) | ||
2339 | return -ENOMEM; | ||
2340 | |||
2341 | ret = iwlagn_rate_control_register(); | 2194 | ret = iwlagn_rate_control_register(); |
2342 | if (ret) { | 2195 | if (ret) { |
2343 | pr_err("Unable to register rate control algorithm: %d\n", ret); | 2196 | pr_err("Unable to register rate control algorithm: %d\n", ret); |
2344 | goto error_rc_register; | 2197 | return ret; |
2345 | } | 2198 | } |
2346 | 2199 | ||
2347 | ret = iwl_pci_register_driver(); | 2200 | ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); |
2348 | if (ret) | 2201 | if (ret) { |
2349 | goto error_pci_register; | 2202 | pr_err("Unable to register op_mode: %d\n", ret); |
2350 | return ret; | 2203 | iwlagn_rate_control_unregister(); |
2204 | } | ||
2351 | 2205 | ||
2352 | error_pci_register: | ||
2353 | iwlagn_rate_control_unregister(); | ||
2354 | error_rc_register: | ||
2355 | kmem_cache_destroy(iwl_tx_cmd_pool); | ||
2356 | return ret; | 2206 | return ret; |
2357 | } | 2207 | } |
2208 | module_init(iwl_init); | ||
2358 | 2209 | ||
2359 | static void __exit iwl_exit(void) | 2210 | static void __exit iwl_exit(void) |
2360 | { | 2211 | { |
2361 | iwl_pci_unregister_driver(); | 2212 | iwl_opmode_deregister("iwldvm"); |
2362 | iwlagn_rate_control_unregister(); | 2213 | iwlagn_rate_control_unregister(); |
2363 | kmem_cache_destroy(iwl_tx_cmd_pool); | ||
2364 | } | 2214 | } |
2365 | |||
2366 | module_exit(iwl_exit); | 2215 | module_exit(iwl_exit); |
2367 | module_init(iwl_init); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index 544ddf17f5bd..518cf3715809 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
@@ -31,18 +31,15 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | |||
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | #include "iwl-eeprom.h" | ||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | 36 | #include "iwl-debug.h" |
43 | #include "iwl-power.h" | ||
44 | #include "iwl-trans.h" | 37 | #include "iwl-trans.h" |
45 | #include "iwl-modparams.h" | 38 | #include "iwl-modparams.h" |
39 | #include "dev.h" | ||
40 | #include "agn.h" | ||
41 | #include "commands.h" | ||
42 | #include "power.h" | ||
46 | 43 | ||
47 | /* | 44 | /* |
48 | * Setting power level allows the card to go to sleep when not busy. | 45 | * Setting power level allows the card to go to sleep when not busy. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/dvm/power.h index 21afc92efacb..a2cee7f04848 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/dvm/power.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #ifndef __iwl_power_setting_h__ | 28 | #ifndef __iwl_power_setting_h__ |
29 | #define __iwl_power_setting_h__ | 29 | #define __iwl_power_setting_h__ |
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "commands.h" |
32 | 32 | ||
33 | struct iwl_power_mgr { | 33 | struct iwl_power_mgr { |
34 | struct iwl_powertable_cmd sleep_cmd; | 34 | struct iwl_powertable_cmd sleep_cmd; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 8cebd7c363fc..6fddd2785e6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -35,10 +35,8 @@ | |||
35 | 35 | ||
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | 37 | ||
38 | #include "iwl-dev.h" | 38 | #include "dev.h" |
39 | #include "iwl-agn.h" | 39 | #include "agn.h" |
40 | #include "iwl-op-mode.h" | ||
41 | #include "iwl-modparams.h" | ||
42 | 40 | ||
43 | #define RS_NAME "iwl-agn-rs" | 41 | #define RS_NAME "iwl-agn-rs" |
44 | 42 | ||
@@ -819,7 +817,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
819 | 817 | ||
820 | if (num_of_ant(tbl->ant_type) > 1) | 818 | if (num_of_ant(tbl->ant_type) > 1) |
821 | tbl->ant_type = | 819 | tbl->ant_type = |
822 | first_antenna(priv->hw_params.valid_tx_ant); | 820 | first_antenna(priv->eeprom_data->valid_tx_ant); |
823 | 821 | ||
824 | tbl->is_ht40 = 0; | 822 | tbl->is_ht40 = 0; |
825 | tbl->is_SGI = 0; | 823 | tbl->is_SGI = 0; |
@@ -1447,7 +1445,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1447 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1445 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1448 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1446 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1449 | u8 start_action; | 1447 | u8 start_action; |
1450 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1448 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1451 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1449 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1452 | int ret = 0; | 1450 | int ret = 0; |
1453 | u8 update_search_tbl_counter = 0; | 1451 | u8 update_search_tbl_counter = 0; |
@@ -1465,7 +1463,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1465 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1463 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1466 | /* avoid antenna B and MIMO */ | 1464 | /* avoid antenna B and MIMO */ |
1467 | valid_tx_ant = | 1465 | valid_tx_ant = |
1468 | first_antenna(priv->hw_params.valid_tx_ant); | 1466 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1469 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | 1467 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && |
1470 | tbl->action != IWL_LEGACY_SWITCH_SISO) | 1468 | tbl->action != IWL_LEGACY_SWITCH_SISO) |
1471 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1469 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
@@ -1489,7 +1487,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1489 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1487 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1490 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1488 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1491 | valid_tx_ant = | 1489 | valid_tx_ant = |
1492 | first_antenna(priv->hw_params.valid_tx_ant); | 1490 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1493 | } | 1491 | } |
1494 | 1492 | ||
1495 | start_action = tbl->action; | 1493 | start_action = tbl->action; |
@@ -1623,7 +1621,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1623 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1621 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1624 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1622 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1625 | u8 start_action; | 1623 | u8 start_action; |
1626 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1624 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1627 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1625 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1628 | u8 update_search_tbl_counter = 0; | 1626 | u8 update_search_tbl_counter = 0; |
1629 | int ret; | 1627 | int ret; |
@@ -1641,7 +1639,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1641 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1639 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1642 | /* avoid antenna B and MIMO */ | 1640 | /* avoid antenna B and MIMO */ |
1643 | valid_tx_ant = | 1641 | valid_tx_ant = |
1644 | first_antenna(priv->hw_params.valid_tx_ant); | 1642 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1645 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | 1643 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) |
1646 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1644 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1647 | break; | 1645 | break; |
@@ -1659,7 +1657,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1659 | /* configure as 1x1 if bt full concurrency */ | 1657 | /* configure as 1x1 if bt full concurrency */ |
1660 | if (priv->bt_full_concurrent) { | 1658 | if (priv->bt_full_concurrent) { |
1661 | valid_tx_ant = | 1659 | valid_tx_ant = |
1662 | first_antenna(priv->hw_params.valid_tx_ant); | 1660 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1663 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1661 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1664 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1662 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1665 | } | 1663 | } |
@@ -1795,7 +1793,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1795 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1793 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1796 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1794 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1797 | u8 start_action; | 1795 | u8 start_action; |
1798 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1796 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1799 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1797 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1800 | u8 update_search_tbl_counter = 0; | 1798 | u8 update_search_tbl_counter = 0; |
1801 | int ret; | 1799 | int ret; |
@@ -1965,7 +1963,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1965 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1963 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1966 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1964 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1967 | u8 start_action; | 1965 | u8 start_action; |
1968 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1966 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1969 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1967 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1970 | int ret; | 1968 | int ret; |
1971 | u8 update_search_tbl_counter = 0; | 1969 | u8 update_search_tbl_counter = 0; |
@@ -2699,7 +2697,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2699 | 2697 | ||
2700 | i = lq_sta->last_txrate_idx; | 2698 | i = lq_sta->last_txrate_idx; |
2701 | 2699 | ||
2702 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2700 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2703 | 2701 | ||
2704 | if (!lq_sta->search_better_tbl) | 2702 | if (!lq_sta->search_better_tbl) |
2705 | active_tbl = lq_sta->active_tbl; | 2703 | active_tbl = lq_sta->active_tbl; |
@@ -2893,15 +2891,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2893 | 2891 | ||
2894 | /* These values will be overridden later */ | 2892 | /* These values will be overridden later */ |
2895 | lq_sta->lq.general_params.single_stream_ant_msk = | 2893 | lq_sta->lq.general_params.single_stream_ant_msk = |
2896 | first_antenna(priv->hw_params.valid_tx_ant); | 2894 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2897 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2895 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2898 | priv->hw_params.valid_tx_ant & | 2896 | priv->eeprom_data->valid_tx_ant & |
2899 | ~first_antenna(priv->hw_params.valid_tx_ant); | 2897 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
2900 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | 2898 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { |
2901 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2899 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; |
2902 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 2900 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
2903 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2901 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2904 | priv->hw_params.valid_tx_ant; | 2902 | priv->eeprom_data->valid_tx_ant; |
2905 | } | 2903 | } |
2906 | 2904 | ||
2907 | /* as default allow aggregation for all tids */ | 2905 | /* as default allow aggregation for all tids */ |
@@ -2947,7 +2945,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2947 | if (priv && priv->bt_full_concurrent) { | 2945 | if (priv && priv->bt_full_concurrent) { |
2948 | /* 1x1 only */ | 2946 | /* 1x1 only */ |
2949 | tbl_type.ant_type = | 2947 | tbl_type.ant_type = |
2950 | first_antenna(priv->hw_params.valid_tx_ant); | 2948 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2951 | } | 2949 | } |
2952 | 2950 | ||
2953 | /* How many times should we repeat the initial rate? */ | 2951 | /* How many times should we repeat the initial rate? */ |
@@ -2979,7 +2977,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2979 | if (priv->bt_full_concurrent) | 2977 | if (priv->bt_full_concurrent) |
2980 | valid_tx_ant = ANT_A; | 2978 | valid_tx_ant = ANT_A; |
2981 | else | 2979 | else |
2982 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2980 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2983 | } | 2981 | } |
2984 | 2982 | ||
2985 | /* Fill rest of rate table */ | 2983 | /* Fill rest of rate table */ |
@@ -3013,7 +3011,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3013 | if (priv && priv->bt_full_concurrent) { | 3011 | if (priv && priv->bt_full_concurrent) { |
3014 | /* 1x1 only */ | 3012 | /* 1x1 only */ |
3015 | tbl_type.ant_type = | 3013 | tbl_type.ant_type = |
3016 | first_antenna(priv->hw_params.valid_tx_ant); | 3014 | first_antenna(priv->eeprom_data->valid_tx_ant); |
3017 | } | 3015 | } |
3018 | 3016 | ||
3019 | /* Indicate to uCode which entries might be MIMO. | 3017 | /* Indicate to uCode which entries might be MIMO. |
@@ -3100,7 +3098,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
3100 | u8 ant_sel_tx; | 3098 | u8 ant_sel_tx; |
3101 | 3099 | ||
3102 | priv = lq_sta->drv; | 3100 | priv = lq_sta->drv; |
3103 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 3101 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
3104 | if (lq_sta->dbg_fixed_rate) { | 3102 | if (lq_sta->dbg_fixed_rate) { |
3105 | ant_sel_tx = | 3103 | ant_sel_tx = |
3106 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 3104 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) |
@@ -3171,9 +3169,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3171 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 3169 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
3172 | lq_sta->dbg_fixed_rate); | 3170 | lq_sta->dbg_fixed_rate); |
3173 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 3171 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
3174 | (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", | 3172 | (priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "", |
3175 | (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", | 3173 | (priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "", |
3176 | (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 3174 | (priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : ""); |
3177 | desc += sprintf(buff+desc, "lq type %s\n", | 3175 | desc += sprintf(buff+desc, "lq type %s\n", |
3178 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 3176 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
3179 | if (is_Ht(tbl->lq_type)) { | 3177 | if (is_Ht(tbl->lq_type)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h index 82d02e1ae89f..ad3aea8f626a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/dvm/rs.h | |||
@@ -29,9 +29,10 @@ | |||
29 | 29 | ||
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | 31 | ||
32 | #include "iwl-commands.h" | ||
33 | #include "iwl-config.h" | 32 | #include "iwl-config.h" |
34 | 33 | ||
34 | #include "commands.h" | ||
35 | |||
35 | struct iwl_rate_info { | 36 | struct iwl_rate_info { |
36 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ | 37 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ |
37 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ | 38 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 403de96f9747..0ed90bb8b56a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -32,12 +32,10 @@ | |||
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
35 | #include "iwl-eeprom.h" | ||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
38 | #include "iwl-agn-calib.h" | 36 | #include "dev.h" |
39 | #include "iwl-agn.h" | 37 | #include "calib.h" |
40 | #include "iwl-modparams.h" | 38 | #include "agn.h" |
41 | 39 | ||
42 | #define IWL_CMD_ENTRY(x) [x] = #x | 40 | #define IWL_CMD_ENTRY(x) [x] = #x |
43 | 41 | ||
@@ -1012,6 +1010,8 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1012 | rx_status.flag |= RX_FLAG_40MHZ; | 1010 | rx_status.flag |= RX_FLAG_40MHZ; |
1013 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 1011 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
1014 | rx_status.flag |= RX_FLAG_SHORT_GI; | 1012 | rx_status.flag |= RX_FLAG_SHORT_GI; |
1013 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
1014 | rx_status.flag |= RX_FLAG_HT_GF; | ||
1015 | 1015 | ||
1016 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | 1016 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1017 | rxb, &rx_status); | 1017 | rxb, &rx_status); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index 0a3aa7c83003..6ee940f497f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -25,11 +25,11 @@ | |||
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
28 | #include "iwl-dev.h" | ||
29 | #include "iwl-agn.h" | ||
30 | #include "iwl-agn-calib.h" | ||
31 | #include "iwl-trans.h" | 28 | #include "iwl-trans.h" |
32 | #include "iwl-modparams.h" | 29 | #include "iwl-modparams.h" |
30 | #include "dev.h" | ||
31 | #include "agn.h" | ||
32 | #include "calib.h" | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * initialize rxon structure with default values from eeprom | 35 | * initialize rxon structure with default values from eeprom |
@@ -37,8 +37,6 @@ | |||
37 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 37 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
38 | struct iwl_rxon_context *ctx) | 38 | struct iwl_rxon_context *ctx) |
39 | { | 39 | { |
40 | const struct iwl_channel_info *ch_info; | ||
41 | |||
42 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | 40 | memset(&ctx->staging, 0, sizeof(ctx->staging)); |
43 | 41 | ||
44 | if (!ctx->vif) { | 42 | if (!ctx->vif) { |
@@ -80,14 +78,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
80 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 78 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
81 | #endif | 79 | #endif |
82 | 80 | ||
83 | ch_info = iwl_get_channel_info(priv, priv->band, | 81 | ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value); |
84 | le16_to_cpu(ctx->active.channel)); | 82 | priv->band = priv->hw->conf.channel->band; |
85 | |||
86 | if (!ch_info) | ||
87 | ch_info = &priv->channel_info[0]; | ||
88 | |||
89 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | ||
90 | priv->band = ch_info->band; | ||
91 | 83 | ||
92 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | 84 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); |
93 | 85 | ||
@@ -175,7 +167,8 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, | |||
175 | return ret; | 167 | return ret; |
176 | } | 168 | } |
177 | 169 | ||
178 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 170 | static void iwlagn_update_qos(struct iwl_priv *priv, |
171 | struct iwl_rxon_context *ctx) | ||
179 | { | 172 | { |
180 | int ret; | 173 | int ret; |
181 | 174 | ||
@@ -202,8 +195,8 @@ void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
202 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); | 195 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); |
203 | } | 196 | } |
204 | 197 | ||
205 | int iwlagn_update_beacon(struct iwl_priv *priv, | 198 | static int iwlagn_update_beacon(struct iwl_priv *priv, |
206 | struct ieee80211_vif *vif) | 199 | struct ieee80211_vif *vif) |
207 | { | 200 | { |
208 | lockdep_assert_held(&priv->mutex); | 201 | lockdep_assert_held(&priv->mutex); |
209 | 202 | ||
@@ -215,7 +208,7 @@ int iwlagn_update_beacon(struct iwl_priv *priv, | |||
215 | } | 208 | } |
216 | 209 | ||
217 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, | 210 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, |
218 | struct iwl_rxon_context *ctx) | 211 | struct iwl_rxon_context *ctx) |
219 | { | 212 | { |
220 | int ret = 0; | 213 | int ret = 0; |
221 | struct iwl_rxon_assoc_cmd rxon_assoc; | 214 | struct iwl_rxon_assoc_cmd rxon_assoc; |
@@ -427,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
427 | return -EINVAL; | 420 | return -EINVAL; |
428 | } | 421 | } |
429 | 422 | ||
430 | if (tx_power > priv->tx_power_device_lmt) { | 423 | if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) { |
431 | IWL_WARN(priv, | 424 | IWL_WARN(priv, |
432 | "Requested user TXPOWER %d above upper limit %d.\n", | 425 | "Requested user TXPOWER %d above upper limit %d.\n", |
433 | tx_power, priv->tx_power_device_lmt); | 426 | tx_power, priv->eeprom_data->max_tx_pwr_half_dbm); |
434 | return -EINVAL; | 427 | return -EINVAL; |
435 | } | 428 | } |
436 | 429 | ||
@@ -863,8 +856,8 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv, | |||
863 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | 856 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that |
864 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | 857 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |
865 | */ | 858 | */ |
866 | int iwl_full_rxon_required(struct iwl_priv *priv, | 859 | static int iwl_full_rxon_required(struct iwl_priv *priv, |
867 | struct iwl_rxon_context *ctx) | 860 | struct iwl_rxon_context *ctx) |
868 | { | 861 | { |
869 | const struct iwl_rxon_cmd *staging = &ctx->staging; | 862 | const struct iwl_rxon_cmd *staging = &ctx->staging; |
870 | const struct iwl_rxon_cmd *active = &ctx->active; | 863 | const struct iwl_rxon_cmd *active = &ctx->active; |
@@ -1189,7 +1182,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1189 | struct iwl_rxon_context *ctx; | 1182 | struct iwl_rxon_context *ctx; |
1190 | struct ieee80211_conf *conf = &hw->conf; | 1183 | struct ieee80211_conf *conf = &hw->conf; |
1191 | struct ieee80211_channel *channel = conf->channel; | 1184 | struct ieee80211_channel *channel = conf->channel; |
1192 | const struct iwl_channel_info *ch_info; | ||
1193 | int ret = 0; | 1185 | int ret = 0; |
1194 | 1186 | ||
1195 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); | 1187 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); |
@@ -1223,14 +1215,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1223 | } | 1215 | } |
1224 | 1216 | ||
1225 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1217 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1226 | ch_info = iwl_get_channel_info(priv, channel->band, | ||
1227 | channel->hw_value); | ||
1228 | if (!is_channel_valid(ch_info)) { | ||
1229 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | ||
1230 | ret = -EINVAL; | ||
1231 | goto out; | ||
1232 | } | ||
1233 | |||
1234 | for_each_context(priv, ctx) { | 1218 | for_each_context(priv, ctx) { |
1235 | /* Configure HT40 channels */ | 1219 | /* Configure HT40 channels */ |
1236 | if (ctx->ht.enabled != conf_is_ht(conf)) | 1220 | if (ctx->ht.enabled != conf_is_ht(conf)) |
@@ -1294,9 +1278,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
1294 | return ret; | 1278 | return ret; |
1295 | } | 1279 | } |
1296 | 1280 | ||
1297 | void iwlagn_check_needed_chains(struct iwl_priv *priv, | 1281 | static void iwlagn_check_needed_chains(struct iwl_priv *priv, |
1298 | struct iwl_rxon_context *ctx, | 1282 | struct iwl_rxon_context *ctx, |
1299 | struct ieee80211_bss_conf *bss_conf) | 1283 | struct ieee80211_bss_conf *bss_conf) |
1300 | { | 1284 | { |
1301 | struct ieee80211_vif *vif = ctx->vif; | 1285 | struct ieee80211_vif *vif = ctx->vif; |
1302 | struct iwl_rxon_context *tmp; | 1286 | struct iwl_rxon_context *tmp; |
@@ -1388,7 +1372,7 @@ void iwlagn_check_needed_chains(struct iwl_priv *priv, | |||
1388 | ht_conf->single_chain_sufficient = !need_multiple; | 1372 | ht_conf->single_chain_sufficient = !need_multiple; |
1389 | } | 1373 | } |
1390 | 1374 | ||
1391 | void iwlagn_chain_noise_reset(struct iwl_priv *priv) | 1375 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) |
1392 | { | 1376 | { |
1393 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 1377 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
1394 | int ret; | 1378 | int ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 031d8e21f82f..2f271c96ed39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -30,11 +30,8 @@ | |||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | #include "iwl-eeprom.h" | 33 | #include "dev.h" |
34 | #include "iwl-dev.h" | 34 | #include "agn.h" |
35 | #include "iwl-io.h" | ||
36 | #include "iwl-agn.h" | ||
37 | #include "iwl-trans.h" | ||
38 | 35 | ||
39 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after | 36 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after |
40 | * sending probe req. This should be set long enough to hear probe responses | 37 | * sending probe req. This should be set long enough to hear probe responses |
@@ -67,7 +64,6 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
67 | * to receive scan abort command or it does not perform | 64 | * to receive scan abort command or it does not perform |
68 | * hardware scan currently */ | 65 | * hardware scan currently */ |
69 | if (!test_bit(STATUS_READY, &priv->status) || | 66 | if (!test_bit(STATUS_READY, &priv->status) || |
70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || | ||
71 | !test_bit(STATUS_SCAN_HW, &priv->status) || | 67 | !test_bit(STATUS_SCAN_HW, &priv->status) || |
72 | test_bit(STATUS_FW_ERROR, &priv->status)) | 68 | test_bit(STATUS_FW_ERROR, &priv->status)) |
73 | return -EIO; | 69 | return -EIO; |
@@ -101,11 +97,8 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | |||
101 | ieee80211_scan_completed(priv->hw, aborted); | 97 | ieee80211_scan_completed(priv->hw, aborted); |
102 | } | 98 | } |
103 | 99 | ||
104 | if (priv->scan_type == IWL_SCAN_ROC) { | 100 | if (priv->scan_type == IWL_SCAN_ROC) |
105 | ieee80211_remain_on_channel_expired(priv->hw); | 101 | iwl_scan_roc_expired(priv); |
106 | priv->hw_roc_channel = NULL; | ||
107 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
108 | } | ||
109 | 102 | ||
110 | priv->scan_type = IWL_SCAN_NORMAL; | 103 | priv->scan_type = IWL_SCAN_NORMAL; |
111 | priv->scan_vif = NULL; | 104 | priv->scan_vif = NULL; |
@@ -134,11 +127,8 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) | |||
134 | goto out_settings; | 127 | goto out_settings; |
135 | } | 128 | } |
136 | 129 | ||
137 | if (priv->scan_type == IWL_SCAN_ROC) { | 130 | if (priv->scan_type == IWL_SCAN_ROC) |
138 | ieee80211_remain_on_channel_expired(priv->hw); | 131 | iwl_scan_roc_expired(priv); |
139 | priv->hw_roc_channel = NULL; | ||
140 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
141 | } | ||
142 | 132 | ||
143 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | 133 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { |
144 | int err; | 134 | int err; |
@@ -453,27 +443,17 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
453 | 443 | ||
454 | /* Return valid, unused, channel for a passive scan to reset the RF */ | 444 | /* Return valid, unused, channel for a passive scan to reset the RF */ |
455 | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | 445 | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, |
456 | enum ieee80211_band band) | 446 | enum ieee80211_band band) |
457 | { | 447 | { |
458 | const struct iwl_channel_info *ch_info; | 448 | struct ieee80211_supported_band *sband = priv->hw->wiphy->bands[band]; |
459 | int i; | ||
460 | u8 channel = 0; | ||
461 | u8 min, max; | ||
462 | struct iwl_rxon_context *ctx; | 449 | struct iwl_rxon_context *ctx; |
450 | int i; | ||
463 | 451 | ||
464 | if (band == IEEE80211_BAND_5GHZ) { | 452 | for (i = 0; i < sband->n_channels; i++) { |
465 | min = 14; | ||
466 | max = priv->channel_count; | ||
467 | } else { | ||
468 | min = 0; | ||
469 | max = 14; | ||
470 | } | ||
471 | |||
472 | for (i = min; i < max; i++) { | ||
473 | bool busy = false; | 453 | bool busy = false; |
474 | 454 | ||
475 | for_each_context(priv, ctx) { | 455 | for_each_context(priv, ctx) { |
476 | busy = priv->channel_info[i].channel == | 456 | busy = sband->channels[i].hw_value == |
477 | le16_to_cpu(ctx->staging.channel); | 457 | le16_to_cpu(ctx->staging.channel); |
478 | if (busy) | 458 | if (busy) |
479 | break; | 459 | break; |
@@ -482,13 +462,11 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | |||
482 | if (busy) | 462 | if (busy) |
483 | continue; | 463 | continue; |
484 | 464 | ||
485 | channel = priv->channel_info[i].channel; | 465 | if (!(sband->channels[i].flags & IEEE80211_CHAN_DISABLED)) |
486 | ch_info = iwl_get_channel_info(priv, band, channel); | 466 | return sband->channels[i].hw_value; |
487 | if (is_channel_valid(ch_info)) | ||
488 | break; | ||
489 | } | 467 | } |
490 | 468 | ||
491 | return channel; | 469 | return 0; |
492 | } | 470 | } |
493 | 471 | ||
494 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | 472 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, |
@@ -540,7 +518,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
540 | { | 518 | { |
541 | struct ieee80211_channel *chan; | 519 | struct ieee80211_channel *chan; |
542 | const struct ieee80211_supported_band *sband; | 520 | const struct ieee80211_supported_band *sband; |
543 | const struct iwl_channel_info *ch_info; | ||
544 | u16 passive_dwell = 0; | 521 | u16 passive_dwell = 0; |
545 | u16 active_dwell = 0; | 522 | u16 active_dwell = 0; |
546 | int added, i; | 523 | int added, i; |
@@ -565,16 +542,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
565 | channel = chan->hw_value; | 542 | channel = chan->hw_value; |
566 | scan_ch->channel = cpu_to_le16(channel); | 543 | scan_ch->channel = cpu_to_le16(channel); |
567 | 544 | ||
568 | ch_info = iwl_get_channel_info(priv, band, channel); | 545 | if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) |
569 | if (!is_channel_valid(ch_info)) { | ||
570 | IWL_DEBUG_SCAN(priv, | ||
571 | "Channel %d is INVALID for this band.\n", | ||
572 | channel); | ||
573 | continue; | ||
574 | } | ||
575 | |||
576 | if (!is_active || is_channel_passive(ch_info) || | ||
577 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
578 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 546 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
579 | else | 547 | else |
580 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 548 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
@@ -678,12 +646,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
678 | u16 rx_chain = 0; | 646 | u16 rx_chain = 0; |
679 | enum ieee80211_band band; | 647 | enum ieee80211_band band; |
680 | u8 n_probes = 0; | 648 | u8 n_probes = 0; |
681 | u8 rx_ant = priv->hw_params.valid_rx_ant; | 649 | u8 rx_ant = priv->eeprom_data->valid_rx_ant; |
682 | u8 rate; | 650 | u8 rate; |
683 | bool is_active = false; | 651 | bool is_active = false; |
684 | int chan_mod; | 652 | int chan_mod; |
685 | u8 active_chains; | 653 | u8 active_chains; |
686 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 654 | u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant; |
687 | int ret; | 655 | int ret; |
688 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | 656 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + |
689 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | 657 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + |
@@ -893,7 +861,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
893 | 861 | ||
894 | /* MIMO is not used here, but value is required */ | 862 | /* MIMO is not used here, but value is required */ |
895 | rx_chain |= | 863 | rx_chain |= |
896 | priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | 864 | priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
897 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 865 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
898 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 866 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
899 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 867 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
@@ -994,8 +962,10 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
994 | set_bit(STATUS_SCAN_HW, &priv->status); | 962 | set_bit(STATUS_SCAN_HW, &priv->status); |
995 | 963 | ||
996 | ret = iwlagn_set_pan_params(priv); | 964 | ret = iwlagn_set_pan_params(priv); |
997 | if (ret) | 965 | if (ret) { |
966 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
998 | return ret; | 967 | return ret; |
968 | } | ||
999 | 969 | ||
1000 | ret = iwl_dvm_send_cmd(priv, &cmd); | 970 | ret = iwl_dvm_send_cmd(priv, &cmd); |
1001 | if (ret) { | 971 | if (ret) { |
@@ -1008,7 +978,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1008 | 978 | ||
1009 | void iwl_init_scan_params(struct iwl_priv *priv) | 979 | void iwl_init_scan_params(struct iwl_priv *priv) |
1010 | { | 980 | { |
1011 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; | 981 | u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1; |
1012 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | 982 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) |
1013 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | 983 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; |
1014 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 984 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
@@ -1158,3 +1128,40 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | |||
1158 | mutex_unlock(&priv->mutex); | 1128 | mutex_unlock(&priv->mutex); |
1159 | } | 1129 | } |
1160 | } | 1130 | } |
1131 | |||
1132 | void iwl_scan_roc_expired(struct iwl_priv *priv) | ||
1133 | { | ||
1134 | /* | ||
1135 | * The status bit should be set here, to prevent a race | ||
1136 | * where the atomic_read returns 1, but before the execution continues | ||
1137 | * iwl_scan_offchannel_skb_status() checks if the status bit is set | ||
1138 | */ | ||
1139 | set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1140 | |||
1141 | if (atomic_read(&priv->num_aux_in_flight) == 0) { | ||
1142 | ieee80211_remain_on_channel_expired(priv->hw); | ||
1143 | priv->hw_roc_channel = NULL; | ||
1144 | schedule_delayed_work(&priv->hw_roc_disable_work, | ||
1145 | 10 * HZ); | ||
1146 | |||
1147 | clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||
1148 | } else { | ||
1149 | IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n", | ||
1150 | atomic_read(&priv->num_aux_in_flight)); | ||
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | void iwl_scan_offchannel_skb(struct iwl_priv *priv) | ||
1155 | { | ||
1156 | WARN_ON(!priv->hw_roc_start_notified); | ||
1157 | atomic_inc(&priv->num_aux_in_flight); | ||
1158 | } | ||
1159 | |||
1160 | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv) | ||
1161 | { | ||
1162 | if (atomic_dec_return(&priv->num_aux_in_flight) == 0 && | ||
1163 | test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) { | ||
1164 | IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n"); | ||
1165 | iwl_scan_roc_expired(priv); | ||
1166 | } | ||
1167 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index aea07aab3c9e..286ce4e18068 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -28,10 +28,9 @@ | |||
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | |||
32 | #include "iwl-dev.h" | ||
33 | #include "iwl-agn.h" | ||
34 | #include "iwl-trans.h" | 31 | #include "iwl-trans.h" |
32 | #include "dev.h" | ||
33 | #include "agn.h" | ||
35 | 34 | ||
36 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 35 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
37 | 36 | ||
@@ -171,26 +170,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
171 | return cmd.handler_status; | 170 | return cmd.handler_status; |
172 | } | 171 | } |
173 | 172 | ||
174 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | ||
175 | enum ieee80211_band band, | ||
176 | u16 channel, u8 extension_chan_offset) | ||
177 | { | ||
178 | const struct iwl_channel_info *ch_info; | ||
179 | |||
180 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
181 | if (!is_channel_valid(ch_info)) | ||
182 | return false; | ||
183 | |||
184 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
185 | return !(ch_info->ht40_extension_channel & | ||
186 | IEEE80211_CHAN_NO_HT40PLUS); | ||
187 | else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
188 | return !(ch_info->ht40_extension_channel & | ||
189 | IEEE80211_CHAN_NO_HT40MINUS); | ||
190 | |||
191 | return false; | ||
192 | } | ||
193 | |||
194 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 173 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
195 | struct iwl_rxon_context *ctx, | 174 | struct iwl_rxon_context *ctx, |
196 | struct ieee80211_sta_ht_cap *ht_cap) | 175 | struct ieee80211_sta_ht_cap *ht_cap) |
@@ -198,21 +177,25 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
198 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | 177 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) |
199 | return false; | 178 | return false; |
200 | 179 | ||
180 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
181 | if (priv->disable_ht40) | ||
182 | return false; | ||
183 | #endif | ||
184 | |||
201 | /* | 185 | /* |
202 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 186 | * Remainder of this function checks ht_cap, but if it's |
203 | * the bit will not set if it is pure 40MHz case | 187 | * NULL then we can do HT40 (special case for RXON) |
204 | */ | 188 | */ |
205 | if (ht_cap && !ht_cap->ht_supported) | 189 | if (!ht_cap) |
190 | return true; | ||
191 | |||
192 | if (!ht_cap->ht_supported) | ||
206 | return false; | 193 | return false; |
207 | 194 | ||
208 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 195 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
209 | if (priv->disable_ht40) | ||
210 | return false; | 196 | return false; |
211 | #endif | ||
212 | 197 | ||
213 | return iwl_is_channel_extension(priv, priv->band, | 198 | return true; |
214 | le16_to_cpu(ctx->staging.channel), | ||
215 | ctx->ht.extension_chan_offset); | ||
216 | } | 199 | } |
217 | 200 | ||
218 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | 201 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, |
@@ -236,6 +219,7 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | |||
236 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; | 219 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; |
237 | 220 | ||
238 | IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n", | 221 | IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n", |
222 | sta->addr, | ||
239 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? | 223 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? |
240 | "static" : | 224 | "static" : |
241 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? | 225 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? |
@@ -649,23 +633,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
649 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | 633 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) |
650 | rate_flags |= RATE_MCS_CCK_MSK; | 634 | rate_flags |= RATE_MCS_CCK_MSK; |
651 | 635 | ||
652 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 636 | rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) << |
653 | RATE_MCS_ANT_POS; | 637 | RATE_MCS_ANT_POS; |
654 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 638 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); |
655 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | 639 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) |
656 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | 640 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; |
657 | 641 | ||
658 | link_cmd->general_params.single_stream_ant_msk = | 642 | link_cmd->general_params.single_stream_ant_msk = |
659 | first_antenna(priv->hw_params.valid_tx_ant); | 643 | first_antenna(priv->eeprom_data->valid_tx_ant); |
660 | 644 | ||
661 | link_cmd->general_params.dual_stream_ant_msk = | 645 | link_cmd->general_params.dual_stream_ant_msk = |
662 | priv->hw_params.valid_tx_ant & | 646 | priv->eeprom_data->valid_tx_ant & |
663 | ~first_antenna(priv->hw_params.valid_tx_ant); | 647 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
664 | if (!link_cmd->general_params.dual_stream_ant_msk) { | 648 | if (!link_cmd->general_params.dual_stream_ant_msk) { |
665 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | 649 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; |
666 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 650 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
667 | link_cmd->general_params.dual_stream_ant_msk = | 651 | link_cmd->general_params.dual_stream_ant_msk = |
668 | priv->hw_params.valid_tx_ant; | 652 | priv->eeprom_data->valid_tx_ant; |
669 | } | 653 | } |
670 | 654 | ||
671 | link_cmd->agg_params.agg_dis_start_th = | 655 | link_cmd->agg_params.agg_dis_start_th = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c index 492e64fb9f3d..e08b1a383594 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c | |||
@@ -69,15 +69,14 @@ | |||
69 | #include <net/cfg80211.h> | 69 | #include <net/cfg80211.h> |
70 | #include <net/mac80211.h> | 70 | #include <net/mac80211.h> |
71 | #include <net/netlink.h> | 71 | #include <net/netlink.h> |
72 | |||
73 | #include "iwl-dev.h" | ||
74 | #include "iwl-debug.h" | 72 | #include "iwl-debug.h" |
75 | #include "iwl-io.h" | 73 | #include "iwl-io.h" |
76 | #include "iwl-agn.h" | ||
77 | #include "iwl-testmode.h" | ||
78 | #include "iwl-trans.h" | 74 | #include "iwl-trans.h" |
79 | #include "iwl-fh.h" | 75 | #include "iwl-fh.h" |
80 | #include "iwl-prph.h" | 76 | #include "iwl-prph.h" |
77 | #include "dev.h" | ||
78 | #include "agn.h" | ||
79 | #include "testmode.h" | ||
81 | 80 | ||
82 | 81 | ||
83 | /* Periphery registers absolute lower bound. This is used in order to | 82 | /* Periphery registers absolute lower bound. This is used in order to |
@@ -89,7 +88,7 @@ | |||
89 | /* The TLVs used in the gnl message policy between the kernel module and | 88 | /* The TLVs used in the gnl message policy between the kernel module and |
90 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | 89 | * user space application. iwl_testmode_gnl_msg_policy is to be carried |
91 | * through the NL80211_CMD_TESTMODE channel regulated by nl80211. | 90 | * through the NL80211_CMD_TESTMODE channel regulated by nl80211. |
92 | * See iwl-testmode.h | 91 | * See testmode.h |
93 | */ | 92 | */ |
94 | static | 93 | static |
95 | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | 94 | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { |
@@ -129,7 +128,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | |||
129 | }; | 128 | }; |
130 | 129 | ||
131 | /* | 130 | /* |
132 | * See the struct iwl_rx_packet in iwl-commands.h for the format of the | 131 | * See the struct iwl_rx_packet in commands.h for the format of the |
133 | * received events from the device | 132 | * received events from the device |
134 | */ | 133 | */ |
135 | static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) | 134 | static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) |
@@ -535,9 +534,9 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
535 | break; | 534 | break; |
536 | 535 | ||
537 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 536 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: |
538 | if (priv->eeprom) { | 537 | if (priv->eeprom_blob) { |
539 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | 538 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, |
540 | priv->cfg->base_params->eeprom_size + 20); | 539 | priv->eeprom_blob_size + 20); |
541 | if (!skb) { | 540 | if (!skb) { |
542 | IWL_ERR(priv, "Memory allocation fail\n"); | 541 | IWL_ERR(priv, "Memory allocation fail\n"); |
543 | return -ENOMEM; | 542 | return -ENOMEM; |
@@ -545,15 +544,15 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
545 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | 544 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, |
546 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | 545 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || |
547 | nla_put(skb, IWL_TM_ATTR_EEPROM, | 546 | nla_put(skb, IWL_TM_ATTR_EEPROM, |
548 | priv->cfg->base_params->eeprom_size, | 547 | priv->eeprom_blob_size, |
549 | priv->eeprom)) | 548 | priv->eeprom_blob)) |
550 | goto nla_put_failure; | 549 | goto nla_put_failure; |
551 | status = cfg80211_testmode_reply(skb); | 550 | status = cfg80211_testmode_reply(skb); |
552 | if (status < 0) | 551 | if (status < 0) |
553 | IWL_ERR(priv, "Error sending msg : %d\n", | 552 | IWL_ERR(priv, "Error sending msg : %d\n", |
554 | status); | 553 | status); |
555 | } else | 554 | } else |
556 | return -EFAULT; | 555 | return -ENODATA; |
557 | break; | 556 | break; |
558 | 557 | ||
559 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | 558 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/dvm/testmode.h index 6ba211b09426..6ba211b09426 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.h | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index a5cfe0aceedb..eb864433e59d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -31,17 +31,14 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | |||
35 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
36 | |||
37 | #include "iwl-agn.h" | ||
38 | #include "iwl-eeprom.h" | ||
39 | #include "iwl-dev.h" | ||
40 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | ||
43 | #include "iwl-agn-tt.h" | ||
44 | #include "iwl-modparams.h" | 36 | #include "iwl-modparams.h" |
37 | #include "iwl-debug.h" | ||
38 | #include "agn.h" | ||
39 | #include "dev.h" | ||
40 | #include "commands.h" | ||
41 | #include "tt.h" | ||
45 | 42 | ||
46 | /* default Thermal Throttling transaction table | 43 | /* default Thermal Throttling transaction table |
47 | * Current state | Throttling Down | Throttling Up | 44 | * Current state | Throttling Down | Throttling Up |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/dvm/tt.h index 86bbf47501c1..44c7c8f30a2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/drivers/net/wireless/iwlwifi/dvm/tt.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #ifndef __iwl_tt_setting_h__ | 28 | #ifndef __iwl_tt_setting_h__ |
29 | #define __iwl_tt_setting_h__ | 29 | #define __iwl_tt_setting_h__ |
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "commands.h" |
32 | 32 | ||
33 | #define IWL_ABSOLUTE_ZERO 0 | 33 | #define IWL_ABSOLUTE_ZERO 0 |
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | 34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 3366e2e2f00f..0dfaf649b257 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -32,12 +32,11 @@ | |||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/ieee80211.h> | 34 | #include <linux/ieee80211.h> |
35 | |||
36 | #include "iwl-dev.h" | ||
37 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
38 | #include "iwl-agn-hw.h" | ||
39 | #include "iwl-agn.h" | ||
40 | #include "iwl-trans.h" | 36 | #include "iwl-trans.h" |
37 | #include "iwl-agn-hw.h" | ||
38 | #include "dev.h" | ||
39 | #include "agn.h" | ||
41 | 40 | ||
42 | static const u8 tid_to_ac[] = { | 41 | static const u8 tid_to_ac[] = { |
43 | IEEE80211_AC_BE, | 42 | IEEE80211_AC_BE, |
@@ -187,7 +186,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
187 | rate_idx = info->control.rates[0].idx; | 186 | rate_idx = info->control.rates[0].idx; |
188 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | 187 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || |
189 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | 188 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) |
190 | rate_idx = rate_lowest_index(&priv->bands[info->band], | 189 | rate_idx = rate_lowest_index( |
190 | &priv->eeprom_data->bands[info->band], | ||
191 | info->control.sta); | 191 | info->control.sta); |
192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | 192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ |
193 | if (info->band == IEEE80211_BAND_5GHZ) | 193 | if (info->band == IEEE80211_BAND_5GHZ) |
@@ -207,10 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
207 | priv->bt_full_concurrent) { | 207 | priv->bt_full_concurrent) { |
208 | /* operated as 1x1 in full concurrency mode */ | 208 | /* operated as 1x1 in full concurrency mode */ |
209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
210 | first_antenna(priv->hw_params.valid_tx_ant)); | 210 | first_antenna(priv->eeprom_data->valid_tx_ant)); |
211 | } else | 211 | } else |
212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant( |
213 | priv->hw_params.valid_tx_ant); | 213 | priv, priv->mgmt_tx_ant, |
214 | priv->eeprom_data->valid_tx_ant); | ||
214 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
215 | 216 | ||
216 | /* Set the rate in the TX cmd */ | 217 | /* Set the rate in the TX cmd */ |
@@ -296,7 +297,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
296 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 297 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
297 | struct iwl_station_priv *sta_priv = NULL; | 298 | struct iwl_station_priv *sta_priv = NULL; |
298 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 299 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
299 | struct iwl_device_cmd *dev_cmd = NULL; | 300 | struct iwl_device_cmd *dev_cmd; |
300 | struct iwl_tx_cmd *tx_cmd; | 301 | struct iwl_tx_cmd *tx_cmd; |
301 | __le16 fc; | 302 | __le16 fc; |
302 | u8 hdr_len; | 303 | u8 hdr_len; |
@@ -378,7 +379,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
378 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 379 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
379 | is_agg = true; | 380 | is_agg = true; |
380 | 381 | ||
381 | dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC); | 382 | dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans); |
382 | 383 | ||
383 | if (unlikely(!dev_cmd)) | 384 | if (unlikely(!dev_cmd)) |
384 | goto drop_unlock_priv; | 385 | goto drop_unlock_priv; |
@@ -486,11 +487,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
486 | if (sta_priv && sta_priv->client && !is_agg) | 487 | if (sta_priv && sta_priv->client && !is_agg) |
487 | atomic_inc(&sta_priv->pending_frames); | 488 | atomic_inc(&sta_priv->pending_frames); |
488 | 489 | ||
490 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
491 | iwl_scan_offchannel_skb(priv); | ||
492 | |||
489 | return 0; | 493 | return 0; |
490 | 494 | ||
491 | drop_unlock_sta: | 495 | drop_unlock_sta: |
492 | if (dev_cmd) | 496 | if (dev_cmd) |
493 | kmem_cache_free(iwl_tx_cmd_pool, dev_cmd); | 497 | iwl_trans_free_tx_cmd(priv->trans, dev_cmd); |
494 | spin_unlock(&priv->sta_lock); | 498 | spin_unlock(&priv->sta_lock); |
495 | drop_unlock_priv: | 499 | drop_unlock_priv: |
496 | return -1; | 500 | return -1; |
@@ -597,7 +601,7 @@ turn_off: | |||
597 | * time, or we hadn't time to drain the AC queues. | 601 | * time, or we hadn't time to drain the AC queues. |
598 | */ | 602 | */ |
599 | if (agg_state == IWL_AGG_ON) | 603 | if (agg_state == IWL_AGG_ON) |
600 | iwl_trans_tx_agg_disable(priv->trans, txq_id); | 604 | iwl_trans_txq_disable(priv->trans, txq_id); |
601 | else | 605 | else |
602 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | 606 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", |
603 | agg_state); | 607 | agg_state); |
@@ -686,9 +690,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
686 | 690 | ||
687 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | 691 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; |
688 | 692 | ||
689 | iwl_trans_tx_agg_setup(priv->trans, q, fifo, | 693 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, |
690 | sta_priv->sta_id, tid, | 694 | buf_size, ssn); |
691 | buf_size, ssn); | ||
692 | 695 | ||
693 | /* | 696 | /* |
694 | * If the limit is 0, then it wasn't initialised yet, | 697 | * If the limit is 0, then it wasn't initialised yet, |
@@ -753,8 +756,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
753 | IWL_DEBUG_TX_QUEUES(priv, | 756 | IWL_DEBUG_TX_QUEUES(priv, |
754 | "Can continue DELBA flow ssn = next_recl =" | 757 | "Can continue DELBA flow ssn = next_recl =" |
755 | " %d", tid_data->next_reclaimed); | 758 | " %d", tid_data->next_reclaimed); |
756 | iwl_trans_tx_agg_disable(priv->trans, | 759 | iwl_trans_txq_disable(priv->trans, |
757 | tid_data->agg.txq_id); | 760 | tid_data->agg.txq_id); |
758 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | 761 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); |
759 | tid_data->agg.state = IWL_AGG_OFF; | 762 | tid_data->agg.state = IWL_AGG_OFF; |
760 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); | 763 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); |
@@ -1136,6 +1139,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1136 | struct sk_buff *skb; | 1139 | struct sk_buff *skb; |
1137 | struct iwl_rxon_context *ctx; | 1140 | struct iwl_rxon_context *ctx; |
1138 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | 1141 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); |
1142 | bool is_offchannel_skb; | ||
1139 | 1143 | ||
1140 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | 1144 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> |
1141 | IWLAGN_TX_RES_TID_POS; | 1145 | IWLAGN_TX_RES_TID_POS; |
@@ -1149,6 +1153,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1149 | 1153 | ||
1150 | __skb_queue_head_init(&skbs); | 1154 | __skb_queue_head_init(&skbs); |
1151 | 1155 | ||
1156 | is_offchannel_skb = false; | ||
1157 | |||
1152 | if (tx_resp->frame_count == 1) { | 1158 | if (tx_resp->frame_count == 1) { |
1153 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 1159 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); |
1154 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | 1160 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); |
@@ -1189,8 +1195,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1189 | 1195 | ||
1190 | info = IEEE80211_SKB_CB(skb); | 1196 | info = IEEE80211_SKB_CB(skb); |
1191 | ctx = info->driver_data[0]; | 1197 | ctx = info->driver_data[0]; |
1192 | kmem_cache_free(iwl_tx_cmd_pool, | 1198 | iwl_trans_free_tx_cmd(priv->trans, |
1193 | (info->driver_data[1])); | 1199 | info->driver_data[1]); |
1194 | 1200 | ||
1195 | memset(&info->status, 0, sizeof(info->status)); | 1201 | memset(&info->status, 0, sizeof(info->status)); |
1196 | 1202 | ||
@@ -1225,10 +1231,19 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1225 | if (!is_agg) | 1231 | if (!is_agg) |
1226 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1232 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
1227 | 1233 | ||
1234 | is_offchannel_skb = | ||
1235 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | ||
1228 | freed++; | 1236 | freed++; |
1229 | } | 1237 | } |
1230 | 1238 | ||
1231 | WARN_ON(!is_agg && freed != 1); | 1239 | WARN_ON(!is_agg && freed != 1); |
1240 | |||
1241 | /* | ||
1242 | * An offchannel frame can be send only on the AUX queue, where | ||
1243 | * there is no aggregation (and reordering) so it only is single | ||
1244 | * skb is expected to be processed. | ||
1245 | */ | ||
1246 | WARN_ON(is_offchannel_skb && freed != 1); | ||
1232 | } | 1247 | } |
1233 | 1248 | ||
1234 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 1249 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
@@ -1239,6 +1254,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1239 | ieee80211_tx_status(priv->hw, skb); | 1254 | ieee80211_tx_status(priv->hw, skb); |
1240 | } | 1255 | } |
1241 | 1256 | ||
1257 | if (is_offchannel_skb) | ||
1258 | iwl_scan_offchannel_skb_status(priv); | ||
1259 | |||
1242 | return 0; | 1260 | return 0; |
1243 | } | 1261 | } |
1244 | 1262 | ||
@@ -1341,7 +1359,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1341 | WARN_ON_ONCE(1); | 1359 | WARN_ON_ONCE(1); |
1342 | 1360 | ||
1343 | info = IEEE80211_SKB_CB(skb); | 1361 | info = IEEE80211_SKB_CB(skb); |
1344 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 1362 | iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); |
1345 | 1363 | ||
1346 | if (freed == 1) { | 1364 | if (freed == 1) { |
1347 | /* this is the first skb we deliver in this batch */ | 1365 | /* this is the first skb we deliver in this batch */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index bc40dc68b0f4..b3a314ba48c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -30,15 +30,16 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | 32 | ||
33 | #include "iwl-dev.h" | ||
34 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
35 | #include "iwl-agn-hw.h" | 34 | #include "iwl-agn-hw.h" |
36 | #include "iwl-agn.h" | ||
37 | #include "iwl-agn-calib.h" | ||
38 | #include "iwl-trans.h" | 35 | #include "iwl-trans.h" |
39 | #include "iwl-fh.h" | 36 | #include "iwl-fh.h" |
40 | #include "iwl-op-mode.h" | 37 | #include "iwl-op-mode.h" |
41 | 38 | ||
39 | #include "dev.h" | ||
40 | #include "agn.h" | ||
41 | #include "calib.h" | ||
42 | |||
42 | /****************************************************************************** | 43 | /****************************************************************************** |
43 | * | 44 | * |
44 | * uCode download functions | 45 | * uCode download functions |
@@ -60,8 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) | |||
60 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) | 61 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) |
61 | { | 62 | { |
62 | struct iwl_calib_xtal_freq_cmd cmd; | 63 | struct iwl_calib_xtal_freq_cmd cmd; |
63 | __le16 *xtal_calib = | 64 | __le16 *xtal_calib = priv->eeprom_data->xtal_calib; |
64 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); | ||
65 | 65 | ||
66 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 66 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); |
67 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 67 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
@@ -72,12 +72,10 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | |||
72 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | 72 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) |
73 | { | 73 | { |
74 | struct iwl_calib_temperature_offset_cmd cmd; | 74 | struct iwl_calib_temperature_offset_cmd cmd; |
75 | __le16 *offset_calib = | ||
76 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
77 | 75 | ||
78 | memset(&cmd, 0, sizeof(cmd)); | 76 | memset(&cmd, 0, sizeof(cmd)); |
79 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 77 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
80 | memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); | 78 | cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature; |
81 | if (!(cmd.radio_sensor_offset)) | 79 | if (!(cmd.radio_sensor_offset)) |
82 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; | 80 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; |
83 | 81 | ||
@@ -89,27 +87,17 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
89 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | 87 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) |
90 | { | 88 | { |
91 | struct iwl_calib_temperature_offset_v2_cmd cmd; | 89 | struct iwl_calib_temperature_offset_v2_cmd cmd; |
92 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, | ||
93 | EEPROM_KELVIN_TEMPERATURE); | ||
94 | __le16 *offset_calib_low = | ||
95 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
96 | struct iwl_eeprom_calib_hdr *hdr; | ||
97 | 90 | ||
98 | memset(&cmd, 0, sizeof(cmd)); | 91 | memset(&cmd, 0, sizeof(cmd)); |
99 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 92 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
100 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 93 | cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature; |
101 | EEPROM_CALIB_ALL); | 94 | cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature; |
102 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 95 | if (!cmd.radio_sensor_offset_low) { |
103 | sizeof(*offset_calib_high)); | ||
104 | memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, | ||
105 | sizeof(*offset_calib_low)); | ||
106 | if (!(cmd.radio_sensor_offset_low)) { | ||
107 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | 96 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); |
108 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | 97 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; |
109 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | 98 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; |
110 | } | 99 | } |
111 | memcpy(&cmd.burntVoltageRef, &hdr->voltage, | 100 | cmd.burntVoltageRef = priv->eeprom_data->calib_voltage; |
112 | sizeof(hdr->voltage)); | ||
113 | 101 | ||
114 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | 102 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", |
115 | le16_to_cpu(cmd.radio_sensor_offset_high)); | 103 | le16_to_cpu(cmd.radio_sensor_offset_high)); |
@@ -177,7 +165,7 @@ int iwl_init_alive_start(struct iwl_priv *priv) | |||
177 | return 0; | 165 | return 0; |
178 | } | 166 | } |
179 | 167 | ||
180 | int iwl_send_wimax_coex(struct iwl_priv *priv) | 168 | static int iwl_send_wimax_coex(struct iwl_priv *priv) |
181 | { | 169 | { |
182 | struct iwl_wimax_coex_cmd coex_cmd; | 170 | struct iwl_wimax_coex_cmd coex_cmd; |
183 | 171 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 67b28aa7f9be..10e47938b635 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -113,7 +113,7 @@ enum iwl_led_mode { | |||
113 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0 | 113 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0 |
114 | 114 | ||
115 | /* TX queue watchdog timeouts in mSecs */ | 115 | /* TX queue watchdog timeouts in mSecs */ |
116 | #define IWL_WATCHHDOG_DISABLED 0 | 116 | #define IWL_WATCHDOG_DISABLED 0 |
117 | #define IWL_DEF_WD_TIMEOUT 2000 | 117 | #define IWL_DEF_WD_TIMEOUT 2000 |
118 | #define IWL_LONG_WD_TIMEOUT 10000 | 118 | #define IWL_LONG_WD_TIMEOUT 10000 |
119 | #define IWL_MAX_WD_TIMEOUT 120000 | 119 | #define IWL_MAX_WD_TIMEOUT 120000 |
@@ -143,7 +143,7 @@ enum iwl_led_mode { | |||
143 | * @chain_noise_scale: default chain noise scale used for gain computation | 143 | * @chain_noise_scale: default chain noise scale used for gain computation |
144 | * @wd_timeout: TX queues watchdog timeout | 144 | * @wd_timeout: TX queues watchdog timeout |
145 | * @max_event_log_size: size of event log buffer size for ucode event logging | 145 | * @max_event_log_size: size of event log buffer size for ucode event logging |
146 | * @shadow_reg_enable: HW shadhow register bit | 146 | * @shadow_reg_enable: HW shadow register support |
147 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up | 147 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up |
148 | * @no_idle_support: do not support idle mode | 148 | * @no_idle_support: do not support idle mode |
149 | */ | 149 | */ |
@@ -182,13 +182,34 @@ struct iwl_bt_params { | |||
182 | bool bt_sco_disable; | 182 | bool bt_sco_disable; |
183 | bool bt_session_2; | 183 | bool bt_session_2; |
184 | }; | 184 | }; |
185 | |||
185 | /* | 186 | /* |
186 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | 187 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic |
188 | * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 | ||
187 | */ | 189 | */ |
188 | struct iwl_ht_params { | 190 | struct iwl_ht_params { |
191 | enum ieee80211_smps_mode smps_mode; | ||
189 | const bool ht_greenfield_support; /* if used set to true */ | 192 | const bool ht_greenfield_support; /* if used set to true */ |
190 | bool use_rts_for_aggregation; | 193 | bool use_rts_for_aggregation; |
191 | enum ieee80211_smps_mode smps_mode; | 194 | u8 ht40_bands; |
195 | }; | ||
196 | |||
197 | /* | ||
198 | * information on how to parse the EEPROM | ||
199 | */ | ||
200 | #define EEPROM_REG_BAND_1_CHANNELS 0x08 | ||
201 | #define EEPROM_REG_BAND_2_CHANNELS 0x26 | ||
202 | #define EEPROM_REG_BAND_3_CHANNELS 0x42 | ||
203 | #define EEPROM_REG_BAND_4_CHANNELS 0x5C | ||
204 | #define EEPROM_REG_BAND_5_CHANNELS 0x74 | ||
205 | #define EEPROM_REG_BAND_24_HT40_CHANNELS 0x82 | ||
206 | #define EEPROM_REG_BAND_52_HT40_CHANNELS 0x92 | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80 | ||
208 | #define EEPROM_REGULATORY_BAND_NO_HT40 0 | ||
209 | |||
210 | struct iwl_eeprom_params { | ||
211 | const u8 regulatory_bands[7]; | ||
212 | bool enhanced_txpower; | ||
192 | }; | 213 | }; |
193 | 214 | ||
194 | /** | 215 | /** |
@@ -243,6 +264,7 @@ struct iwl_cfg { | |||
243 | /* params likely to change within a device family */ | 264 | /* params likely to change within a device family */ |
244 | const struct iwl_ht_params *ht_params; | 265 | const struct iwl_ht_params *ht_params; |
245 | const struct iwl_bt_params *bt_params; | 266 | const struct iwl_bt_params *bt_params; |
267 | const struct iwl_eeprom_params *eeprom_params; | ||
246 | const bool need_temp_offset_calib; /* if used set to true */ | 268 | const bool need_temp_offset_calib; /* if used set to true */ |
247 | const bool no_xtal_calib; | 269 | const bool no_xtal_calib; |
248 | enum iwl_led_mode led_mode; | 270 | enum iwl_led_mode led_mode; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 59750543fce7..34a5287dfc2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -97,13 +97,10 @@ | |||
97 | /* | 97 | /* |
98 | * Hardware revision info | 98 | * Hardware revision info |
99 | * Bit fields: | 99 | * Bit fields: |
100 | * 31-8: Reserved | 100 | * 31-16: Reserved |
101 | * 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions | 101 | * 15-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions |
102 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | 102 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D |
103 | * 1-0: "Dash" (-) value, as in A-1, etc. | 103 | * 1-0: "Dash" (-) value, as in A-1, etc. |
104 | * | ||
105 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | ||
106 | * NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965). | ||
107 | */ | 104 | */ |
108 | #define CSR_HW_REV (CSR_BASE+0x028) | 105 | #define CSR_HW_REV (CSR_BASE+0x028) |
109 | 106 | ||
@@ -155,9 +152,21 @@ | |||
155 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) | 152 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) |
156 | 153 | ||
157 | /* Bits for CSR_HW_IF_CONFIG_REG */ | 154 | /* Bits for CSR_HW_IF_CONFIG_REG */ |
158 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) | 155 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) |
159 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | 156 | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) |
157 | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0) | ||
158 | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) | ||
160 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) | 159 | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) |
160 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE (0x00000C00) | ||
161 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH (0x00003000) | ||
162 | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP (0x0000C000) | ||
163 | |||
164 | #define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH (0) | ||
165 | #define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP (2) | ||
166 | #define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER (6) | ||
167 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE (10) | ||
168 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH (12) | ||
169 | #define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP (14) | ||
161 | 170 | ||
162 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) | 171 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) |
163 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | 172 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) |
@@ -270,7 +279,10 @@ | |||
270 | 279 | ||
271 | 280 | ||
272 | /* HW REV */ | 281 | /* HW REV */ |
273 | #define CSR_HW_REV_TYPE_MSK (0x00001F0) | 282 | #define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0) |
283 | #define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2) | ||
284 | |||
285 | #define CSR_HW_REV_TYPE_MSK (0x000FFF0) | ||
274 | #define CSR_HW_REV_TYPE_5300 (0x0000020) | 286 | #define CSR_HW_REV_TYPE_5300 (0x0000020) |
275 | #define CSR_HW_REV_TYPE_5350 (0x0000030) | 287 | #define CSR_HW_REV_TYPE_5350 (0x0000030) |
276 | #define CSR_HW_REV_TYPE_5100 (0x0000050) | 288 | #define CSR_HW_REV_TYPE_5100 (0x0000050) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c index 2d1b42847b9b..0f8fcd1d4fe2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/iwlwifi/iwl-debug.c | |||
@@ -62,6 +62,7 @@ | |||
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/interrupt.h> | 64 | #include <linux/interrupt.h> |
65 | #include <linux/export.h> | ||
65 | #include "iwl-debug.h" | 66 | #include "iwl-debug.h" |
66 | #include "iwl-devtrace.h" | 67 | #include "iwl-devtrace.h" |
67 | 68 | ||
@@ -81,8 +82,11 @@ void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \ | |||
81 | } | 82 | } |
82 | 83 | ||
83 | __iwl_fn(warn) | 84 | __iwl_fn(warn) |
85 | EXPORT_SYMBOL_GPL(__iwl_warn); | ||
84 | __iwl_fn(info) | 86 | __iwl_fn(info) |
87 | EXPORT_SYMBOL_GPL(__iwl_info); | ||
85 | __iwl_fn(crit) | 88 | __iwl_fn(crit) |
89 | EXPORT_SYMBOL_GPL(__iwl_crit); | ||
86 | 90 | ||
87 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | 91 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, |
88 | const char *fmt, ...) | 92 | const char *fmt, ...) |
@@ -103,6 +107,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, | |||
103 | trace_iwlwifi_err(&vaf); | 107 | trace_iwlwifi_err(&vaf); |
104 | va_end(args); | 108 | va_end(args); |
105 | } | 109 | } |
110 | EXPORT_SYMBOL_GPL(__iwl_err); | ||
106 | 111 | ||
107 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) | 112 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) |
108 | void __iwl_dbg(struct device *dev, | 113 | void __iwl_dbg(struct device *dev, |
@@ -125,4 +130,5 @@ void __iwl_dbg(struct device *dev, | |||
125 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); | 130 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); |
126 | va_end(args); | 131 | va_end(args); |
127 | } | 132 | } |
133 | EXPORT_SYMBOL_GPL(__iwl_dbg); | ||
128 | #endif | 134 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 8376b842bdba..42b20b0e83bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -38,13 +38,14 @@ static inline bool iwl_have_debug_level(u32 level) | |||
38 | } | 38 | } |
39 | 39 | ||
40 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace, | 40 | void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace, |
41 | const char *fmt, ...); | 41 | const char *fmt, ...) __printf(4, 5); |
42 | void __iwl_warn(struct device *dev, const char *fmt, ...); | 42 | void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3); |
43 | void __iwl_info(struct device *dev, const char *fmt, ...); | 43 | void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3); |
44 | void __iwl_crit(struct device *dev, const char *fmt, ...); | 44 | void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); |
45 | 45 | ||
46 | /* No matter what is m (priv, bus, trans), this will work */ | 46 | /* No matter what is m (priv, bus, trans), this will work */ |
47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | 47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) |
48 | #define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a) | ||
48 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | 49 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) |
49 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | 50 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) |
50 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | 51 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) |
@@ -52,9 +53,9 @@ void __iwl_crit(struct device *dev, const char *fmt, ...); | |||
52 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) | 53 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) |
53 | void __iwl_dbg(struct device *dev, | 54 | void __iwl_dbg(struct device *dev, |
54 | u32 level, bool limit, const char *function, | 55 | u32 level, bool limit, const char *function, |
55 | const char *fmt, ...); | 56 | const char *fmt, ...) __printf(5, 6); |
56 | #else | 57 | #else |
57 | static inline void | 58 | __printf(5, 6) static inline void |
58 | __iwl_dbg(struct device *dev, | 59 | __iwl_dbg(struct device *dev, |
59 | u32 level, bool limit, const char *function, | 60 | u32 level, bool limit, const char *function, |
60 | const char *fmt, ...) | 61 | const char *fmt, ...) |
@@ -69,6 +70,8 @@ do { \ | |||
69 | 70 | ||
70 | #define IWL_DEBUG(m, level, fmt, args...) \ | 71 | #define IWL_DEBUG(m, level, fmt, args...) \ |
71 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | 72 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) |
73 | #define IWL_DEBUG_DEV(dev, level, fmt, args...) \ | ||
74 | __iwl_dbg((dev), level, false, __func__, fmt, ##args) | ||
72 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ | 75 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ |
73 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | 76 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) |
74 | 77 | ||
@@ -153,7 +156,7 @@ do { \ | |||
153 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) | 156 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) |
154 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) | 157 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) |
155 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) | 158 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) |
156 | #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) | 159 | #define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a) |
157 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | 160 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) |
158 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) | 161 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) |
159 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | 162 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 91f45e71e0a2..70191ddbd8f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -42,4 +42,9 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | |||
42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
43 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | 43 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); |
44 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); | 44 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); |
45 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_info); | ||
46 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_warn); | ||
47 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_crit); | ||
48 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_err); | ||
49 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dbg); | ||
45 | #endif | 50 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 06203d6a1d86..65364793021f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define __IWLWIFI_DEVICE_TRACE | 28 | #define __IWLWIFI_DEVICE_TRACE |
29 | 29 | ||
30 | #include <linux/tracepoint.h> | 30 | #include <linux/tracepoint.h> |
31 | #include <linux/device.h> | ||
31 | 32 | ||
32 | 33 | ||
33 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | 34 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index fac67a526a30..49df0e9d5c5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -77,8 +77,33 @@ | |||
77 | /* private includes */ | 77 | /* private includes */ |
78 | #include "iwl-fw-file.h" | 78 | #include "iwl-fw-file.h" |
79 | 79 | ||
80 | /****************************************************************************** | ||
81 | * | ||
82 | * module boiler plate | ||
83 | * | ||
84 | ******************************************************************************/ | ||
85 | |||
86 | /* | ||
87 | * module name, copyright, version, etc. | ||
88 | */ | ||
89 | #define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux" | ||
90 | |||
91 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
92 | #define VD "d" | ||
93 | #else | ||
94 | #define VD | ||
95 | #endif | ||
96 | |||
97 | #define DRV_VERSION IWLWIFI_VERSION VD | ||
98 | |||
99 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | ||
100 | MODULE_VERSION(DRV_VERSION); | ||
101 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | ||
102 | MODULE_LICENSE("GPL"); | ||
103 | |||
80 | /** | 104 | /** |
81 | * struct iwl_drv - drv common data | 105 | * struct iwl_drv - drv common data |
106 | * @list: list of drv structures using this opmode | ||
82 | * @fw: the iwl_fw structure | 107 | * @fw: the iwl_fw structure |
83 | * @op_mode: the running op_mode | 108 | * @op_mode: the running op_mode |
84 | * @trans: transport layer | 109 | * @trans: transport layer |
@@ -89,6 +114,7 @@ | |||
89 | * @request_firmware_complete: the firmware has been obtained from user space | 114 | * @request_firmware_complete: the firmware has been obtained from user space |
90 | */ | 115 | */ |
91 | struct iwl_drv { | 116 | struct iwl_drv { |
117 | struct list_head list; | ||
92 | struct iwl_fw fw; | 118 | struct iwl_fw fw; |
93 | 119 | ||
94 | struct iwl_op_mode *op_mode; | 120 | struct iwl_op_mode *op_mode; |
@@ -102,7 +128,17 @@ struct iwl_drv { | |||
102 | struct completion request_firmware_complete; | 128 | struct completion request_firmware_complete; |
103 | }; | 129 | }; |
104 | 130 | ||
131 | #define DVM_OP_MODE 0 | ||
132 | #define MVM_OP_MODE 1 | ||
105 | 133 | ||
134 | static struct iwlwifi_opmode_table { | ||
135 | const char *name; /* name: iwldvm, iwlmvm, etc */ | ||
136 | const struct iwl_op_mode_ops *ops; /* pointer to op_mode ops */ | ||
137 | struct list_head drv; /* list of devices using this op_mode */ | ||
138 | } iwlwifi_opmode_table[] = { /* ops set when driver is initialized */ | ||
139 | { .name = "iwldvm", .ops = NULL }, | ||
140 | { .name = "iwlmvm", .ops = NULL }, | ||
141 | }; | ||
106 | 142 | ||
107 | /* | 143 | /* |
108 | * struct fw_sec: Just for the image parsing proccess. | 144 | * struct fw_sec: Just for the image parsing proccess. |
@@ -721,7 +757,6 @@ static int validate_sec_sizes(struct iwl_drv *drv, | |||
721 | return 0; | 757 | return 0; |
722 | } | 758 | } |
723 | 759 | ||
724 | |||
725 | /** | 760 | /** |
726 | * iwl_ucode_callback - callback when firmware was loaded | 761 | * iwl_ucode_callback - callback when firmware was loaded |
727 | * | 762 | * |
@@ -733,6 +768,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
733 | struct iwl_drv *drv = context; | 768 | struct iwl_drv *drv = context; |
734 | struct iwl_fw *fw = &drv->fw; | 769 | struct iwl_fw *fw = &drv->fw; |
735 | struct iwl_ucode_header *ucode; | 770 | struct iwl_ucode_header *ucode; |
771 | struct iwlwifi_opmode_table *op; | ||
736 | int err; | 772 | int err; |
737 | struct iwl_firmware_pieces pieces; | 773 | struct iwl_firmware_pieces pieces; |
738 | const unsigned int api_max = drv->cfg->ucode_api_max; | 774 | const unsigned int api_max = drv->cfg->ucode_api_max; |
@@ -862,10 +898,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
862 | /* We have our copies now, allow OS release its copies */ | 898 | /* We have our copies now, allow OS release its copies */ |
863 | release_firmware(ucode_raw); | 899 | release_firmware(ucode_raw); |
864 | 900 | ||
865 | drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw); | 901 | op = &iwlwifi_opmode_table[DVM_OP_MODE]; |
866 | 902 | ||
867 | if (!drv->op_mode) | 903 | /* add this device to the list of devices using this op_mode */ |
868 | goto out_unbind; | 904 | list_add_tail(&drv->list, &op->drv); |
905 | |||
906 | if (op->ops) { | ||
907 | const struct iwl_op_mode_ops *ops = op->ops; | ||
908 | drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw); | ||
909 | |||
910 | if (!drv->op_mode) | ||
911 | goto out_unbind; | ||
912 | } else { | ||
913 | request_module_nowait("%s", op->name); | ||
914 | } | ||
869 | 915 | ||
870 | /* | 916 | /* |
871 | * Complete the firmware request last so that | 917 | * Complete the firmware request last so that |
@@ -943,6 +989,67 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
943 | .auto_agg = true, | 989 | .auto_agg = true, |
944 | /* the rest are 0 by default */ | 990 | /* the rest are 0 by default */ |
945 | }; | 991 | }; |
992 | EXPORT_SYMBOL_GPL(iwlwifi_mod_params); | ||
993 | |||
994 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) | ||
995 | { | ||
996 | int i; | ||
997 | struct iwl_drv *drv; | ||
998 | |||
999 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { | ||
1000 | if (strcmp(iwlwifi_opmode_table[i].name, name)) | ||
1001 | continue; | ||
1002 | iwlwifi_opmode_table[i].ops = ops; | ||
1003 | list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) | ||
1004 | drv->op_mode = ops->start(drv->trans, drv->cfg, | ||
1005 | &drv->fw); | ||
1006 | return 0; | ||
1007 | } | ||
1008 | return -EIO; | ||
1009 | } | ||
1010 | EXPORT_SYMBOL_GPL(iwl_opmode_register); | ||
1011 | |||
1012 | void iwl_opmode_deregister(const char *name) | ||
1013 | { | ||
1014 | int i; | ||
1015 | struct iwl_drv *drv; | ||
1016 | |||
1017 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { | ||
1018 | if (strcmp(iwlwifi_opmode_table[i].name, name)) | ||
1019 | continue; | ||
1020 | iwlwifi_opmode_table[i].ops = NULL; | ||
1021 | |||
1022 | /* call the stop routine for all devices */ | ||
1023 | list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) { | ||
1024 | if (drv->op_mode) { | ||
1025 | iwl_op_mode_stop(drv->op_mode); | ||
1026 | drv->op_mode = NULL; | ||
1027 | } | ||
1028 | } | ||
1029 | return; | ||
1030 | } | ||
1031 | } | ||
1032 | EXPORT_SYMBOL_GPL(iwl_opmode_deregister); | ||
1033 | |||
1034 | static int __init iwl_drv_init(void) | ||
1035 | { | ||
1036 | int i; | ||
1037 | |||
1038 | for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) | ||
1039 | INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv); | ||
1040 | |||
1041 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | ||
1042 | pr_info(DRV_COPYRIGHT "\n"); | ||
1043 | |||
1044 | return iwl_pci_register_driver(); | ||
1045 | } | ||
1046 | module_init(iwl_drv_init); | ||
1047 | |||
1048 | static void __exit iwl_drv_exit(void) | ||
1049 | { | ||
1050 | iwl_pci_unregister_driver(); | ||
1051 | } | ||
1052 | module_exit(iwl_drv_exit); | ||
946 | 1053 | ||
947 | #ifdef CONFIG_IWLWIFI_DEBUG | 1054 | #ifdef CONFIG_IWLWIFI_DEBUG |
948 | module_param_named(debug, iwlwifi_mod_params.debug_level, uint, | 1055 | module_param_named(debug, iwlwifi_mod_params.debug_level, uint, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c new file mode 100644 index 000000000000..c87a05cbec12 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -0,0 +1,900 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | #include "iwl-modparams.h" | ||
66 | #include "iwl-eeprom-parse.h" | ||
67 | |||
68 | /* EEPROM offset definitions */ | ||
69 | |||
70 | /* indirect access definitions */ | ||
71 | #define ADDRESS_MSK 0x0000FFFF | ||
72 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
73 | #define INDIRECT_HOST 0x00010000 | ||
74 | #define INDIRECT_GENERAL 0x00020000 | ||
75 | #define INDIRECT_REGULATORY 0x00030000 | ||
76 | #define INDIRECT_CALIBRATION 0x00040000 | ||
77 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
78 | #define INDIRECT_OTHERS 0x00060000 | ||
79 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
80 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
81 | #define INDIRECT_ADDRESS 0x00100000 | ||
82 | |||
83 | /* corresponding link offsets in EEPROM */ | ||
84 | #define EEPROM_LINK_HOST (2*0x64) | ||
85 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
86 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
87 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
88 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
89 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
90 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
91 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
92 | |||
93 | /* General */ | ||
94 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
95 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
96 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
97 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
98 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
99 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
100 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
101 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
102 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
103 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
104 | |||
105 | /* calibration */ | ||
106 | struct iwl_eeprom_calib_hdr { | ||
107 | u8 version; | ||
108 | u8 pa_type; | ||
109 | __le16 voltage; | ||
110 | } __packed; | ||
111 | |||
112 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
113 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
114 | |||
115 | /* temperature */ | ||
116 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
117 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
118 | |||
119 | /* | ||
120 | * EEPROM bands | ||
121 | * These are the channel numbers from each band in the order | ||
122 | * that they are stored in the EEPROM band information. Note | ||
123 | * that EEPROM bands aren't the same as mac80211 bands, and | ||
124 | * there are even special "ht40 bands" in the EEPROM. | ||
125 | */ | ||
126 | static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */ | ||
127 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
128 | }; | ||
129 | |||
130 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
131 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
132 | }; | ||
133 | |||
134 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
135 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
136 | }; | ||
137 | |||
138 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
139 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
140 | }; | ||
141 | |||
142 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
143 | 145, 149, 153, 157, 161, 165 | ||
144 | }; | ||
145 | |||
146 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
147 | 1, 2, 3, 4, 5, 6, 7 | ||
148 | }; | ||
149 | |||
150 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
151 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
152 | }; | ||
153 | |||
154 | #define IWL_NUM_CHANNELS (ARRAY_SIZE(iwl_eeprom_band_1) + \ | ||
155 | ARRAY_SIZE(iwl_eeprom_band_2) + \ | ||
156 | ARRAY_SIZE(iwl_eeprom_band_3) + \ | ||
157 | ARRAY_SIZE(iwl_eeprom_band_4) + \ | ||
158 | ARRAY_SIZE(iwl_eeprom_band_5)) | ||
159 | |||
160 | /* rate data (static) */ | ||
161 | static struct ieee80211_rate iwl_cfg80211_rates[] = { | ||
162 | { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, | ||
163 | { .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1, | ||
164 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
165 | { .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2, | ||
166 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
167 | { .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3, | ||
168 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||
169 | { .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, }, | ||
170 | { .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, }, | ||
171 | { .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, }, | ||
172 | { .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, }, | ||
173 | { .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, }, | ||
174 | { .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, }, | ||
175 | { .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, }, | ||
176 | { .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, }, | ||
177 | }; | ||
178 | #define RATES_24_OFFS 0 | ||
179 | #define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates) | ||
180 | #define RATES_52_OFFS 4 | ||
181 | #define N_RATES_52 (N_RATES_24 - RATES_52_OFFS) | ||
182 | |||
183 | /* EEPROM reading functions */ | ||
184 | |||
185 | static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset) | ||
186 | { | ||
187 | if (WARN_ON(offset + sizeof(u16) > eeprom_size)) | ||
188 | return 0; | ||
189 | return le16_to_cpup((__le16 *)(eeprom + offset)); | ||
190 | } | ||
191 | |||
192 | static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size, | ||
193 | u32 address) | ||
194 | { | ||
195 | u16 offset = 0; | ||
196 | |||
197 | if ((address & INDIRECT_ADDRESS) == 0) | ||
198 | return address; | ||
199 | |||
200 | switch (address & INDIRECT_TYPE_MSK) { | ||
201 | case INDIRECT_HOST: | ||
202 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
203 | EEPROM_LINK_HOST); | ||
204 | break; | ||
205 | case INDIRECT_GENERAL: | ||
206 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
207 | EEPROM_LINK_GENERAL); | ||
208 | break; | ||
209 | case INDIRECT_REGULATORY: | ||
210 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
211 | EEPROM_LINK_REGULATORY); | ||
212 | break; | ||
213 | case INDIRECT_TXP_LIMIT: | ||
214 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
215 | EEPROM_LINK_TXP_LIMIT); | ||
216 | break; | ||
217 | case INDIRECT_TXP_LIMIT_SIZE: | ||
218 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
219 | EEPROM_LINK_TXP_LIMIT_SIZE); | ||
220 | break; | ||
221 | case INDIRECT_CALIBRATION: | ||
222 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
223 | EEPROM_LINK_CALIBRATION); | ||
224 | break; | ||
225 | case INDIRECT_PROCESS_ADJST: | ||
226 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
227 | EEPROM_LINK_PROCESS_ADJST); | ||
228 | break; | ||
229 | case INDIRECT_OTHERS: | ||
230 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
231 | EEPROM_LINK_OTHERS); | ||
232 | break; | ||
233 | default: | ||
234 | WARN_ON(1); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | /* translate the offset from words to byte */ | ||
239 | return (address & ADDRESS_MSK) + (offset << 1); | ||
240 | } | ||
241 | |||
242 | static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size, | ||
243 | u32 offset) | ||
244 | { | ||
245 | u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset); | ||
246 | |||
247 | if (WARN_ON(address >= eeprom_size)) | ||
248 | return NULL; | ||
249 | |||
250 | return &eeprom[address]; | ||
251 | } | ||
252 | |||
253 | static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size, | ||
254 | struct iwl_eeprom_data *data) | ||
255 | { | ||
256 | struct iwl_eeprom_calib_hdr *hdr; | ||
257 | |||
258 | hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
259 | EEPROM_CALIB_ALL); | ||
260 | if (!hdr) | ||
261 | return -ENODATA; | ||
262 | data->calib_version = hdr->version; | ||
263 | data->calib_voltage = hdr->voltage; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * enum iwl_eeprom_channel_flags - channel flags in EEPROM | ||
270 | * @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo | ||
271 | * @EEPROM_CHANNEL_IBSS: usable as an IBSS channel | ||
272 | * @EEPROM_CHANNEL_ACTIVE: active scanning allowed | ||
273 | * @EEPROM_CHANNEL_RADAR: radar detection required | ||
274 | * @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?) | ||
275 | * @EEPROM_CHANNEL_DFS: dynamic freq selection candidate | ||
276 | */ | ||
277 | enum iwl_eeprom_channel_flags { | ||
278 | EEPROM_CHANNEL_VALID = BIT(0), | ||
279 | EEPROM_CHANNEL_IBSS = BIT(1), | ||
280 | EEPROM_CHANNEL_ACTIVE = BIT(3), | ||
281 | EEPROM_CHANNEL_RADAR = BIT(4), | ||
282 | EEPROM_CHANNEL_WIDE = BIT(5), | ||
283 | EEPROM_CHANNEL_DFS = BIT(7), | ||
284 | }; | ||
285 | |||
286 | /** | ||
287 | * struct iwl_eeprom_channel - EEPROM channel data | ||
288 | * @flags: %EEPROM_CHANNEL_* flags | ||
289 | * @max_power_avg: max power (in dBm) on this channel, at most 31 dBm | ||
290 | */ | ||
291 | struct iwl_eeprom_channel { | ||
292 | u8 flags; | ||
293 | s8 max_power_avg; | ||
294 | } __packed; | ||
295 | |||
296 | |||
297 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
298 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
299 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
300 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
301 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
302 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
303 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
304 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
305 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
306 | }; | ||
307 | |||
308 | /** | ||
309 | * iwl_eeprom_enhanced_txpwr structure | ||
310 | * @flags: entry flags | ||
311 | * @channel: channel number | ||
312 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
313 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
314 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
315 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
316 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
317 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
318 | * | ||
319 | * This structure presents the enhanced regulatory tx power limit layout | ||
320 | * in an EEPROM image. | ||
321 | */ | ||
322 | struct iwl_eeprom_enhanced_txpwr { | ||
323 | u8 flags; | ||
324 | u8 channel; | ||
325 | s8 chain_a_max; | ||
326 | s8 chain_b_max; | ||
327 | s8 chain_c_max; | ||
328 | u8 delta_20_in_40; | ||
329 | s8 mimo2_max; | ||
330 | s8 mimo3_max; | ||
331 | } __packed; | ||
332 | |||
333 | static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data, | ||
334 | struct iwl_eeprom_enhanced_txpwr *txp) | ||
335 | { | ||
336 | s8 result = 0; /* (.5 dBm) */ | ||
337 | |||
338 | /* Take the highest tx power from any valid chains */ | ||
339 | if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result) | ||
340 | result = txp->chain_a_max; | ||
341 | |||
342 | if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result) | ||
343 | result = txp->chain_b_max; | ||
344 | |||
345 | if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result) | ||
346 | result = txp->chain_c_max; | ||
347 | |||
348 | if ((data->valid_tx_ant == ANT_AB || | ||
349 | data->valid_tx_ant == ANT_BC || | ||
350 | data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result) | ||
351 | result = txp->mimo2_max; | ||
352 | |||
353 | if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result) | ||
354 | result = txp->mimo3_max; | ||
355 | |||
356 | return result; | ||
357 | } | ||
358 | |||
359 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
360 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
361 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
362 | |||
363 | #define TXP_CHECK_AND_PRINT(x) \ | ||
364 | ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "") | ||
365 | |||
366 | static void | ||
367 | iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data, | ||
368 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
369 | int n_channels, s8 max_txpower_avg) | ||
370 | { | ||
371 | int ch_idx; | ||
372 | enum ieee80211_band band; | ||
373 | |||
374 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
375 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
376 | |||
377 | for (ch_idx = 0; ch_idx < n_channels; ch_idx++) { | ||
378 | struct ieee80211_channel *chan = &data->channels[ch_idx]; | ||
379 | |||
380 | /* update matching channel or from common data only */ | ||
381 | if (txp->channel != 0 && chan->hw_value != txp->channel) | ||
382 | continue; | ||
383 | |||
384 | /* update matching band only */ | ||
385 | if (band != chan->band) | ||
386 | continue; | ||
387 | |||
388 | if (chan->max_power < max_txpower_avg && | ||
389 | !(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ)) | ||
390 | chan->max_power = max_txpower_avg; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static void iwl_eeprom_enhanced_txpower(struct device *dev, | ||
395 | struct iwl_eeprom_data *data, | ||
396 | const u8 *eeprom, size_t eeprom_size, | ||
397 | int n_channels) | ||
398 | { | ||
399 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
400 | int idx, entries; | ||
401 | __le16 *txp_len; | ||
402 | s8 max_txp_avg_halfdbm; | ||
403 | |||
404 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
405 | |||
406 | /* the length is in 16-bit words, but we want entries */ | ||
407 | txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
408 | EEPROM_TXP_SZ_OFFS); | ||
409 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
410 | |||
411 | txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
412 | EEPROM_TXP_OFFS); | ||
413 | |||
414 | for (idx = 0; idx < entries; idx++) { | ||
415 | txp = &txp_array[idx]; | ||
416 | /* skip invalid entries */ | ||
417 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
418 | continue; | ||
419 | |||
420 | IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
421 | (txp->channel && (txp->flags & | ||
422 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
423 | "Common " : (txp->channel) ? | ||
424 | "Channel" : "Common", | ||
425 | (txp->channel), | ||
426 | TXP_CHECK_AND_PRINT(VALID), | ||
427 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
428 | TXP_CHECK_AND_PRINT(OFDM), | ||
429 | TXP_CHECK_AND_PRINT(40MHZ), | ||
430 | TXP_CHECK_AND_PRINT(HT_AP), | ||
431 | TXP_CHECK_AND_PRINT(RES1), | ||
432 | TXP_CHECK_AND_PRINT(RES2), | ||
433 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
434 | txp->flags); | ||
435 | IWL_DEBUG_EEPROM(dev, | ||
436 | "\t\t chain_A: 0x%02x chain_B: 0X%02x chain_C: 0X%02x\n", | ||
437 | txp->chain_a_max, txp->chain_b_max, | ||
438 | txp->chain_c_max); | ||
439 | IWL_DEBUG_EEPROM(dev, | ||
440 | "\t\t MIMO2: 0x%02x MIMO3: 0x%02x High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n", | ||
441 | txp->mimo2_max, txp->mimo3_max, | ||
442 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
443 | (txp->delta_20_in_40 & 0x0f)); | ||
444 | |||
445 | max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp); | ||
446 | |||
447 | iwl_eeprom_enh_txp_read_element(data, txp, n_channels, | ||
448 | DIV_ROUND_UP(max_txp_avg_halfdbm, 2)); | ||
449 | |||
450 | if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm) | ||
451 | data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static void iwl_init_band_reference(const struct iwl_cfg *cfg, | ||
456 | const u8 *eeprom, size_t eeprom_size, | ||
457 | int eeprom_band, int *eeprom_ch_count, | ||
458 | const struct iwl_eeprom_channel **ch_info, | ||
459 | const u8 **eeprom_ch_array) | ||
460 | { | ||
461 | u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1]; | ||
462 | |||
463 | offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY; | ||
464 | |||
465 | *ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset); | ||
466 | |||
467 | switch (eeprom_band) { | ||
468 | case 1: /* 2.4GHz band */ | ||
469 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
470 | *eeprom_ch_array = iwl_eeprom_band_1; | ||
471 | break; | ||
472 | case 2: /* 4.9GHz band */ | ||
473 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
474 | *eeprom_ch_array = iwl_eeprom_band_2; | ||
475 | break; | ||
476 | case 3: /* 5.2GHz band */ | ||
477 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
478 | *eeprom_ch_array = iwl_eeprom_band_3; | ||
479 | break; | ||
480 | case 4: /* 5.5GHz band */ | ||
481 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
482 | *eeprom_ch_array = iwl_eeprom_band_4; | ||
483 | break; | ||
484 | case 5: /* 5.7GHz band */ | ||
485 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
486 | *eeprom_ch_array = iwl_eeprom_band_5; | ||
487 | break; | ||
488 | case 6: /* 2.4GHz ht40 channels */ | ||
489 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
490 | *eeprom_ch_array = iwl_eeprom_band_6; | ||
491 | break; | ||
492 | case 7: /* 5 GHz ht40 channels */ | ||
493 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
494 | *eeprom_ch_array = iwl_eeprom_band_7; | ||
495 | break; | ||
496 | default: | ||
497 | *eeprom_ch_count = 0; | ||
498 | *eeprom_ch_array = NULL; | ||
499 | WARN_ON(1); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | #define CHECK_AND_PRINT(x) \ | ||
504 | ((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
505 | |||
506 | static void iwl_mod_ht40_chan_info(struct device *dev, | ||
507 | struct iwl_eeprom_data *data, int n_channels, | ||
508 | enum ieee80211_band band, u16 channel, | ||
509 | const struct iwl_eeprom_channel *eeprom_ch, | ||
510 | u8 clear_ht40_extension_channel) | ||
511 | { | ||
512 | struct ieee80211_channel *chan = NULL; | ||
513 | int i; | ||
514 | |||
515 | for (i = 0; i < n_channels; i++) { | ||
516 | if (data->channels[i].band != band) | ||
517 | continue; | ||
518 | if (data->channels[i].hw_value != channel) | ||
519 | continue; | ||
520 | chan = &data->channels[i]; | ||
521 | break; | ||
522 | } | ||
523 | |||
524 | if (!chan) | ||
525 | return; | ||
526 | |||
527 | IWL_DEBUG_EEPROM(dev, | ||
528 | "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
529 | channel, | ||
530 | band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", | ||
531 | CHECK_AND_PRINT(IBSS), | ||
532 | CHECK_AND_PRINT(ACTIVE), | ||
533 | CHECK_AND_PRINT(RADAR), | ||
534 | CHECK_AND_PRINT(WIDE), | ||
535 | CHECK_AND_PRINT(DFS), | ||
536 | eeprom_ch->flags, | ||
537 | eeprom_ch->max_power_avg, | ||
538 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) && | ||
539 | !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? "" | ||
540 | : "not "); | ||
541 | |||
542 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
543 | chan->flags &= ~clear_ht40_extension_channel; | ||
544 | } | ||
545 | |||
546 | #define CHECK_AND_PRINT_I(x) \ | ||
547 | ((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
548 | |||
549 | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | ||
550 | struct iwl_eeprom_data *data, | ||
551 | const u8 *eeprom, size_t eeprom_size) | ||
552 | { | ||
553 | int band, ch_idx; | ||
554 | const struct iwl_eeprom_channel *eeprom_ch_info; | ||
555 | const u8 *eeprom_ch_array; | ||
556 | int eeprom_ch_count; | ||
557 | int n_channels = 0; | ||
558 | |||
559 | /* | ||
560 | * Loop through the 5 EEPROM bands and add them to the parse list | ||
561 | */ | ||
562 | for (band = 1; band <= 5; band++) { | ||
563 | struct ieee80211_channel *channel; | ||
564 | |||
565 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
566 | &eeprom_ch_count, &eeprom_ch_info, | ||
567 | &eeprom_ch_array); | ||
568 | |||
569 | /* Loop through each band adding each of the channels */ | ||
570 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
571 | const struct iwl_eeprom_channel *eeprom_ch; | ||
572 | |||
573 | eeprom_ch = &eeprom_ch_info[ch_idx]; | ||
574 | |||
575 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) { | ||
576 | IWL_DEBUG_EEPROM(dev, | ||
577 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | ||
578 | eeprom_ch_array[ch_idx], | ||
579 | eeprom_ch_info[ch_idx].flags, | ||
580 | (band != 1) ? "5.2" : "2.4"); | ||
581 | continue; | ||
582 | } | ||
583 | |||
584 | channel = &data->channels[n_channels]; | ||
585 | n_channels++; | ||
586 | |||
587 | channel->hw_value = eeprom_ch_array[ch_idx]; | ||
588 | channel->band = (band == 1) ? IEEE80211_BAND_2GHZ | ||
589 | : IEEE80211_BAND_5GHZ; | ||
590 | channel->center_freq = | ||
591 | ieee80211_channel_to_frequency( | ||
592 | channel->hw_value, channel->band); | ||
593 | |||
594 | /* set no-HT40, will enable as appropriate later */ | ||
595 | channel->flags = IEEE80211_CHAN_NO_HT40; | ||
596 | |||
597 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) | ||
598 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | ||
599 | |||
600 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
601 | channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
602 | |||
603 | if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) | ||
604 | channel->flags |= IEEE80211_CHAN_RADAR; | ||
605 | |||
606 | /* Initialize regulatory-based run-time data */ | ||
607 | channel->max_power = | ||
608 | eeprom_ch_info[ch_idx].max_power_avg; | ||
609 | IWL_DEBUG_EEPROM(dev, | ||
610 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
611 | channel->hw_value, | ||
612 | (band != 1) ? "5.2" : "2.4", | ||
613 | CHECK_AND_PRINT_I(VALID), | ||
614 | CHECK_AND_PRINT_I(IBSS), | ||
615 | CHECK_AND_PRINT_I(ACTIVE), | ||
616 | CHECK_AND_PRINT_I(RADAR), | ||
617 | CHECK_AND_PRINT_I(WIDE), | ||
618 | CHECK_AND_PRINT_I(DFS), | ||
619 | eeprom_ch_info[ch_idx].flags, | ||
620 | eeprom_ch_info[ch_idx].max_power_avg, | ||
621 | ((eeprom_ch_info[ch_idx].flags & | ||
622 | EEPROM_CHANNEL_IBSS) && | ||
623 | !(eeprom_ch_info[ch_idx].flags & | ||
624 | EEPROM_CHANNEL_RADAR)) | ||
625 | ? "" : "not "); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | if (cfg->eeprom_params->enhanced_txpower) { | ||
630 | /* | ||
631 | * for newer device (6000 series and up) | ||
632 | * EEPROM contain enhanced tx power information | ||
633 | * driver need to process addition information | ||
634 | * to determine the max channel tx power limits | ||
635 | */ | ||
636 | iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size, | ||
637 | n_channels); | ||
638 | } else { | ||
639 | /* All others use data from channel map */ | ||
640 | int i; | ||
641 | |||
642 | data->max_tx_pwr_half_dbm = -128; | ||
643 | |||
644 | for (i = 0; i < n_channels; i++) | ||
645 | data->max_tx_pwr_half_dbm = | ||
646 | max_t(s8, data->max_tx_pwr_half_dbm, | ||
647 | data->channels[i].max_power * 2); | ||
648 | } | ||
649 | |||
650 | /* Check if we do have HT40 channels */ | ||
651 | if (cfg->eeprom_params->regulatory_bands[5] == | ||
652 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
653 | cfg->eeprom_params->regulatory_bands[6] == | ||
654 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
655 | return n_channels; | ||
656 | |||
657 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
658 | for (band = 6; band <= 7; band++) { | ||
659 | enum ieee80211_band ieeeband; | ||
660 | |||
661 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
662 | &eeprom_ch_count, &eeprom_ch_info, | ||
663 | &eeprom_ch_array); | ||
664 | |||
665 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
666 | ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ | ||
667 | : IEEE80211_BAND_5GHZ; | ||
668 | |||
669 | /* Loop through each band adding each of the channels */ | ||
670 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
671 | /* Set up driver's info for lower half */ | ||
672 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
673 | eeprom_ch_array[ch_idx], | ||
674 | &eeprom_ch_info[ch_idx], | ||
675 | IEEE80211_CHAN_NO_HT40PLUS); | ||
676 | |||
677 | /* Set up driver's info for upper half */ | ||
678 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
679 | eeprom_ch_array[ch_idx] + 4, | ||
680 | &eeprom_ch_info[ch_idx], | ||
681 | IEEE80211_CHAN_NO_HT40MINUS); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | return n_channels; | ||
686 | } | ||
687 | |||
688 | static int iwl_init_sband_channels(struct iwl_eeprom_data *data, | ||
689 | struct ieee80211_supported_band *sband, | ||
690 | int n_channels, enum ieee80211_band band) | ||
691 | { | ||
692 | struct ieee80211_channel *chan = &data->channels[0]; | ||
693 | int n = 0, idx = 0; | ||
694 | |||
695 | while (chan->band != band && idx < n_channels) | ||
696 | chan = &data->channels[++idx]; | ||
697 | |||
698 | sband->channels = &data->channels[idx]; | ||
699 | |||
700 | while (chan->band == band && idx < n_channels) { | ||
701 | chan = &data->channels[++idx]; | ||
702 | n++; | ||
703 | } | ||
704 | |||
705 | sband->n_channels = n; | ||
706 | |||
707 | return n; | ||
708 | } | ||
709 | |||
710 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
711 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
712 | |||
713 | static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | ||
714 | struct iwl_eeprom_data *data, | ||
715 | struct ieee80211_sta_ht_cap *ht_info, | ||
716 | enum ieee80211_band band) | ||
717 | { | ||
718 | int max_bit_rate = 0; | ||
719 | u8 rx_chains; | ||
720 | u8 tx_chains; | ||
721 | |||
722 | tx_chains = hweight8(data->valid_tx_ant); | ||
723 | if (cfg->rx_with_siso_diversity) | ||
724 | rx_chains = 1; | ||
725 | else | ||
726 | rx_chains = hweight8(data->valid_rx_ant); | ||
727 | |||
728 | if (!(data->sku & EEPROM_SKU_CAP_11N_ENABLE) || !cfg->ht_params) { | ||
729 | ht_info->ht_supported = false; | ||
730 | return; | ||
731 | } | ||
732 | |||
733 | ht_info->ht_supported = true; | ||
734 | ht_info->cap = 0; | ||
735 | |||
736 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
737 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
738 | |||
739 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
740 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; | ||
741 | |||
742 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
743 | if (rx_chains >= 2) | ||
744 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
745 | if (rx_chains >= 3) | ||
746 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
747 | |||
748 | if (cfg->ht_params->ht_greenfield_support) | ||
749 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
750 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
751 | |||
752 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
753 | |||
754 | if (cfg->ht_params->ht40_bands & BIT(band)) { | ||
755 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
756 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
757 | ht_info->mcs.rx_mask[4] = 0x01; | ||
758 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
759 | } | ||
760 | |||
761 | /* Highest supported Rx data rate */ | ||
762 | max_bit_rate *= rx_chains; | ||
763 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
764 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
765 | |||
766 | /* Tx MCS capabilities */ | ||
767 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
768 | if (tx_chains != rx_chains) { | ||
769 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
770 | ht_info->mcs.tx_params |= ((tx_chains - 1) << | ||
771 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | ||
776 | struct iwl_eeprom_data *data, | ||
777 | const u8 *eeprom, size_t eeprom_size) | ||
778 | { | ||
779 | int n_channels = iwl_init_channel_map(dev, cfg, data, | ||
780 | eeprom, eeprom_size); | ||
781 | int n_used = 0; | ||
782 | struct ieee80211_supported_band *sband; | ||
783 | |||
784 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | ||
785 | sband->band = IEEE80211_BAND_2GHZ; | ||
786 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | ||
787 | sband->n_bitrates = N_RATES_24; | ||
788 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
789 | IEEE80211_BAND_2GHZ); | ||
790 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | ||
791 | |||
792 | sband = &data->bands[IEEE80211_BAND_5GHZ]; | ||
793 | sband->band = IEEE80211_BAND_5GHZ; | ||
794 | sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; | ||
795 | sband->n_bitrates = N_RATES_52; | ||
796 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
797 | IEEE80211_BAND_5GHZ); | ||
798 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | ||
799 | |||
800 | if (n_channels != n_used) | ||
801 | IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", | ||
802 | n_used, n_channels); | ||
803 | } | ||
804 | |||
805 | /* EEPROM data functions */ | ||
806 | |||
807 | struct iwl_eeprom_data * | ||
808 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
809 | const u8 *eeprom, size_t eeprom_size) | ||
810 | { | ||
811 | struct iwl_eeprom_data *data; | ||
812 | const void *tmp; | ||
813 | |||
814 | if (WARN_ON(!cfg || !cfg->eeprom_params)) | ||
815 | return NULL; | ||
816 | |||
817 | data = kzalloc(sizeof(*data) + | ||
818 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||
819 | GFP_KERNEL); | ||
820 | if (!data) | ||
821 | return NULL; | ||
822 | |||
823 | /* get MAC address(es) */ | ||
824 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS); | ||
825 | if (!tmp) | ||
826 | goto err_free; | ||
827 | memcpy(data->hw_addr, tmp, ETH_ALEN); | ||
828 | data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size, | ||
829 | EEPROM_NUM_MAC_ADDRESS); | ||
830 | |||
831 | if (iwl_eeprom_read_calib(eeprom, eeprom_size, data)) | ||
832 | goto err_free; | ||
833 | |||
834 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL); | ||
835 | if (!tmp) | ||
836 | goto err_free; | ||
837 | memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib)); | ||
838 | |||
839 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
840 | EEPROM_RAW_TEMPERATURE); | ||
841 | if (!tmp) | ||
842 | goto err_free; | ||
843 | data->raw_temperature = *(__le16 *)tmp; | ||
844 | |||
845 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
846 | EEPROM_KELVIN_TEMPERATURE); | ||
847 | if (!tmp) | ||
848 | goto err_free; | ||
849 | data->kelvin_temperature = *(__le16 *)tmp; | ||
850 | data->kelvin_voltage = *((__le16 *)tmp + 1); | ||
851 | |||
852 | data->radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size, | ||
853 | EEPROM_RADIO_CONFIG); | ||
854 | data->sku = iwl_eeprom_query16(eeprom, eeprom_size, | ||
855 | EEPROM_SKU_CAP); | ||
856 | data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size, | ||
857 | EEPROM_VERSION); | ||
858 | |||
859 | data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(data->radio_cfg); | ||
860 | data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(data->radio_cfg); | ||
861 | |||
862 | /* check overrides (some devices have wrong EEPROM) */ | ||
863 | if (cfg->valid_tx_ant) | ||
864 | data->valid_tx_ant = cfg->valid_tx_ant; | ||
865 | if (cfg->valid_rx_ant) | ||
866 | data->valid_rx_ant = cfg->valid_rx_ant; | ||
867 | |||
868 | if (!data->valid_tx_ant || !data->valid_rx_ant) { | ||
869 | IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | ||
870 | data->valid_tx_ant, data->valid_rx_ant); | ||
871 | goto err_free; | ||
872 | } | ||
873 | |||
874 | iwl_init_sbands(dev, cfg, data, eeprom, eeprom_size); | ||
875 | |||
876 | return data; | ||
877 | err_free: | ||
878 | kfree(data); | ||
879 | return NULL; | ||
880 | } | ||
881 | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | ||
882 | |||
883 | /* helper functions */ | ||
884 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
885 | struct iwl_trans *trans) | ||
886 | { | ||
887 | if (data->eeprom_version >= trans->cfg->eeprom_ver || | ||
888 | data->calib_version >= trans->cfg->eeprom_calib_ver) { | ||
889 | IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
890 | data->eeprom_version, data->calib_version); | ||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | IWL_ERR(trans, | ||
895 | "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | ||
896 | data->eeprom_version, trans->cfg->eeprom_ver, | ||
897 | data->calib_version, trans->cfg->eeprom_calib_ver); | ||
898 | return -EINVAL; | ||
899 | } | ||
900 | EXPORT_SYMBOL_GPL(iwl_eeprom_check_version); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h new file mode 100644 index 000000000000..9c07c670a1ce --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #ifndef __iwl_eeprom_parse_h__ | ||
63 | #define __iwl_eeprom_parse_h__ | ||
64 | |||
65 | #include <linux/types.h> | ||
66 | #include <linux/if_ether.h> | ||
67 | #include "iwl-trans.h" | ||
68 | |||
69 | /* SKU Capabilities (actual values from EEPROM definition) */ | ||
70 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
71 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
72 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
73 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
74 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
75 | |||
76 | /* radio config bits (actual values from EEPROM definition) */ | ||
77 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
78 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
79 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
80 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
81 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
82 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
83 | |||
84 | struct iwl_eeprom_data { | ||
85 | int n_hw_addrs; | ||
86 | u8 hw_addr[ETH_ALEN]; | ||
87 | |||
88 | u16 radio_config; | ||
89 | |||
90 | u8 calib_version; | ||
91 | __le16 calib_voltage; | ||
92 | |||
93 | __le16 raw_temperature; | ||
94 | __le16 kelvin_temperature; | ||
95 | __le16 kelvin_voltage; | ||
96 | __le16 xtal_calib[2]; | ||
97 | |||
98 | u16 sku; | ||
99 | u16 radio_cfg; | ||
100 | u16 eeprom_version; | ||
101 | s8 max_tx_pwr_half_dbm; | ||
102 | |||
103 | u8 valid_tx_ant, valid_rx_ant; | ||
104 | |||
105 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
106 | struct ieee80211_channel channels[]; | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * iwl_parse_eeprom_data - parse EEPROM data and return values | ||
111 | * | ||
112 | * @dev: device pointer we're parsing for, for debug only | ||
113 | * @cfg: device configuration for parsing and overrides | ||
114 | * @eeprom: the EEPROM data | ||
115 | * @eeprom_size: length of the EEPROM data | ||
116 | * | ||
117 | * This function parses all EEPROM values we need and then | ||
118 | * returns a (newly allocated) struct containing all the | ||
119 | * relevant values for driver use. The struct must be freed | ||
120 | * later with iwl_free_eeprom_data(). | ||
121 | */ | ||
122 | struct iwl_eeprom_data * | ||
123 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
124 | const u8 *eeprom, size_t eeprom_size); | ||
125 | |||
126 | /** | ||
127 | * iwl_free_eeprom_data - free EEPROM data | ||
128 | * @data: the data to free | ||
129 | */ | ||
130 | static inline void iwl_free_eeprom_data(struct iwl_eeprom_data *data) | ||
131 | { | ||
132 | kfree(data); | ||
133 | } | ||
134 | |||
135 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
136 | struct iwl_trans *trans); | ||
137 | |||
138 | #endif /* __iwl_eeprom_parse_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c new file mode 100644 index 000000000000..27c7da3c6ed1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | |||
66 | #include "iwl-debug.h" | ||
67 | #include "iwl-eeprom-read.h" | ||
68 | #include "iwl-io.h" | ||
69 | #include "iwl-prph.h" | ||
70 | #include "iwl-csr.h" | ||
71 | |||
72 | /* | ||
73 | * EEPROM access time values: | ||
74 | * | ||
75 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
76 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
77 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
78 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
79 | */ | ||
80 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
81 | |||
82 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
83 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
84 | |||
85 | |||
86 | /* | ||
87 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
88 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
89 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
90 | * weren't arbitrated by the semaphore. | ||
91 | */ | ||
92 | |||
93 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
94 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
95 | |||
96 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
97 | { | ||
98 | u16 count; | ||
99 | int ret; | ||
100 | |||
101 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
102 | /* Request semaphore */ | ||
103 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
104 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
105 | |||
106 | /* See if we got it */ | ||
107 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
108 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
109 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
110 | EEPROM_SEM_TIMEOUT); | ||
111 | if (ret >= 0) { | ||
112 | IWL_DEBUG_EEPROM(trans->dev, | ||
113 | "Acquired semaphore after %d tries.\n", | ||
114 | count+1); | ||
115 | return ret; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
123 | { | ||
124 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
125 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
126 | } | ||
127 | |||
128 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) | ||
129 | { | ||
130 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; | ||
131 | |||
132 | IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp); | ||
133 | |||
134 | switch (gp) { | ||
135 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
136 | if (!nvm_is_otp) { | ||
137 | IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n", | ||
138 | gp); | ||
139 | return -ENOENT; | ||
140 | } | ||
141 | return 0; | ||
142 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
143 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
144 | if (nvm_is_otp) { | ||
145 | IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp); | ||
146 | return -ENOENT; | ||
147 | } | ||
148 | return 0; | ||
149 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
150 | default: | ||
151 | IWL_ERR(trans, | ||
152 | "bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n", | ||
153 | nvm_is_otp ? "OTP" : "EEPROM", gp); | ||
154 | return -ENOENT; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /****************************************************************************** | ||
159 | * | ||
160 | * OTP related functions | ||
161 | * | ||
162 | ******************************************************************************/ | ||
163 | |||
164 | static void iwl_set_otp_access_absolute(struct iwl_trans *trans) | ||
165 | { | ||
166 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
167 | |||
168 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
169 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
170 | } | ||
171 | |||
172 | static int iwl_nvm_is_otp(struct iwl_trans *trans) | ||
173 | { | ||
174 | u32 otpgp; | ||
175 | |||
176 | /* OTP only valid for CP/PP and after */ | ||
177 | switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
178 | case CSR_HW_REV_TYPE_NONE: | ||
179 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
180 | return -EIO; | ||
181 | case CSR_HW_REV_TYPE_5300: | ||
182 | case CSR_HW_REV_TYPE_5350: | ||
183 | case CSR_HW_REV_TYPE_5100: | ||
184 | case CSR_HW_REV_TYPE_5150: | ||
185 | return 0; | ||
186 | default: | ||
187 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
188 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
189 | return 1; | ||
190 | return 0; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
195 | { | ||
196 | int ret; | ||
197 | |||
198 | /* Enable 40MHz radio clock */ | ||
199 | iwl_write32(trans, CSR_GP_CNTRL, | ||
200 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
201 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
202 | |||
203 | /* wait for clock to be ready */ | ||
204 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
205 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
206 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
207 | 25000); | ||
208 | if (ret < 0) { | ||
209 | IWL_ERR(trans, "Time out access OTP\n"); | ||
210 | } else { | ||
211 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
212 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
213 | udelay(5); | ||
214 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
215 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
216 | |||
217 | /* | ||
218 | * CSR auto clock gate disable bit - | ||
219 | * this is only applicable for HW with OTP shadow RAM | ||
220 | */ | ||
221 | if (trans->cfg->base_params->shadow_ram_support) | ||
222 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
223 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
229 | __le16 *eeprom_data) | ||
230 | { | ||
231 | int ret = 0; | ||
232 | u32 r; | ||
233 | u32 otpgp; | ||
234 | |||
235 | iwl_write32(trans, CSR_EEPROM_REG, | ||
236 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
237 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
238 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
239 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
240 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
241 | if (ret < 0) { | ||
242 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
243 | return ret; | ||
244 | } | ||
245 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
246 | /* check for ECC errors: */ | ||
247 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
248 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
249 | /* stop in this case */ | ||
250 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
251 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
252 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
253 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
257 | /* continue in this case */ | ||
258 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
259 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
260 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
261 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
262 | } | ||
263 | *eeprom_data = cpu_to_le16(r >> 16); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * iwl_is_otp_empty: check for empty OTP | ||
269 | */ | ||
270 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
271 | { | ||
272 | u16 next_link_addr = 0; | ||
273 | __le16 link_value; | ||
274 | bool is_empty = false; | ||
275 | |||
276 | /* locate the beginning of OTP link list */ | ||
277 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
278 | if (!link_value) { | ||
279 | IWL_ERR(trans, "OTP is empty\n"); | ||
280 | is_empty = true; | ||
281 | } | ||
282 | } else { | ||
283 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
284 | is_empty = true; | ||
285 | } | ||
286 | |||
287 | return is_empty; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* | ||
292 | * iwl_find_otp_image: find EEPROM image in OTP | ||
293 | * finding the OTP block that contains the EEPROM image. | ||
294 | * the last valid block on the link list (the block _before_ the last block) | ||
295 | * is the block we should read and used to configure the device. | ||
296 | * If all the available OTP blocks are full, the last block will be the block | ||
297 | * we should read and used to configure the device. | ||
298 | * only perform this operation if shadow RAM is disabled | ||
299 | */ | ||
300 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
301 | u16 *validblockaddr) | ||
302 | { | ||
303 | u16 next_link_addr = 0, valid_addr; | ||
304 | __le16 link_value = 0; | ||
305 | int usedblocks = 0; | ||
306 | |||
307 | /* set addressing mode to absolute to traverse the link list */ | ||
308 | iwl_set_otp_access_absolute(trans); | ||
309 | |||
310 | /* checking for empty OTP or error */ | ||
311 | if (iwl_is_otp_empty(trans)) | ||
312 | return -EINVAL; | ||
313 | |||
314 | /* | ||
315 | * start traverse link list | ||
316 | * until reach the max number of OTP blocks | ||
317 | * different devices have different number of OTP blocks | ||
318 | */ | ||
319 | do { | ||
320 | /* save current valid block address | ||
321 | * check for more block on the link list | ||
322 | */ | ||
323 | valid_addr = next_link_addr; | ||
324 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
325 | IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n", | ||
326 | usedblocks, next_link_addr); | ||
327 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
328 | return -EINVAL; | ||
329 | if (!link_value) { | ||
330 | /* | ||
331 | * reach the end of link list, return success and | ||
332 | * set address point to the starting address | ||
333 | * of the image | ||
334 | */ | ||
335 | *validblockaddr = valid_addr; | ||
336 | /* skip first 2 bytes (link list pointer) */ | ||
337 | *validblockaddr += 2; | ||
338 | return 0; | ||
339 | } | ||
340 | /* more in the link list, continue */ | ||
341 | usedblocks++; | ||
342 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
343 | |||
344 | /* OTP has no valid blocks */ | ||
345 | IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * iwl_read_eeprom - read EEPROM contents | ||
351 | * | ||
352 | * Load the EEPROM contents from adapter and return it | ||
353 | * and its size. | ||
354 | * | ||
355 | * NOTE: This routine uses the non-debug IO access functions. | ||
356 | */ | ||
357 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | ||
358 | { | ||
359 | __le16 *e; | ||
360 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP); | ||
361 | int sz; | ||
362 | int ret; | ||
363 | u16 addr; | ||
364 | u16 validblockaddr = 0; | ||
365 | u16 cache_addr = 0; | ||
366 | int nvm_is_otp; | ||
367 | |||
368 | if (!eeprom || !eeprom_size) | ||
369 | return -EINVAL; | ||
370 | |||
371 | nvm_is_otp = iwl_nvm_is_otp(trans); | ||
372 | if (nvm_is_otp < 0) | ||
373 | return nvm_is_otp; | ||
374 | |||
375 | sz = trans->cfg->base_params->eeprom_size; | ||
376 | IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); | ||
377 | |||
378 | e = kmalloc(sz, GFP_KERNEL); | ||
379 | if (!e) | ||
380 | return -ENOMEM; | ||
381 | |||
382 | ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); | ||
383 | if (ret < 0) { | ||
384 | IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
385 | goto err_free; | ||
386 | } | ||
387 | |||
388 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
389 | ret = iwl_eeprom_acquire_semaphore(trans); | ||
390 | if (ret < 0) { | ||
391 | IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); | ||
392 | goto err_free; | ||
393 | } | ||
394 | |||
395 | if (nvm_is_otp) { | ||
396 | ret = iwl_init_otp_access(trans); | ||
397 | if (ret) { | ||
398 | IWL_ERR(trans, "Failed to initialize OTP access.\n"); | ||
399 | goto err_unlock; | ||
400 | } | ||
401 | |||
402 | iwl_write32(trans, CSR_EEPROM_GP, | ||
403 | iwl_read32(trans, CSR_EEPROM_GP) & | ||
404 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
405 | |||
406 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
407 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
408 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
409 | /* traversing the linked list if no shadow ram supported */ | ||
410 | if (!trans->cfg->base_params->shadow_ram_support) { | ||
411 | ret = iwl_find_otp_image(trans, &validblockaddr); | ||
412 | if (ret) | ||
413 | goto err_unlock; | ||
414 | } | ||
415 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
416 | addr += sizeof(u16)) { | ||
417 | __le16 eeprom_data; | ||
418 | |||
419 | ret = iwl_read_otp_word(trans, addr, &eeprom_data); | ||
420 | if (ret) | ||
421 | goto err_unlock; | ||
422 | e[cache_addr / 2] = eeprom_data; | ||
423 | cache_addr += sizeof(u16); | ||
424 | } | ||
425 | } else { | ||
426 | /* eeprom is an array of 16bit values */ | ||
427 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
428 | u32 r; | ||
429 | |||
430 | iwl_write32(trans, CSR_EEPROM_REG, | ||
431 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
432 | |||
433 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
434 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
435 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
436 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
437 | if (ret < 0) { | ||
438 | IWL_ERR(trans, | ||
439 | "Time out reading EEPROM[%d]\n", addr); | ||
440 | goto err_unlock; | ||
441 | } | ||
442 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
443 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n", | ||
448 | nvm_is_otp ? "OTP" : "EEPROM"); | ||
449 | |||
450 | iwl_eeprom_release_semaphore(trans); | ||
451 | |||
452 | *eeprom_size = sz; | ||
453 | *eeprom = (u8 *)e; | ||
454 | return 0; | ||
455 | |||
456 | err_unlock: | ||
457 | iwl_eeprom_release_semaphore(trans); | ||
458 | err_free: | ||
459 | kfree(e); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h new file mode 100644 index 000000000000..1337c9d36fee --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include "iwl-trans.h" | ||
67 | |||
68 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size); | ||
69 | |||
70 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c deleted file mode 100644 index b8e2b223ac36..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ /dev/null | |||
@@ -1,1148 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/slab.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-dev.h" | ||
72 | #include "iwl-debug.h" | ||
73 | #include "iwl-agn.h" | ||
74 | #include "iwl-eeprom.h" | ||
75 | #include "iwl-io.h" | ||
76 | #include "iwl-prph.h" | ||
77 | |||
78 | /************************** EEPROM BANDS **************************** | ||
79 | * | ||
80 | * The iwl_eeprom_band definitions below provide the mapping from the | ||
81 | * EEPROM contents to the specific channel number supported for each | ||
82 | * band. | ||
83 | * | ||
84 | * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 | ||
85 | * definition below maps to physical channel 42 in the 5.2GHz spectrum. | ||
86 | * The specific geography and calibration information for that channel | ||
87 | * is contained in the eeprom map itself. | ||
88 | * | ||
89 | * During init, we copy the eeprom information and channel map | ||
90 | * information into priv->channel_info_24/52 and priv->channel_map_24/52 | ||
91 | * | ||
92 | * channel_map_24/52 provides the index in the channel_info array for a | ||
93 | * given channel. We have to have two separate maps as there is channel | ||
94 | * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and | ||
95 | * band_2 | ||
96 | * | ||
97 | * A value of 0xff stored in the channel_map indicates that the channel | ||
98 | * is not supported by the hardware at all. | ||
99 | * | ||
100 | * A value of 0xfe in the channel_map indicates that the channel is not | ||
101 | * valid for Tx with the current hardware. This means that | ||
102 | * while the system can tune and receive on a given channel, it may not | ||
103 | * be able to associate or transmit any frames on that | ||
104 | * channel. There is no corresponding channel information for that | ||
105 | * entry. | ||
106 | * | ||
107 | *********************************************************************/ | ||
108 | |||
109 | /* 2.4 GHz */ | ||
110 | const u8 iwl_eeprom_band_1[14] = { | ||
111 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
112 | }; | ||
113 | |||
114 | /* 5.2 GHz bands */ | ||
115 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
116 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
117 | }; | ||
118 | |||
119 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
120 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
121 | }; | ||
122 | |||
123 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
124 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
125 | }; | ||
126 | |||
127 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
128 | 145, 149, 153, 157, 161, 165 | ||
129 | }; | ||
130 | |||
131 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
132 | 1, 2, 3, 4, 5, 6, 7 | ||
133 | }; | ||
134 | |||
135 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
136 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
137 | }; | ||
138 | |||
139 | /****************************************************************************** | ||
140 | * | ||
141 | * generic NVM functions | ||
142 | * | ||
143 | ******************************************************************************/ | ||
144 | |||
145 | /* | ||
146 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
147 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
148 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
149 | * weren't arbitrated by the semaphore. | ||
150 | */ | ||
151 | |||
152 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
153 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
154 | |||
155 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
156 | { | ||
157 | u16 count; | ||
158 | int ret; | ||
159 | |||
160 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
161 | /* Request semaphore */ | ||
162 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
163 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
164 | |||
165 | /* See if we got it */ | ||
166 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
167 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
168 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
169 | EEPROM_SEM_TIMEOUT); | ||
170 | if (ret >= 0) { | ||
171 | IWL_DEBUG_EEPROM(trans, | ||
172 | "Acquired semaphore after %d tries.\n", | ||
173 | count+1); | ||
174 | return ret; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
182 | { | ||
183 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
184 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
185 | |||
186 | } | ||
187 | |||
188 | static int iwl_eeprom_verify_signature(struct iwl_priv *priv) | ||
189 | { | ||
190 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
191 | CSR_EEPROM_GP_VALID_MSK; | ||
192 | int ret = 0; | ||
193 | |||
194 | IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); | ||
195 | switch (gp) { | ||
196 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
197 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | ||
198 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", | ||
199 | gp); | ||
200 | ret = -ENOENT; | ||
201 | } | ||
202 | break; | ||
203 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
204 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
205 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | ||
206 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); | ||
207 | ret = -ENOENT; | ||
208 | } | ||
209 | break; | ||
210 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
211 | default: | ||
212 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " | ||
213 | "EEPROM_GP=0x%08x\n", | ||
214 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
215 | ? "OTP" : "EEPROM", gp); | ||
216 | ret = -ENOENT; | ||
217 | break; | ||
218 | } | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset) | ||
223 | { | ||
224 | if (!priv->eeprom) | ||
225 | return 0; | ||
226 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
227 | } | ||
228 | |||
229 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
230 | { | ||
231 | u16 eeprom_ver; | ||
232 | u16 calib_ver; | ||
233 | |||
234 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
235 | calib_ver = iwl_eeprom_calib_version(priv); | ||
236 | |||
237 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
238 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
239 | goto err; | ||
240 | |||
241 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
242 | eeprom_ver, calib_ver); | ||
243 | |||
244 | return 0; | ||
245 | err: | ||
246 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
247 | "CALIB=0x%x < 0x%x\n", | ||
248 | eeprom_ver, priv->cfg->eeprom_ver, | ||
249 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
250 | return -EINVAL; | ||
251 | |||
252 | } | ||
253 | |||
254 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
255 | { | ||
256 | u16 radio_cfg; | ||
257 | |||
258 | priv->hw_params.sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | ||
259 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
260 | !priv->cfg->ht_params) { | ||
261 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | if (!priv->hw_params.sku) { | ||
266 | IWL_ERR(priv, "Invalid device sku\n"); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||
271 | |||
272 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
273 | |||
274 | priv->hw_params.valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
275 | priv->hw_params.valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
276 | |||
277 | /* check overrides (some devices have wrong EEPROM) */ | ||
278 | if (priv->cfg->valid_tx_ant) | ||
279 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
280 | if (priv->cfg->valid_rx_ant) | ||
281 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
282 | |||
283 | if (!priv->hw_params.valid_tx_ant || !priv->hw_params.valid_rx_ant) { | ||
284 | IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", | ||
285 | priv->hw_params.valid_tx_ant, | ||
286 | priv->hw_params.valid_rx_ant); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
291 | priv->hw_params.valid_tx_ant, priv->hw_params.valid_rx_ant); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv) | ||
297 | { | ||
298 | struct iwl_eeprom_calib_hdr *hdr; | ||
299 | |||
300 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
301 | EEPROM_CALIB_ALL); | ||
302 | return hdr->version; | ||
303 | } | ||
304 | |||
305 | static u32 eeprom_indirect_address(struct iwl_priv *priv, u32 address) | ||
306 | { | ||
307 | u16 offset = 0; | ||
308 | |||
309 | if ((address & INDIRECT_ADDRESS) == 0) | ||
310 | return address; | ||
311 | |||
312 | switch (address & INDIRECT_TYPE_MSK) { | ||
313 | case INDIRECT_HOST: | ||
314 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | ||
315 | break; | ||
316 | case INDIRECT_GENERAL: | ||
317 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | ||
318 | break; | ||
319 | case INDIRECT_REGULATORY: | ||
320 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | ||
321 | break; | ||
322 | case INDIRECT_TXP_LIMIT: | ||
323 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); | ||
324 | break; | ||
325 | case INDIRECT_TXP_LIMIT_SIZE: | ||
326 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); | ||
327 | break; | ||
328 | case INDIRECT_CALIBRATION: | ||
329 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | ||
330 | break; | ||
331 | case INDIRECT_PROCESS_ADJST: | ||
332 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | ||
333 | break; | ||
334 | case INDIRECT_OTHERS: | ||
335 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | ||
336 | break; | ||
337 | default: | ||
338 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
339 | address & INDIRECT_TYPE_MSK); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | /* translate the offset from words to byte */ | ||
344 | return (address & ADDRESS_MSK) + (offset << 1); | ||
345 | } | ||
346 | |||
347 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset) | ||
348 | { | ||
349 | u32 address = eeprom_indirect_address(priv, offset); | ||
350 | BUG_ON(address >= priv->cfg->base_params->eeprom_size); | ||
351 | return &priv->eeprom[address]; | ||
352 | } | ||
353 | |||
354 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac) | ||
355 | { | ||
356 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
357 | EEPROM_MAC_ADDRESS); | ||
358 | memcpy(mac, addr, ETH_ALEN); | ||
359 | } | ||
360 | |||
361 | /****************************************************************************** | ||
362 | * | ||
363 | * OTP related functions | ||
364 | * | ||
365 | ******************************************************************************/ | ||
366 | |||
367 | static void iwl_set_otp_access(struct iwl_trans *trans, | ||
368 | enum iwl_access_mode mode) | ||
369 | { | ||
370 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
371 | |||
372 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) | ||
373 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
374 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
375 | else | ||
376 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
377 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
378 | } | ||
379 | |||
380 | static int iwl_get_nvm_type(struct iwl_trans *trans, u32 hw_rev) | ||
381 | { | ||
382 | u32 otpgp; | ||
383 | int nvm_type; | ||
384 | |||
385 | /* OTP only valid for CP/PP and after */ | ||
386 | switch (hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
387 | case CSR_HW_REV_TYPE_NONE: | ||
388 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
389 | return -ENOENT; | ||
390 | case CSR_HW_REV_TYPE_5300: | ||
391 | case CSR_HW_REV_TYPE_5350: | ||
392 | case CSR_HW_REV_TYPE_5100: | ||
393 | case CSR_HW_REV_TYPE_5150: | ||
394 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
395 | break; | ||
396 | default: | ||
397 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
398 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
399 | nvm_type = NVM_DEVICE_TYPE_OTP; | ||
400 | else | ||
401 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
402 | break; | ||
403 | } | ||
404 | return nvm_type; | ||
405 | } | ||
406 | |||
407 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
408 | { | ||
409 | int ret; | ||
410 | |||
411 | /* Enable 40MHz radio clock */ | ||
412 | iwl_write32(trans, CSR_GP_CNTRL, | ||
413 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
414 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
415 | |||
416 | /* wait for clock to be ready */ | ||
417 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
418 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
419 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
420 | 25000); | ||
421 | if (ret < 0) | ||
422 | IWL_ERR(trans, "Time out access OTP\n"); | ||
423 | else { | ||
424 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
425 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
426 | udelay(5); | ||
427 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
428 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
429 | |||
430 | /* | ||
431 | * CSR auto clock gate disable bit - | ||
432 | * this is only applicable for HW with OTP shadow RAM | ||
433 | */ | ||
434 | if (trans->cfg->base_params->shadow_ram_support) | ||
435 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
436 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
437 | } | ||
438 | return ret; | ||
439 | } | ||
440 | |||
441 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
442 | __le16 *eeprom_data) | ||
443 | { | ||
444 | int ret = 0; | ||
445 | u32 r; | ||
446 | u32 otpgp; | ||
447 | |||
448 | iwl_write32(trans, CSR_EEPROM_REG, | ||
449 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
450 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
451 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
452 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
453 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
454 | if (ret < 0) { | ||
455 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
456 | return ret; | ||
457 | } | ||
458 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
459 | /* check for ECC errors: */ | ||
460 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
461 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
462 | /* stop in this case */ | ||
463 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
464 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
465 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
466 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
470 | /* continue in this case */ | ||
471 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
472 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
473 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
474 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
475 | } | ||
476 | *eeprom_data = cpu_to_le16(r >> 16); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * iwl_is_otp_empty: check for empty OTP | ||
482 | */ | ||
483 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
484 | { | ||
485 | u16 next_link_addr = 0; | ||
486 | __le16 link_value; | ||
487 | bool is_empty = false; | ||
488 | |||
489 | /* locate the beginning of OTP link list */ | ||
490 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
491 | if (!link_value) { | ||
492 | IWL_ERR(trans, "OTP is empty\n"); | ||
493 | is_empty = true; | ||
494 | } | ||
495 | } else { | ||
496 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
497 | is_empty = true; | ||
498 | } | ||
499 | |||
500 | return is_empty; | ||
501 | } | ||
502 | |||
503 | |||
504 | /* | ||
505 | * iwl_find_otp_image: find EEPROM image in OTP | ||
506 | * finding the OTP block that contains the EEPROM image. | ||
507 | * the last valid block on the link list (the block _before_ the last block) | ||
508 | * is the block we should read and used to configure the device. | ||
509 | * If all the available OTP blocks are full, the last block will be the block | ||
510 | * we should read and used to configure the device. | ||
511 | * only perform this operation if shadow RAM is disabled | ||
512 | */ | ||
513 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
514 | u16 *validblockaddr) | ||
515 | { | ||
516 | u16 next_link_addr = 0, valid_addr; | ||
517 | __le16 link_value = 0; | ||
518 | int usedblocks = 0; | ||
519 | |||
520 | /* set addressing mode to absolute to traverse the link list */ | ||
521 | iwl_set_otp_access(trans, IWL_OTP_ACCESS_ABSOLUTE); | ||
522 | |||
523 | /* checking for empty OTP or error */ | ||
524 | if (iwl_is_otp_empty(trans)) | ||
525 | return -EINVAL; | ||
526 | |||
527 | /* | ||
528 | * start traverse link list | ||
529 | * until reach the max number of OTP blocks | ||
530 | * different devices have different number of OTP blocks | ||
531 | */ | ||
532 | do { | ||
533 | /* save current valid block address | ||
534 | * check for more block on the link list | ||
535 | */ | ||
536 | valid_addr = next_link_addr; | ||
537 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
538 | IWL_DEBUG_EEPROM(trans, "OTP blocks %d addr 0x%x\n", | ||
539 | usedblocks, next_link_addr); | ||
540 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
541 | return -EINVAL; | ||
542 | if (!link_value) { | ||
543 | /* | ||
544 | * reach the end of link list, return success and | ||
545 | * set address point to the starting address | ||
546 | * of the image | ||
547 | */ | ||
548 | *validblockaddr = valid_addr; | ||
549 | /* skip first 2 bytes (link list pointer) */ | ||
550 | *validblockaddr += 2; | ||
551 | return 0; | ||
552 | } | ||
553 | /* more in the link list, continue */ | ||
554 | usedblocks++; | ||
555 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
556 | |||
557 | /* OTP has no valid blocks */ | ||
558 | IWL_DEBUG_EEPROM(trans, "OTP has no valid blocks\n"); | ||
559 | return -EINVAL; | ||
560 | } | ||
561 | |||
562 | /****************************************************************************** | ||
563 | * | ||
564 | * Tx Power related functions | ||
565 | * | ||
566 | ******************************************************************************/ | ||
567 | /** | ||
568 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
569 | * find the highest tx power from all chains for the channel | ||
570 | */ | ||
571 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
572 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
573 | int element, s8 *max_txpower_in_half_dbm) | ||
574 | { | ||
575 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
576 | |||
577 | /* Take the highest tx power from any valid chains */ | ||
578 | if ((priv->hw_params.valid_tx_ant & ANT_A) && | ||
579 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
580 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
581 | if ((priv->hw_params.valid_tx_ant & ANT_B) && | ||
582 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
583 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
584 | if ((priv->hw_params.valid_tx_ant & ANT_C) && | ||
585 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
586 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
587 | if (((priv->hw_params.valid_tx_ant == ANT_AB) | | ||
588 | (priv->hw_params.valid_tx_ant == ANT_BC) | | ||
589 | (priv->hw_params.valid_tx_ant == ANT_AC)) && | ||
590 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
591 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
592 | if ((priv->hw_params.valid_tx_ant == ANT_ABC) && | ||
593 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
594 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
595 | |||
596 | /* | ||
597 | * max. tx power in EEPROM is in 1/2 dBm format | ||
598 | * convert from 1/2 dBm to dBm (round-up convert) | ||
599 | * but we also do not want to loss 1/2 dBm resolution which | ||
600 | * will impact performance | ||
601 | */ | ||
602 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
603 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
604 | } | ||
605 | |||
606 | static void | ||
607 | iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | ||
608 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
609 | s8 max_txpower_avg) | ||
610 | { | ||
611 | int ch_idx; | ||
612 | bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; | ||
613 | enum ieee80211_band band; | ||
614 | |||
615 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
616 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
617 | |||
618 | for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { | ||
619 | struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; | ||
620 | |||
621 | /* update matching channel or from common data only */ | ||
622 | if (txp->channel != 0 && ch_info->channel != txp->channel) | ||
623 | continue; | ||
624 | |||
625 | /* update matching band only */ | ||
626 | if (band != ch_info->band) | ||
627 | continue; | ||
628 | |||
629 | if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { | ||
630 | ch_info->max_power_avg = max_txpower_avg; | ||
631 | ch_info->curr_txpow = max_txpower_avg; | ||
632 | ch_info->scan_power = max_txpower_avg; | ||
633 | } | ||
634 | |||
635 | if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) | ||
636 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
641 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
642 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
643 | |||
644 | #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ | ||
645 | ? # x " " : "") | ||
646 | |||
647 | static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
648 | { | ||
649 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
650 | int idx, entries; | ||
651 | __le16 *txp_len; | ||
652 | s8 max_txp_avg, max_txp_avg_halfdbm; | ||
653 | |||
654 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
655 | |||
656 | /* the length is in 16-bit words, but we want entries */ | ||
657 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | ||
658 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
659 | |||
660 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | ||
661 | |||
662 | for (idx = 0; idx < entries; idx++) { | ||
663 | txp = &txp_array[idx]; | ||
664 | /* skip invalid entries */ | ||
665 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
666 | continue; | ||
667 | |||
668 | IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
669 | (txp->channel && (txp->flags & | ||
670 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
671 | "Common " : (txp->channel) ? | ||
672 | "Channel" : "Common", | ||
673 | (txp->channel), | ||
674 | TXP_CHECK_AND_PRINT(VALID), | ||
675 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
676 | TXP_CHECK_AND_PRINT(OFDM), | ||
677 | TXP_CHECK_AND_PRINT(40MHZ), | ||
678 | TXP_CHECK_AND_PRINT(HT_AP), | ||
679 | TXP_CHECK_AND_PRINT(RES1), | ||
680 | TXP_CHECK_AND_PRINT(RES2), | ||
681 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
682 | txp->flags); | ||
683 | IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " | ||
684 | "chain_B: 0X%02x chain_C: 0X%02x\n", | ||
685 | txp->chain_a_max, txp->chain_b_max, | ||
686 | txp->chain_c_max); | ||
687 | IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " | ||
688 | "MIMO3: 0x%02x High 20_on_40: 0x%02x " | ||
689 | "Low 20_on_40: 0x%02x\n", | ||
690 | txp->mimo2_max, txp->mimo3_max, | ||
691 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
692 | (txp->delta_20_in_40 & 0x0f)); | ||
693 | |||
694 | max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, | ||
695 | &max_txp_avg_halfdbm); | ||
696 | |||
697 | /* | ||
698 | * Update the user limit values values to the highest | ||
699 | * power supported by any channel | ||
700 | */ | ||
701 | if (max_txp_avg > priv->tx_power_user_lmt) | ||
702 | priv->tx_power_user_lmt = max_txp_avg; | ||
703 | if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) | ||
704 | priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; | ||
705 | |||
706 | iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); | ||
707 | } | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * iwl_eeprom_init - read EEPROM contents | ||
712 | * | ||
713 | * Load the EEPROM contents from adapter into priv->eeprom | ||
714 | * | ||
715 | * NOTE: This routine uses the non-debug IO access functions. | ||
716 | */ | ||
717 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | ||
718 | { | ||
719 | __le16 *e; | ||
720 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP); | ||
721 | int sz; | ||
722 | int ret; | ||
723 | u16 addr; | ||
724 | u16 validblockaddr = 0; | ||
725 | u16 cache_addr = 0; | ||
726 | |||
727 | priv->nvm_device_type = iwl_get_nvm_type(priv->trans, hw_rev); | ||
728 | if (priv->nvm_device_type == -ENOENT) | ||
729 | return -ENOENT; | ||
730 | /* allocate eeprom */ | ||
731 | sz = priv->cfg->base_params->eeprom_size; | ||
732 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); | ||
733 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | ||
734 | if (!priv->eeprom) { | ||
735 | ret = -ENOMEM; | ||
736 | goto alloc_err; | ||
737 | } | ||
738 | e = (__le16 *)priv->eeprom; | ||
739 | |||
740 | ret = iwl_eeprom_verify_signature(priv); | ||
741 | if (ret < 0) { | ||
742 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
743 | ret = -ENOENT; | ||
744 | goto err; | ||
745 | } | ||
746 | |||
747 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
748 | ret = iwl_eeprom_acquire_semaphore(priv->trans); | ||
749 | if (ret < 0) { | ||
750 | IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); | ||
751 | ret = -ENOENT; | ||
752 | goto err; | ||
753 | } | ||
754 | |||
755 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | ||
756 | |||
757 | ret = iwl_init_otp_access(priv->trans); | ||
758 | if (ret) { | ||
759 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); | ||
760 | ret = -ENOENT; | ||
761 | goto done; | ||
762 | } | ||
763 | iwl_write32(priv->trans, CSR_EEPROM_GP, | ||
764 | iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
765 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
766 | |||
767 | iwl_set_bit(priv->trans, CSR_OTP_GP_REG, | ||
768 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
769 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
770 | /* traversing the linked list if no shadow ram supported */ | ||
771 | if (!priv->cfg->base_params->shadow_ram_support) { | ||
772 | if (iwl_find_otp_image(priv->trans, &validblockaddr)) { | ||
773 | ret = -ENOENT; | ||
774 | goto done; | ||
775 | } | ||
776 | } | ||
777 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
778 | addr += sizeof(u16)) { | ||
779 | __le16 eeprom_data; | ||
780 | |||
781 | ret = iwl_read_otp_word(priv->trans, addr, | ||
782 | &eeprom_data); | ||
783 | if (ret) | ||
784 | goto done; | ||
785 | e[cache_addr / 2] = eeprom_data; | ||
786 | cache_addr += sizeof(u16); | ||
787 | } | ||
788 | } else { | ||
789 | /* eeprom is an array of 16bit values */ | ||
790 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
791 | u32 r; | ||
792 | |||
793 | iwl_write32(priv->trans, CSR_EEPROM_REG, | ||
794 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
795 | |||
796 | ret = iwl_poll_bit(priv->trans, CSR_EEPROM_REG, | ||
797 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
798 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
799 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
800 | if (ret < 0) { | ||
801 | IWL_ERR(priv, | ||
802 | "Time out reading EEPROM[%d]\n", addr); | ||
803 | goto done; | ||
804 | } | ||
805 | r = iwl_read32(priv->trans, CSR_EEPROM_REG); | ||
806 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
807 | } | ||
808 | } | ||
809 | |||
810 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", | ||
811 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
812 | ? "OTP" : "EEPROM", | ||
813 | iwl_eeprom_query16(priv, EEPROM_VERSION)); | ||
814 | |||
815 | ret = 0; | ||
816 | done: | ||
817 | iwl_eeprom_release_semaphore(priv->trans); | ||
818 | |||
819 | err: | ||
820 | if (ret) | ||
821 | iwl_eeprom_free(priv); | ||
822 | alloc_err: | ||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | void iwl_eeprom_free(struct iwl_priv *priv) | ||
827 | { | ||
828 | kfree(priv->eeprom); | ||
829 | priv->eeprom = NULL; | ||
830 | } | ||
831 | |||
832 | static void iwl_init_band_reference(struct iwl_priv *priv, | ||
833 | int eep_band, int *eeprom_ch_count, | ||
834 | const struct iwl_eeprom_channel **eeprom_ch_info, | ||
835 | const u8 **eeprom_ch_index) | ||
836 | { | ||
837 | u32 offset = priv->lib-> | ||
838 | eeprom_ops.regulatory_bands[eep_band - 1]; | ||
839 | switch (eep_band) { | ||
840 | case 1: /* 2.4GHz band */ | ||
841 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
842 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
843 | iwl_eeprom_query_addr(priv, offset); | ||
844 | *eeprom_ch_index = iwl_eeprom_band_1; | ||
845 | break; | ||
846 | case 2: /* 4.9GHz band */ | ||
847 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
848 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
849 | iwl_eeprom_query_addr(priv, offset); | ||
850 | *eeprom_ch_index = iwl_eeprom_band_2; | ||
851 | break; | ||
852 | case 3: /* 5.2GHz band */ | ||
853 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
854 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
855 | iwl_eeprom_query_addr(priv, offset); | ||
856 | *eeprom_ch_index = iwl_eeprom_band_3; | ||
857 | break; | ||
858 | case 4: /* 5.5GHz band */ | ||
859 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
860 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
861 | iwl_eeprom_query_addr(priv, offset); | ||
862 | *eeprom_ch_index = iwl_eeprom_band_4; | ||
863 | break; | ||
864 | case 5: /* 5.7GHz band */ | ||
865 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
866 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
867 | iwl_eeprom_query_addr(priv, offset); | ||
868 | *eeprom_ch_index = iwl_eeprom_band_5; | ||
869 | break; | ||
870 | case 6: /* 2.4GHz ht40 channels */ | ||
871 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
872 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
873 | iwl_eeprom_query_addr(priv, offset); | ||
874 | *eeprom_ch_index = iwl_eeprom_band_6; | ||
875 | break; | ||
876 | case 7: /* 5 GHz ht40 channels */ | ||
877 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
878 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
879 | iwl_eeprom_query_addr(priv, offset); | ||
880 | *eeprom_ch_index = iwl_eeprom_band_7; | ||
881 | break; | ||
882 | default: | ||
883 | BUG(); | ||
884 | return; | ||
885 | } | ||
886 | } | ||
887 | |||
888 | #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ | ||
889 | ? # x " " : "") | ||
890 | /** | ||
891 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. | ||
892 | * | ||
893 | * Does not set up a command, or touch hardware. | ||
894 | */ | ||
895 | static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | ||
896 | enum ieee80211_band band, u16 channel, | ||
897 | const struct iwl_eeprom_channel *eeprom_ch, | ||
898 | u8 clear_ht40_extension_channel) | ||
899 | { | ||
900 | struct iwl_channel_info *ch_info; | ||
901 | |||
902 | ch_info = (struct iwl_channel_info *) | ||
903 | iwl_get_channel_info(priv, band, channel); | ||
904 | |||
905 | if (!is_channel_valid(ch_info)) | ||
906 | return -1; | ||
907 | |||
908 | IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" | ||
909 | " Ad-Hoc %ssupported\n", | ||
910 | ch_info->channel, | ||
911 | is_channel_a_band(ch_info) ? | ||
912 | "5.2" : "2.4", | ||
913 | CHECK_AND_PRINT(IBSS), | ||
914 | CHECK_AND_PRINT(ACTIVE), | ||
915 | CHECK_AND_PRINT(RADAR), | ||
916 | CHECK_AND_PRINT(WIDE), | ||
917 | CHECK_AND_PRINT(DFS), | ||
918 | eeprom_ch->flags, | ||
919 | eeprom_ch->max_power_avg, | ||
920 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) | ||
921 | && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? | ||
922 | "" : "not "); | ||
923 | |||
924 | ch_info->ht40_eeprom = *eeprom_ch; | ||
925 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; | ||
926 | ch_info->ht40_flags = eeprom_ch->flags; | ||
927 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
928 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ | ||
934 | ? # x " " : "") | ||
935 | |||
936 | /** | ||
937 | * iwl_init_channel_map - Set up driver's info for all possible channels | ||
938 | */ | ||
939 | int iwl_init_channel_map(struct iwl_priv *priv) | ||
940 | { | ||
941 | int eeprom_ch_count = 0; | ||
942 | const u8 *eeprom_ch_index = NULL; | ||
943 | const struct iwl_eeprom_channel *eeprom_ch_info = NULL; | ||
944 | int band, ch; | ||
945 | struct iwl_channel_info *ch_info; | ||
946 | |||
947 | if (priv->channel_count) { | ||
948 | IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n"); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n"); | ||
953 | |||
954 | priv->channel_count = | ||
955 | ARRAY_SIZE(iwl_eeprom_band_1) + | ||
956 | ARRAY_SIZE(iwl_eeprom_band_2) + | ||
957 | ARRAY_SIZE(iwl_eeprom_band_3) + | ||
958 | ARRAY_SIZE(iwl_eeprom_band_4) + | ||
959 | ARRAY_SIZE(iwl_eeprom_band_5); | ||
960 | |||
961 | IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", | ||
962 | priv->channel_count); | ||
963 | |||
964 | priv->channel_info = kcalloc(priv->channel_count, | ||
965 | sizeof(struct iwl_channel_info), | ||
966 | GFP_KERNEL); | ||
967 | if (!priv->channel_info) { | ||
968 | IWL_ERR(priv, "Could not allocate channel_info\n"); | ||
969 | priv->channel_count = 0; | ||
970 | return -ENOMEM; | ||
971 | } | ||
972 | |||
973 | ch_info = priv->channel_info; | ||
974 | |||
975 | /* Loop through the 5 EEPROM bands adding them in order to the | ||
976 | * channel map we maintain (that contains additional information than | ||
977 | * what just in the EEPROM) */ | ||
978 | for (band = 1; band <= 5; band++) { | ||
979 | |||
980 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
981 | &eeprom_ch_info, &eeprom_ch_index); | ||
982 | |||
983 | /* Loop through each band adding each of the channels */ | ||
984 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
985 | ch_info->channel = eeprom_ch_index[ch]; | ||
986 | ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : | ||
987 | IEEE80211_BAND_5GHZ; | ||
988 | |||
989 | /* permanently store EEPROM's channel regulatory flags | ||
990 | * and max power in channel info database. */ | ||
991 | ch_info->eeprom = eeprom_ch_info[ch]; | ||
992 | |||
993 | /* Copy the run-time flags so they are there even on | ||
994 | * invalid channels */ | ||
995 | ch_info->flags = eeprom_ch_info[ch].flags; | ||
996 | /* First write that ht40 is not enabled, and then enable | ||
997 | * one by one */ | ||
998 | ch_info->ht40_extension_channel = | ||
999 | IEEE80211_CHAN_NO_HT40; | ||
1000 | |||
1001 | if (!(is_channel_valid(ch_info))) { | ||
1002 | IWL_DEBUG_EEPROM(priv, | ||
1003 | "Ch. %d Flags %x [%sGHz] - " | ||
1004 | "No traffic\n", | ||
1005 | ch_info->channel, | ||
1006 | ch_info->flags, | ||
1007 | is_channel_a_band(ch_info) ? | ||
1008 | "5.2" : "2.4"); | ||
1009 | ch_info++; | ||
1010 | continue; | ||
1011 | } | ||
1012 | |||
1013 | /* Initialize regulatory-based run-time data */ | ||
1014 | ch_info->max_power_avg = ch_info->curr_txpow = | ||
1015 | eeprom_ch_info[ch].max_power_avg; | ||
1016 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | ||
1017 | ch_info->min_power = 0; | ||
1018 | |||
1019 | IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] " | ||
1020 | "%s%s%s%s%s%s(0x%02x %ddBm):" | ||
1021 | " Ad-Hoc %ssupported\n", | ||
1022 | ch_info->channel, | ||
1023 | is_channel_a_band(ch_info) ? | ||
1024 | "5.2" : "2.4", | ||
1025 | CHECK_AND_PRINT_I(VALID), | ||
1026 | CHECK_AND_PRINT_I(IBSS), | ||
1027 | CHECK_AND_PRINT_I(ACTIVE), | ||
1028 | CHECK_AND_PRINT_I(RADAR), | ||
1029 | CHECK_AND_PRINT_I(WIDE), | ||
1030 | CHECK_AND_PRINT_I(DFS), | ||
1031 | eeprom_ch_info[ch].flags, | ||
1032 | eeprom_ch_info[ch].max_power_avg, | ||
1033 | ((eeprom_ch_info[ch]. | ||
1034 | flags & EEPROM_CHANNEL_IBSS) | ||
1035 | && !(eeprom_ch_info[ch]. | ||
1036 | flags & EEPROM_CHANNEL_RADAR)) | ||
1037 | ? "" : "not "); | ||
1038 | |||
1039 | ch_info++; | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /* Check if we do have HT40 channels */ | ||
1044 | if (priv->lib->eeprom_ops.regulatory_bands[5] == | ||
1045 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
1046 | priv->lib->eeprom_ops.regulatory_bands[6] == | ||
1047 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
1048 | return 0; | ||
1049 | |||
1050 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
1051 | for (band = 6; band <= 7; band++) { | ||
1052 | enum ieee80211_band ieeeband; | ||
1053 | |||
1054 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
1055 | &eeprom_ch_info, &eeprom_ch_index); | ||
1056 | |||
1057 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
1058 | ieeeband = | ||
1059 | (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1060 | |||
1061 | /* Loop through each band adding each of the channels */ | ||
1062 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
1063 | /* Set up driver's info for lower half */ | ||
1064 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1065 | eeprom_ch_index[ch], | ||
1066 | &eeprom_ch_info[ch], | ||
1067 | IEEE80211_CHAN_NO_HT40PLUS); | ||
1068 | |||
1069 | /* Set up driver's info for upper half */ | ||
1070 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1071 | eeprom_ch_index[ch] + 4, | ||
1072 | &eeprom_ch_info[ch], | ||
1073 | IEEE80211_CHAN_NO_HT40MINUS); | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | /* for newer device (6000 series and up) | ||
1078 | * EEPROM contain enhanced tx power information | ||
1079 | * driver need to process addition information | ||
1080 | * to determine the max channel tx power limits | ||
1081 | */ | ||
1082 | if (priv->lib->eeprom_ops.enhanced_txpower) | ||
1083 | iwl_eeprom_enhanced_txpower(priv); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * iwl_free_channel_map - undo allocations in iwl_init_channel_map | ||
1090 | */ | ||
1091 | void iwl_free_channel_map(struct iwl_priv *priv) | ||
1092 | { | ||
1093 | kfree(priv->channel_info); | ||
1094 | priv->channel_count = 0; | ||
1095 | } | ||
1096 | |||
1097 | /** | ||
1098 | * iwl_get_channel_info - Find driver's private channel info | ||
1099 | * | ||
1100 | * Based on band and channel number. | ||
1101 | */ | ||
1102 | const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, | ||
1103 | enum ieee80211_band band, u16 channel) | ||
1104 | { | ||
1105 | int i; | ||
1106 | |||
1107 | switch (band) { | ||
1108 | case IEEE80211_BAND_5GHZ: | ||
1109 | for (i = 14; i < priv->channel_count; i++) { | ||
1110 | if (priv->channel_info[i].channel == channel) | ||
1111 | return &priv->channel_info[i]; | ||
1112 | } | ||
1113 | break; | ||
1114 | case IEEE80211_BAND_2GHZ: | ||
1115 | if (channel >= 1 && channel <= 14) | ||
1116 | return &priv->channel_info[channel - 1]; | ||
1117 | break; | ||
1118 | default: | ||
1119 | BUG(); | ||
1120 | } | ||
1121 | |||
1122 | return NULL; | ||
1123 | } | ||
1124 | |||
1125 | void iwl_rf_config(struct iwl_priv *priv) | ||
1126 | { | ||
1127 | u16 radio_cfg; | ||
1128 | |||
1129 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
1130 | |||
1131 | /* write radio config values to register */ | ||
1132 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
1133 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1134 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
1135 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
1136 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
1137 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
1138 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
1139 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
1140 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
1141 | } else | ||
1142 | WARN_ON(1); | ||
1143 | |||
1144 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
1145 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1146 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
1147 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
1148 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h deleted file mode 100644 index 64bfd947caeb..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ /dev/null | |||
@@ -1,269 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include <net/mac80211.h> | ||
67 | |||
68 | struct iwl_priv; | ||
69 | |||
70 | /* | ||
71 | * EEPROM access time values: | ||
72 | * | ||
73 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
74 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
75 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
76 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
77 | */ | ||
78 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
79 | |||
80 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
81 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. | ||
86 | * | ||
87 | * IBSS and/or AP operation is allowed *only* on those channels with | ||
88 | * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because | ||
89 | * RADAR detection is not supported by the 4965 driver, but is a | ||
90 | * requirement for establishing a new network for legal operation on channels | ||
91 | * requiring RADAR detection or restricting ACTIVE scanning. | ||
92 | * | ||
93 | * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels. | ||
94 | * It only indicates that 20 MHz channel use is supported; HT40 channel | ||
95 | * usage is indicated by a separate set of regulatory flags for each | ||
96 | * HT40 channel pair. | ||
97 | * | ||
98 | * NOTE: Using a channel inappropriately will result in a uCode error! | ||
99 | */ | ||
100 | #define IWL_NUM_TX_CALIB_GROUPS 5 | ||
101 | enum { | ||
102 | EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ | ||
103 | EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ | ||
104 | /* Bit 2 Reserved */ | ||
105 | EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ | ||
106 | EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ | ||
107 | EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ | ||
108 | /* Bit 6 Reserved (was Narrow Channel) */ | ||
109 | EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ | ||
110 | }; | ||
111 | |||
112 | /* SKU Capabilities */ | ||
113 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
114 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
115 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
116 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
117 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
118 | |||
119 | /* *regulatory* channel data format in eeprom, one for each channel. | ||
120 | * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ | ||
121 | struct iwl_eeprom_channel { | ||
122 | u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ | ||
123 | s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ | ||
124 | } __packed; | ||
125 | |||
126 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
127 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
128 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
129 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
130 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
131 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
132 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
133 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
134 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
135 | }; | ||
136 | |||
137 | /** | ||
138 | * iwl_eeprom_enhanced_txpwr structure | ||
139 | * This structure presents the enhanced regulatory tx power limit layout | ||
140 | * in eeprom image | ||
141 | * Enhanced regulatory tx power portion of eeprom image can be broken down | ||
142 | * into individual structures; each one is 8 bytes in size and contain the | ||
143 | * following information | ||
144 | * @flags: entry flags | ||
145 | * @channel: channel number | ||
146 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
147 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
148 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
149 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
150 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
151 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
152 | * | ||
153 | */ | ||
154 | struct iwl_eeprom_enhanced_txpwr { | ||
155 | u8 flags; | ||
156 | u8 channel; | ||
157 | s8 chain_a_max; | ||
158 | s8 chain_b_max; | ||
159 | s8 chain_c_max; | ||
160 | u8 delta_20_in_40; | ||
161 | s8 mimo2_max; | ||
162 | s8 mimo3_max; | ||
163 | } __packed; | ||
164 | |||
165 | /* calibration */ | ||
166 | struct iwl_eeprom_calib_hdr { | ||
167 | u8 version; | ||
168 | u8 pa_type; | ||
169 | __le16 voltage; | ||
170 | } __packed; | ||
171 | |||
172 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
173 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
174 | |||
175 | /* temperature */ | ||
176 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
177 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
178 | |||
179 | |||
180 | /* agn links */ | ||
181 | #define EEPROM_LINK_HOST (2*0x64) | ||
182 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
183 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
184 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
185 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
186 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
187 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
188 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
189 | |||
190 | /* agn regulatory - indirect access */ | ||
191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ | ||
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | ||
193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ | ||
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | ||
195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ | ||
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | ||
197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ | ||
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ | ||
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | ||
201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ | ||
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ | ||
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
205 | |||
206 | /* 6000 regulatory - indirect access */ | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | ||
208 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
209 | /* 2.4 GHz */ | ||
210 | extern const u8 iwl_eeprom_band_1[14]; | ||
211 | |||
212 | #define ADDRESS_MSK 0x0000FFFF | ||
213 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
214 | #define INDIRECT_HOST 0x00010000 | ||
215 | #define INDIRECT_GENERAL 0x00020000 | ||
216 | #define INDIRECT_REGULATORY 0x00030000 | ||
217 | #define INDIRECT_CALIBRATION 0x00040000 | ||
218 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
219 | #define INDIRECT_OTHERS 0x00060000 | ||
220 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
221 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
222 | #define INDIRECT_ADDRESS 0x00100000 | ||
223 | |||
224 | /* General */ | ||
225 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
226 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
227 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
228 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
229 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
230 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
231 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
232 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
233 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
234 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
235 | |||
236 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ | ||
237 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
238 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
239 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
240 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
241 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
242 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
243 | |||
244 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
245 | |||
246 | #define EEPROM_REGULATORY_BAND_NO_HT40 (0) | ||
247 | |||
248 | struct iwl_eeprom_ops { | ||
249 | const u32 regulatory_bands[7]; | ||
250 | bool enhanced_txpower; | ||
251 | }; | ||
252 | |||
253 | |||
254 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); | ||
255 | void iwl_eeprom_free(struct iwl_priv *priv); | ||
256 | int iwl_eeprom_check_version(struct iwl_priv *priv); | ||
257 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv); | ||
258 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv); | ||
259 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset); | ||
260 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset); | ||
261 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac); | ||
262 | int iwl_init_channel_map(struct iwl_priv *priv); | ||
263 | void iwl_free_channel_map(struct iwl_priv *priv); | ||
264 | const struct iwl_channel_info *iwl_get_channel_info( | ||
265 | const struct iwl_priv *priv, | ||
266 | enum ieee80211_band band, u16 channel); | ||
267 | void iwl_rf_config(struct iwl_priv *priv); | ||
268 | |||
269 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 081dd34d2387..5f2df70b73c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -27,6 +27,7 @@ | |||
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/export.h> | ||
30 | 31 | ||
31 | #include "iwl-io.h" | 32 | #include "iwl-io.h" |
32 | #include"iwl-csr.h" | 33 | #include"iwl-csr.h" |
@@ -52,6 +53,7 @@ void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) | |||
52 | __iwl_set_bit(trans, reg, mask); | 53 | __iwl_set_bit(trans, reg, mask); |
53 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 54 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
54 | } | 55 | } |
56 | EXPORT_SYMBOL_GPL(iwl_set_bit); | ||
55 | 57 | ||
56 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | 58 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
57 | { | 59 | { |
@@ -61,6 +63,25 @@ void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | |||
61 | __iwl_clear_bit(trans, reg, mask); | 63 | __iwl_clear_bit(trans, reg, mask); |
62 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 64 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
63 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(iwl_clear_bit); | ||
67 | |||
68 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | u32 v; | ||
72 | |||
73 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
74 | WARN_ON_ONCE(value & ~mask); | ||
75 | #endif | ||
76 | |||
77 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
78 | v = iwl_read32(trans, reg); | ||
79 | v &= ~mask; | ||
80 | v |= value; | ||
81 | iwl_write32(trans, reg, v); | ||
82 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask); | ||
64 | 85 | ||
65 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | 86 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
66 | u32 bits, u32 mask, int timeout) | 87 | u32 bits, u32 mask, int timeout) |
@@ -76,6 +97,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | |||
76 | 97 | ||
77 | return -ETIMEDOUT; | 98 | return -ETIMEDOUT; |
78 | } | 99 | } |
100 | EXPORT_SYMBOL_GPL(iwl_poll_bit); | ||
79 | 101 | ||
80 | int iwl_grab_nic_access_silent(struct iwl_trans *trans) | 102 | int iwl_grab_nic_access_silent(struct iwl_trans *trans) |
81 | { | 103 | { |
@@ -117,6 +139,7 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans) | |||
117 | 139 | ||
118 | return 0; | 140 | return 0; |
119 | } | 141 | } |
142 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent); | ||
120 | 143 | ||
121 | bool iwl_grab_nic_access(struct iwl_trans *trans) | 144 | bool iwl_grab_nic_access(struct iwl_trans *trans) |
122 | { | 145 | { |
@@ -130,6 +153,7 @@ bool iwl_grab_nic_access(struct iwl_trans *trans) | |||
130 | 153 | ||
131 | return true; | 154 | return true; |
132 | } | 155 | } |
156 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access); | ||
133 | 157 | ||
134 | void iwl_release_nic_access(struct iwl_trans *trans) | 158 | void iwl_release_nic_access(struct iwl_trans *trans) |
135 | { | 159 | { |
@@ -144,6 +168,7 @@ void iwl_release_nic_access(struct iwl_trans *trans) | |||
144 | */ | 168 | */ |
145 | mmiowb(); | 169 | mmiowb(); |
146 | } | 170 | } |
171 | EXPORT_SYMBOL_GPL(iwl_release_nic_access); | ||
147 | 172 | ||
148 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | 173 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) |
149 | { | 174 | { |
@@ -158,6 +183,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | |||
158 | 183 | ||
159 | return value; | 184 | return value; |
160 | } | 185 | } |
186 | EXPORT_SYMBOL_GPL(iwl_read_direct32); | ||
161 | 187 | ||
162 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | 188 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) |
163 | { | 189 | { |
@@ -170,6 +196,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | |||
170 | } | 196 | } |
171 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 197 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
172 | } | 198 | } |
199 | EXPORT_SYMBOL_GPL(iwl_write_direct32); | ||
173 | 200 | ||
174 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 201 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
175 | int timeout) | 202 | int timeout) |
@@ -185,6 +212,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | |||
185 | 212 | ||
186 | return -ETIMEDOUT; | 213 | return -ETIMEDOUT; |
187 | } | 214 | } |
215 | EXPORT_SYMBOL_GPL(iwl_poll_direct_bit); | ||
188 | 216 | ||
189 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg) | 217 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg) |
190 | { | 218 | { |
@@ -211,6 +239,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 reg) | |||
211 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 239 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
212 | return val; | 240 | return val; |
213 | } | 241 | } |
242 | EXPORT_SYMBOL_GPL(iwl_read_prph); | ||
214 | 243 | ||
215 | void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) | 244 | void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) |
216 | { | 245 | { |
@@ -223,6 +252,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) | |||
223 | } | 252 | } |
224 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 253 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
225 | } | 254 | } |
255 | EXPORT_SYMBOL_GPL(iwl_write_prph); | ||
226 | 256 | ||
227 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) | 257 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) |
228 | { | 258 | { |
@@ -236,6 +266,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) | |||
236 | } | 266 | } |
237 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 267 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
238 | } | 268 | } |
269 | EXPORT_SYMBOL_GPL(iwl_set_bits_prph); | ||
239 | 270 | ||
240 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, | 271 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, |
241 | u32 bits, u32 mask) | 272 | u32 bits, u32 mask) |
@@ -250,6 +281,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, | |||
250 | } | 281 | } |
251 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 282 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
252 | } | 283 | } |
284 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph); | ||
253 | 285 | ||
254 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) | 286 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) |
255 | { | 287 | { |
@@ -264,6 +296,7 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) | |||
264 | } | 296 | } |
265 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 297 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
266 | } | 298 | } |
299 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | ||
267 | 300 | ||
268 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, | 301 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, |
269 | void *buf, int words) | 302 | void *buf, int words) |
@@ -281,6 +314,7 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, | |||
281 | } | 314 | } |
282 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 315 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
283 | } | 316 | } |
317 | EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_words); | ||
284 | 318 | ||
285 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) | 319 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) |
286 | { | 320 | { |
@@ -290,6 +324,7 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) | |||
290 | 324 | ||
291 | return value; | 325 | return value; |
292 | } | 326 | } |
327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); | ||
293 | 328 | ||
294 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | 329 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, |
295 | void *buf, int words) | 330 | void *buf, int words) |
@@ -310,8 +345,10 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, | |||
310 | 345 | ||
311 | return result; | 346 | return result; |
312 | } | 347 | } |
348 | EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_words); | ||
313 | 349 | ||
314 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) | 350 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) |
315 | { | 351 | { |
316 | return _iwl_write_targ_mem_words(trans, addr, &val, 1); | 352 | return _iwl_write_targ_mem_words(trans, addr, &val, 1); |
317 | } | 353 | } |
354 | EXPORT_SYMBOL_GPL(iwl_write_targ_mem); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index abb3250164ba..4a9a45f771ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -54,6 +54,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) | |||
54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
56 | 56 | ||
57 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); | ||
58 | |||
57 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | 59 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
58 | u32 bits, u32 mask, int timeout); | 60 | u32 bits, u32 mask, int timeout); |
59 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 61 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index 0066b899fe5c..5cfed29b1b18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -61,6 +61,7 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/sched.h> | 63 | #include <linux/sched.h> |
64 | #include <linux/export.h> | ||
64 | 65 | ||
65 | #include "iwl-notif-wait.h" | 66 | #include "iwl-notif-wait.h" |
66 | 67 | ||
@@ -71,6 +72,7 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) | |||
71 | INIT_LIST_HEAD(¬if_wait->notif_waits); | 72 | INIT_LIST_HEAD(¬if_wait->notif_waits); |
72 | init_waitqueue_head(¬if_wait->notif_waitq); | 73 | init_waitqueue_head(¬if_wait->notif_waitq); |
73 | } | 74 | } |
75 | EXPORT_SYMBOL_GPL(iwl_notification_wait_init); | ||
74 | 76 | ||
75 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | 77 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, |
76 | struct iwl_rx_packet *pkt) | 78 | struct iwl_rx_packet *pkt) |
@@ -115,6 +117,7 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | |||
115 | if (triggered) | 117 | if (triggered) |
116 | wake_up_all(¬if_wait->notif_waitq); | 118 | wake_up_all(¬if_wait->notif_waitq); |
117 | } | 119 | } |
120 | EXPORT_SYMBOL_GPL(iwl_notification_wait_notify); | ||
118 | 121 | ||
119 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | 122 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) |
120 | { | 123 | { |
@@ -128,7 +131,7 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | |||
128 | 131 | ||
129 | wake_up_all(¬if_wait->notif_waitq); | 132 | wake_up_all(¬if_wait->notif_waitq); |
130 | } | 133 | } |
131 | 134 | EXPORT_SYMBOL_GPL(iwl_abort_notification_waits); | |
132 | 135 | ||
133 | void | 136 | void |
134 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | 137 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, |
@@ -152,6 +155,7 @@ iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | |||
152 | list_add(&wait_entry->list, ¬if_wait->notif_waits); | 155 | list_add(&wait_entry->list, ¬if_wait->notif_waits); |
153 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 156 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
154 | } | 157 | } |
158 | EXPORT_SYMBOL_GPL(iwl_init_notification_wait); | ||
155 | 159 | ||
156 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | 160 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, |
157 | struct iwl_notification_wait *wait_entry, | 161 | struct iwl_notification_wait *wait_entry, |
@@ -175,6 +179,7 @@ int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | |||
175 | return -ETIMEDOUT; | 179 | return -ETIMEDOUT; |
176 | return 0; | 180 | return 0; |
177 | } | 181 | } |
182 | EXPORT_SYMBOL_GPL(iwl_wait_notification); | ||
178 | 183 | ||
179 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | 184 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, |
180 | struct iwl_notification_wait *wait_entry) | 185 | struct iwl_notification_wait *wait_entry) |
@@ -183,3 +188,4 @@ void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | |||
183 | list_del(&wait_entry->list); | 188 | list_del(&wait_entry->list); |
184 | spin_unlock_bh(¬if_wait->notif_wait_lock); | 189 | spin_unlock_bh(¬if_wait->notif_wait_lock); |
185 | } | 190 | } |
191 | EXPORT_SYMBOL_GPL(iwl_remove_notification); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 4ef742b28e08..cd9ef114d3a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -145,6 +145,9 @@ struct iwl_op_mode_ops { | |||
145 | void (*wimax_active)(struct iwl_op_mode *op_mode); | 145 | void (*wimax_active)(struct iwl_op_mode *op_mode); |
146 | }; | 146 | }; |
147 | 147 | ||
148 | int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops); | ||
149 | void iwl_opmode_deregister(const char *name); | ||
150 | |||
148 | /** | 151 | /** |
149 | * struct iwl_op_mode - operational mode | 152 | * struct iwl_op_mode - operational mode |
150 | * | 153 | * |
@@ -218,9 +221,4 @@ static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode) | |||
218 | op_mode->ops->wimax_active(op_mode); | 221 | op_mode->ops->wimax_active(op_mode); |
219 | } | 222 | } |
220 | 223 | ||
221 | /***************************************************** | ||
222 | * Op mode layers implementations | ||
223 | ******************************************************/ | ||
224 | extern const struct iwl_op_mode_ops iwl_dvm_ops; | ||
225 | |||
226 | #endif /* __iwl_op_mode_h__ */ | 224 | #endif /* __iwl_op_mode_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b1069290fa9..a9f0415916c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -187,7 +187,7 @@ | |||
187 | #define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) | 187 | #define SCD_QUEUE_STTS_REG_POS_ACTIVE (3) |
188 | #define SCD_QUEUE_STTS_REG_POS_WSL (4) | 188 | #define SCD_QUEUE_STTS_REG_POS_WSL (4) |
189 | #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) | 189 | #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) |
190 | #define SCD_QUEUE_STTS_REG_MSK (0x00FF0000) | 190 | #define SCD_QUEUE_STTS_REG_MSK (0x017F0000) |
191 | 191 | ||
192 | #define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) | 192 | #define SCD_QUEUE_CTX_REG1_CREDIT_POS (8) |
193 | #define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) | 193 | #define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 79a1e7ae4995..00efde8e5536 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -154,6 +154,9 @@ struct iwl_cmd_header { | |||
154 | __le16 sequence; | 154 | __le16 sequence; |
155 | } __packed; | 155 | } __packed; |
156 | 156 | ||
157 | /* iwl_cmd_header flags value */ | ||
158 | #define IWL_CMD_FAILED_MSK 0x40 | ||
159 | |||
157 | 160 | ||
158 | #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ | 161 | #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ |
159 | #define FH_RSCSR_FRAME_INVALID 0x55550000 | 162 | #define FH_RSCSR_FRAME_INVALID 0x55550000 |
@@ -280,6 +283,8 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
280 | 283 | ||
281 | #define MAX_NO_RECLAIM_CMDS 6 | 284 | #define MAX_NO_RECLAIM_CMDS 6 |
282 | 285 | ||
286 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) | ||
287 | |||
283 | /* | 288 | /* |
284 | * Maximum number of HW queues the transport layer | 289 | * Maximum number of HW queues the transport layer |
285 | * currently supports | 290 | * currently supports |
@@ -350,10 +355,10 @@ struct iwl_trans; | |||
350 | * Must be atomic | 355 | * Must be atomic |
351 | * @reclaim: free packet until ssn. Returns a list of freed packets. | 356 | * @reclaim: free packet until ssn. Returns a list of freed packets. |
352 | * Must be atomic | 357 | * Must be atomic |
353 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is | 358 | * @txq_enable: setup a tx queue for AMPDU - will be called once the HW is |
354 | * ready and a successful ADDBA response has been received. | 359 | * ready and a successful ADDBA response has been received. |
355 | * May sleep | 360 | * May sleep |
356 | * @tx_agg_disable: de-configure a Tx queue to send AMPDUs | 361 | * @txq_disable: de-configure a Tx queue to send AMPDUs |
357 | * Must be atomic | 362 | * Must be atomic |
358 | * @wait_tx_queue_empty: wait until all tx queues are empty | 363 | * @wait_tx_queue_empty: wait until all tx queues are empty |
359 | * May sleep | 364 | * May sleep |
@@ -386,9 +391,9 @@ struct iwl_trans_ops { | |||
386 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, | 391 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, |
387 | struct sk_buff_head *skbs); | 392 | struct sk_buff_head *skbs); |
388 | 393 | ||
389 | void (*tx_agg_setup)(struct iwl_trans *trans, int queue, int fifo, | 394 | void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo, |
390 | int sta_id, int tid, int frame_limit, u16 ssn); | 395 | int sta_id, int tid, int frame_limit, u16 ssn); |
391 | void (*tx_agg_disable)(struct iwl_trans *trans, int queue); | 396 | void (*txq_disable)(struct iwl_trans *trans, int queue); |
392 | 397 | ||
393 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 398 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
394 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 399 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); |
@@ -428,6 +433,11 @@ enum iwl_trans_state { | |||
428 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. | 433 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. |
429 | * @pm_support: set to true in start_hw if link pm is supported | 434 | * @pm_support: set to true in start_hw if link pm is supported |
430 | * @wait_command_queue: the wait_queue for SYNC host commands | 435 | * @wait_command_queue: the wait_queue for SYNC host commands |
436 | * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. | ||
437 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | ||
438 | * @dev_cmd_headroom: room needed for the transport's private use before the | ||
439 | * device_cmd for Tx - for internal use only | ||
440 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | ||
431 | */ | 441 | */ |
432 | struct iwl_trans { | 442 | struct iwl_trans { |
433 | const struct iwl_trans_ops *ops; | 443 | const struct iwl_trans_ops *ops; |
@@ -445,6 +455,10 @@ struct iwl_trans { | |||
445 | 455 | ||
446 | wait_queue_head_t wait_command_queue; | 456 | wait_queue_head_t wait_command_queue; |
447 | 457 | ||
458 | /* The following fields are internal only */ | ||
459 | struct kmem_cache *dev_cmd_pool; | ||
460 | size_t dev_cmd_headroom; | ||
461 | |||
448 | /* pointer to trans specific struct */ | 462 | /* pointer to trans specific struct */ |
449 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 463 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
450 | char trans_specific[0] __aligned(sizeof(void *)); | 464 | char trans_specific[0] __aligned(sizeof(void *)); |
@@ -520,6 +534,26 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
520 | return trans->ops->send_cmd(trans, cmd); | 534 | return trans->ops->send_cmd(trans, cmd); |
521 | } | 535 | } |
522 | 536 | ||
537 | static inline struct iwl_device_cmd * | ||
538 | iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) | ||
539 | { | ||
540 | u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC); | ||
541 | |||
542 | if (unlikely(dev_cmd_ptr == NULL)) | ||
543 | return NULL; | ||
544 | |||
545 | return (struct iwl_device_cmd *) | ||
546 | (dev_cmd_ptr + trans->dev_cmd_headroom); | ||
547 | } | ||
548 | |||
549 | static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | ||
550 | struct iwl_device_cmd *dev_cmd) | ||
551 | { | ||
552 | u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom; | ||
553 | |||
554 | kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr); | ||
555 | } | ||
556 | |||
523 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 557 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
524 | struct iwl_device_cmd *dev_cmd, int queue) | 558 | struct iwl_device_cmd *dev_cmd, int queue) |
525 | { | 559 | { |
@@ -538,24 +572,24 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | |||
538 | trans->ops->reclaim(trans, queue, ssn, skbs); | 572 | trans->ops->reclaim(trans, queue, ssn, skbs); |
539 | } | 573 | } |
540 | 574 | ||
541 | static inline void iwl_trans_tx_agg_disable(struct iwl_trans *trans, int queue) | 575 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) |
542 | { | 576 | { |
543 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 577 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
544 | "%s bad state = %d", __func__, trans->state); | 578 | "%s bad state = %d", __func__, trans->state); |
545 | 579 | ||
546 | trans->ops->tx_agg_disable(trans, queue); | 580 | trans->ops->txq_disable(trans, queue); |
547 | } | 581 | } |
548 | 582 | ||
549 | static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, int queue, | 583 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, |
550 | int fifo, int sta_id, int tid, | 584 | int fifo, int sta_id, int tid, |
551 | int frame_limit, u16 ssn) | 585 | int frame_limit, u16 ssn) |
552 | { | 586 | { |
553 | might_sleep(); | 587 | might_sleep(); |
554 | 588 | ||
555 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 589 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
556 | "%s bad state = %d", __func__, trans->state); | 590 | "%s bad state = %d", __func__, trans->state); |
557 | 591 | ||
558 | trans->ops->tx_agg_setup(trans, queue, fifo, sta_id, tid, | 592 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, |
559 | frame_limit, ssn); | 593 | frame_limit, ssn); |
560 | } | 594 | } |
561 | 595 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/pcie/1000.c index 2629a6602dfa..81b83f484f08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/pcie/1000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-csr.h" | 30 | #include "iwl-csr.h" |
32 | #include "iwl-agn-hw.h" | 31 | #include "iwl-agn-hw.h" |
32 | #include "cfg.h" | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL1000_UCODE_API_MAX 5 | 35 | #define IWL1000_UCODE_API_MAX 5 |
@@ -64,13 +64,26 @@ static const struct iwl_base_params iwl1000_base_params = { | |||
64 | .support_ct_kill_exit = true, | 64 | .support_ct_kill_exit = true, |
65 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 65 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
66 | .chain_noise_scale = 1000, | 66 | .chain_noise_scale = 1000, |
67 | .wd_timeout = IWL_WATCHHDOG_DISABLED, | 67 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
68 | .max_event_log_size = 128, | 68 | .max_event_log_size = 128, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static const struct iwl_ht_params iwl1000_ht_params = { | 71 | static const struct iwl_ht_params iwl1000_ht_params = { |
72 | .ht_greenfield_support = true, | 72 | .ht_greenfield_support = true, |
73 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 73 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
74 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||
75 | }; | ||
76 | |||
77 | static const struct iwl_eeprom_params iwl1000_eeprom_params = { | ||
78 | .regulatory_bands = { | ||
79 | EEPROM_REG_BAND_1_CHANNELS, | ||
80 | EEPROM_REG_BAND_2_CHANNELS, | ||
81 | EEPROM_REG_BAND_3_CHANNELS, | ||
82 | EEPROM_REG_BAND_4_CHANNELS, | ||
83 | EEPROM_REG_BAND_5_CHANNELS, | ||
84 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
85 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
86 | } | ||
74 | }; | 87 | }; |
75 | 88 | ||
76 | #define IWL_DEVICE_1000 \ | 89 | #define IWL_DEVICE_1000 \ |
@@ -84,6 +97,7 @@ static const struct iwl_ht_params iwl1000_ht_params = { | |||
84 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 97 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
85 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 98 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
86 | .base_params = &iwl1000_base_params, \ | 99 | .base_params = &iwl1000_base_params, \ |
100 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
87 | .led_mode = IWL_LED_BLINK | 101 | .led_mode = IWL_LED_BLINK |
88 | 102 | ||
89 | const struct iwl_cfg iwl1000_bgn_cfg = { | 103 | const struct iwl_cfg iwl1000_bgn_cfg = { |
@@ -108,6 +122,7 @@ const struct iwl_cfg iwl1000_bg_cfg = { | |||
108 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 122 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
109 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 123 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
110 | .base_params = &iwl1000_base_params, \ | 124 | .base_params = &iwl1000_base_params, \ |
125 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
111 | .led_mode = IWL_LED_RF_STATE, \ | 126 | .led_mode = IWL_LED_RF_STATE, \ |
112 | .rx_with_siso_diversity = true | 127 | .rx_with_siso_diversity = true |
113 | 128 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/pcie/2000.c index 8133105ac645..fd4e78f56fa6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/pcie/2000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-commands.h" /* needed for BT for now */ | 31 | #include "cfg.h" |
32 | #include "dvm/commands.h" /* needed for BT for now */ | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL2030_UCODE_API_MAX 6 | 35 | #define IWL2030_UCODE_API_MAX 6 |
@@ -104,6 +104,7 @@ static const struct iwl_base_params iwl2030_base_params = { | |||
104 | static const struct iwl_ht_params iwl2000_ht_params = { | 104 | static const struct iwl_ht_params iwl2000_ht_params = { |
105 | .ht_greenfield_support = true, | 105 | .ht_greenfield_support = true, |
106 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 106 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
107 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | static const struct iwl_bt_params iwl2030_bt_params = { | 110 | static const struct iwl_bt_params iwl2030_bt_params = { |
@@ -116,6 +117,19 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
116 | .bt_session_2 = true, | 117 | .bt_session_2 = true, |
117 | }; | 118 | }; |
118 | 119 | ||
120 | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | ||
121 | .regulatory_bands = { | ||
122 | EEPROM_REG_BAND_1_CHANNELS, | ||
123 | EEPROM_REG_BAND_2_CHANNELS, | ||
124 | EEPROM_REG_BAND_3_CHANNELS, | ||
125 | EEPROM_REG_BAND_4_CHANNELS, | ||
126 | EEPROM_REG_BAND_5_CHANNELS, | ||
127 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
128 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
129 | }, | ||
130 | .enhanced_txpower = true, | ||
131 | }; | ||
132 | |||
119 | #define IWL_DEVICE_2000 \ | 133 | #define IWL_DEVICE_2000 \ |
120 | .fw_name_pre = IWL2000_FW_PRE, \ | 134 | .fw_name_pre = IWL2000_FW_PRE, \ |
121 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ | 135 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ |
@@ -127,6 +141,7 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
127 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 141 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
128 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 142 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
129 | .base_params = &iwl2000_base_params, \ | 143 | .base_params = &iwl2000_base_params, \ |
144 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
130 | .need_temp_offset_calib = true, \ | 145 | .need_temp_offset_calib = true, \ |
131 | .temp_offset_v2 = true, \ | 146 | .temp_offset_v2 = true, \ |
132 | .led_mode = IWL_LED_RF_STATE | 147 | .led_mode = IWL_LED_RF_STATE |
@@ -155,6 +170,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
155 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 170 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
156 | .base_params = &iwl2030_base_params, \ | 171 | .base_params = &iwl2030_base_params, \ |
157 | .bt_params = &iwl2030_bt_params, \ | 172 | .bt_params = &iwl2030_bt_params, \ |
173 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
158 | .need_temp_offset_calib = true, \ | 174 | .need_temp_offset_calib = true, \ |
159 | .temp_offset_v2 = true, \ | 175 | .temp_offset_v2 = true, \ |
160 | .led_mode = IWL_LED_RF_STATE, \ | 176 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -177,6 +193,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
177 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 193 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
178 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 194 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
179 | .base_params = &iwl2000_base_params, \ | 195 | .base_params = &iwl2000_base_params, \ |
196 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
180 | .need_temp_offset_calib = true, \ | 197 | .need_temp_offset_calib = true, \ |
181 | .temp_offset_v2 = true, \ | 198 | .temp_offset_v2 = true, \ |
182 | .led_mode = IWL_LED_RF_STATE, \ | 199 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -207,6 +224,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
207 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 224 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
208 | .base_params = &iwl2030_base_params, \ | 225 | .base_params = &iwl2030_base_params, \ |
209 | .bt_params = &iwl2030_bt_params, \ | 226 | .bt_params = &iwl2030_bt_params, \ |
227 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
210 | .need_temp_offset_calib = true, \ | 228 | .need_temp_offset_calib = true, \ |
211 | .temp_offset_v2 = true, \ | 229 | .temp_offset_v2 = true, \ |
212 | .led_mode = IWL_LED_RF_STATE, \ | 230 | .led_mode = IWL_LED_RF_STATE, \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/pcie/5000.c index 8e26bc825f23..d1665fa6d15a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/pcie/5000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-csr.h" | 31 | #include "iwl-csr.h" |
32 | #include "cfg.h" | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL5000_UCODE_API_MAX 5 | 35 | #define IWL5000_UCODE_API_MAX 5 |
@@ -62,13 +62,26 @@ static const struct iwl_base_params iwl5000_base_params = { | |||
62 | .led_compensation = 51, | 62 | .led_compensation = 51, |
63 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 63 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
64 | .chain_noise_scale = 1000, | 64 | .chain_noise_scale = 1000, |
65 | .wd_timeout = IWL_WATCHHDOG_DISABLED, | 65 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
66 | .max_event_log_size = 512, | 66 | .max_event_log_size = 512, |
67 | .no_idle_support = true, | 67 | .no_idle_support = true, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static const struct iwl_ht_params iwl5000_ht_params = { | 70 | static const struct iwl_ht_params iwl5000_ht_params = { |
71 | .ht_greenfield_support = true, | 71 | .ht_greenfield_support = true, |
72 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||
73 | }; | ||
74 | |||
75 | static const struct iwl_eeprom_params iwl5000_eeprom_params = { | ||
76 | .regulatory_bands = { | ||
77 | EEPROM_REG_BAND_1_CHANNELS, | ||
78 | EEPROM_REG_BAND_2_CHANNELS, | ||
79 | EEPROM_REG_BAND_3_CHANNELS, | ||
80 | EEPROM_REG_BAND_4_CHANNELS, | ||
81 | EEPROM_REG_BAND_5_CHANNELS, | ||
82 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
83 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
84 | }, | ||
72 | }; | 85 | }; |
73 | 86 | ||
74 | #define IWL_DEVICE_5000 \ | 87 | #define IWL_DEVICE_5000 \ |
@@ -82,6 +95,7 @@ static const struct iwl_ht_params iwl5000_ht_params = { | |||
82 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ | 95 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ |
83 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ | 96 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ |
84 | .base_params = &iwl5000_base_params, \ | 97 | .base_params = &iwl5000_base_params, \ |
98 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
85 | .led_mode = IWL_LED_BLINK | 99 | .led_mode = IWL_LED_BLINK |
86 | 100 | ||
87 | const struct iwl_cfg iwl5300_agn_cfg = { | 101 | const struct iwl_cfg iwl5300_agn_cfg = { |
@@ -128,6 +142,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
128 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 142 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
129 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 143 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
130 | .base_params = &iwl5000_base_params, | 144 | .base_params = &iwl5000_base_params, |
145 | .eeprom_params = &iwl5000_eeprom_params, | ||
131 | .ht_params = &iwl5000_ht_params, | 146 | .ht_params = &iwl5000_ht_params, |
132 | .led_mode = IWL_LED_BLINK, | 147 | .led_mode = IWL_LED_BLINK, |
133 | .internal_wimax_coex = true, | 148 | .internal_wimax_coex = true, |
@@ -144,6 +159,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
144 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ | 159 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ |
145 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ | 160 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ |
146 | .base_params = &iwl5000_base_params, \ | 161 | .base_params = &iwl5000_base_params, \ |
162 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
147 | .no_xtal_calib = true, \ | 163 | .no_xtal_calib = true, \ |
148 | .led_mode = IWL_LED_BLINK, \ | 164 | .led_mode = IWL_LED_BLINK, \ |
149 | .internal_wimax_coex = true | 165 | .internal_wimax_coex = true |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/pcie/6000.c index 19f7ee84ae89..8dd8a6fe61e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/pcie/6000.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
29 | #include "iwl-config.h" | 29 | #include "iwl-config.h" |
30 | #include "iwl-cfg.h" | ||
31 | #include "iwl-agn-hw.h" | 30 | #include "iwl-agn-hw.h" |
32 | #include "iwl-commands.h" /* needed for BT for now */ | 31 | #include "cfg.h" |
32 | #include "dvm/commands.h" /* needed for BT for now */ | ||
33 | 33 | ||
34 | /* Highest firmware API version supported */ | 34 | /* Highest firmware API version supported */ |
35 | #define IWL6000_UCODE_API_MAX 6 | 35 | #define IWL6000_UCODE_API_MAX 6 |
@@ -124,6 +124,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { | |||
124 | static const struct iwl_ht_params iwl6000_ht_params = { | 124 | static const struct iwl_ht_params iwl6000_ht_params = { |
125 | .ht_greenfield_support = true, | 125 | .ht_greenfield_support = true, |
126 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 126 | .use_rts_for_aggregation = true, /* use rts/cts protection */ |
127 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||
127 | }; | 128 | }; |
128 | 129 | ||
129 | static const struct iwl_bt_params iwl6000_bt_params = { | 130 | static const struct iwl_bt_params iwl6000_bt_params = { |
@@ -135,6 +136,19 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
135 | .bt_sco_disable = true, | 136 | .bt_sco_disable = true, |
136 | }; | 137 | }; |
137 | 138 | ||
139 | static const struct iwl_eeprom_params iwl6000_eeprom_params = { | ||
140 | .regulatory_bands = { | ||
141 | EEPROM_REG_BAND_1_CHANNELS, | ||
142 | EEPROM_REG_BAND_2_CHANNELS, | ||
143 | EEPROM_REG_BAND_3_CHANNELS, | ||
144 | EEPROM_REG_BAND_4_CHANNELS, | ||
145 | EEPROM_REG_BAND_5_CHANNELS, | ||
146 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
147 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
148 | }, | ||
149 | .enhanced_txpower = true, | ||
150 | }; | ||
151 | |||
138 | #define IWL_DEVICE_6005 \ | 152 | #define IWL_DEVICE_6005 \ |
139 | .fw_name_pre = IWL6005_FW_PRE, \ | 153 | .fw_name_pre = IWL6005_FW_PRE, \ |
140 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 154 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
@@ -146,6 +160,7 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
146 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ | 160 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ |
147 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ | 161 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
148 | .base_params = &iwl6000_g2_base_params, \ | 162 | .base_params = &iwl6000_g2_base_params, \ |
163 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
149 | .need_temp_offset_calib = true, \ | 164 | .need_temp_offset_calib = true, \ |
150 | .led_mode = IWL_LED_RF_STATE | 165 | .led_mode = IWL_LED_RF_STATE |
151 | 166 | ||
@@ -201,6 +216,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | |||
201 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 216 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
202 | .base_params = &iwl6000_g2_base_params, \ | 217 | .base_params = &iwl6000_g2_base_params, \ |
203 | .bt_params = &iwl6000_bt_params, \ | 218 | .bt_params = &iwl6000_bt_params, \ |
219 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
204 | .need_temp_offset_calib = true, \ | 220 | .need_temp_offset_calib = true, \ |
205 | .led_mode = IWL_LED_RF_STATE, \ | 221 | .led_mode = IWL_LED_RF_STATE, \ |
206 | .adv_pm = true \ | 222 | .adv_pm = true \ |
@@ -273,6 +289,7 @@ const struct iwl_cfg iwl130_bg_cfg = { | |||
273 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ | 289 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ |
274 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ | 290 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ |
275 | .base_params = &iwl6000_base_params, \ | 291 | .base_params = &iwl6000_base_params, \ |
292 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
276 | .led_mode = IWL_LED_BLINK | 293 | .led_mode = IWL_LED_BLINK |
277 | 294 | ||
278 | const struct iwl_cfg iwl6000i_2agn_cfg = { | 295 | const struct iwl_cfg iwl6000i_2agn_cfg = { |
@@ -303,6 +320,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { | |||
303 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ | 320 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ |
304 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ | 321 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ |
305 | .base_params = &iwl6050_base_params, \ | 322 | .base_params = &iwl6050_base_params, \ |
323 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
306 | .led_mode = IWL_LED_BLINK, \ | 324 | .led_mode = IWL_LED_BLINK, \ |
307 | .internal_wimax_coex = true | 325 | .internal_wimax_coex = true |
308 | 326 | ||
@@ -327,6 +345,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = { | |||
327 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ | 345 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ |
328 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ | 346 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ |
329 | .base_params = &iwl6050_base_params, \ | 347 | .base_params = &iwl6050_base_params, \ |
348 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
330 | .led_mode = IWL_LED_BLINK, \ | 349 | .led_mode = IWL_LED_BLINK, \ |
331 | .internal_wimax_coex = true | 350 | .internal_wimax_coex = true |
332 | 351 | ||
@@ -353,6 +372,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = { | |||
353 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 372 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
354 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 373 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
355 | .base_params = &iwl6000_base_params, | 374 | .base_params = &iwl6000_base_params, |
375 | .eeprom_params = &iwl6000_eeprom_params, | ||
356 | .ht_params = &iwl6000_ht_params, | 376 | .ht_params = &iwl6000_ht_params, |
357 | .led_mode = IWL_LED_BLINK, | 377 | .led_mode = IWL_LED_BLINK, |
358 | }; | 378 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/pcie/cfg.h index 82152311d73b..82152311d73b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-cfg.h +++ b/drivers/net/wireless/iwlwifi/pcie/cfg.h | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 0c8a1c2d8847..f4c3500b68c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -68,10 +68,11 @@ | |||
68 | #include <linux/pci-aspm.h> | 68 | #include <linux/pci-aspm.h> |
69 | 69 | ||
70 | #include "iwl-trans.h" | 70 | #include "iwl-trans.h" |
71 | #include "iwl-cfg.h" | ||
72 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
73 | #include "iwl-trans.h" | 72 | #include "iwl-trans.h" |
74 | #include "iwl-trans-pcie-int.h" | 73 | |
74 | #include "cfg.h" | ||
75 | #include "internal.h" | ||
75 | 76 | ||
76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 77 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
77 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ | 78 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index e959207c630a..94201c4d6227 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -313,7 +313,7 @@ void iwl_bg_rx_replenish(struct work_struct *data); | |||
313 | void iwl_irq_tasklet(struct iwl_trans *trans); | 313 | void iwl_irq_tasklet(struct iwl_trans *trans); |
314 | void iwlagn_rx_replenish(struct iwl_trans *trans); | 314 | void iwlagn_rx_replenish(struct iwl_trans *trans); |
315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | 315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, |
316 | struct iwl_rx_queue *q); | 316 | struct iwl_rx_queue *q); |
317 | 317 | ||
318 | /***************************************************** | 318 | /***************************************************** |
319 | * ICT | 319 | * ICT |
@@ -328,7 +328,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data); | |||
328 | * TX / HCMD | 328 | * TX / HCMD |
329 | ******************************************************/ | 329 | ******************************************************/ |
330 | void iwl_txq_update_write_ptr(struct iwl_trans *trans, | 330 | void iwl_txq_update_write_ptr(struct iwl_trans *trans, |
331 | struct iwl_tx_queue *txq); | 331 | struct iwl_tx_queue *txq); |
332 | int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, | 332 | int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, |
333 | struct iwl_tx_queue *txq, | 333 | struct iwl_tx_queue *txq, |
334 | dma_addr_t addr, u16 len, u8 reset); | 334 | dma_addr_t addr, u16 len, u8 reset); |
@@ -337,17 +337,20 @@ int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | |||
337 | void iwl_tx_cmd_complete(struct iwl_trans *trans, | 337 | void iwl_tx_cmd_complete(struct iwl_trans *trans, |
338 | struct iwl_rx_cmd_buffer *rxb, int handler_status); | 338 | struct iwl_rx_cmd_buffer *rxb, int handler_status); |
339 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | 339 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, |
340 | struct iwl_tx_queue *txq, | 340 | struct iwl_tx_queue *txq, |
341 | u16 byte_cnt); | 341 | u16 byte_cnt); |
342 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int queue); | 342 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); |
343 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); | 343 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); |
344 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | 344 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, |
345 | struct iwl_tx_queue *txq, | 345 | struct iwl_tx_queue *txq, |
346 | int tx_fifo_id, bool active); | 346 | int tx_fifo_id, bool active); |
347 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int queue, int fifo, | 347 | void __iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, |
348 | int sta_id, int tid, int frame_limit, u16 ssn); | 348 | int fifo, int sta_id, int tid, |
349 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 349 | int frame_limit, u16 ssn); |
350 | enum dma_data_direction dma_dir); | 350 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, |
351 | int sta_id, int tid, int frame_limit, u16 ssn); | ||
352 | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | ||
353 | enum dma_data_direction dma_dir); | ||
351 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | 354 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, |
352 | struct sk_buff_head *skbs); | 355 | struct sk_buff_head *skbs); |
353 | int iwl_queue_space(const struct iwl_queue *q); | 356 | int iwl_queue_space(const struct iwl_queue *q); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 08517d3c80bb..d6860c070c16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include "iwl-prph.h" | 33 | #include "iwl-prph.h" |
34 | #include "iwl-io.h" | 34 | #include "iwl-io.h" |
35 | #include "iwl-trans-pcie-int.h" | 35 | #include "internal.h" |
36 | #include "iwl-op-mode.h" | 36 | #include "iwl-op-mode.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | 38 | #ifdef CONFIG_IWLWIFI_IDI |
@@ -130,7 +130,7 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q) | |||
130 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 130 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
131 | */ | 131 | */ |
132 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | 132 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, |
133 | struct iwl_rx_queue *q) | 133 | struct iwl_rx_queue *q) |
134 | { | 134 | { |
135 | unsigned long flags; | 135 | unsigned long flags; |
136 | u32 reg; | 136 | u32 reg; |
@@ -201,9 +201,7 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | |||
201 | */ | 201 | */ |
202 | static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | 202 | static void iwlagn_rx_queue_restock(struct iwl_trans *trans) |
203 | { | 203 | { |
204 | struct iwl_trans_pcie *trans_pcie = | 204 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
205 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
206 | |||
207 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 205 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
208 | struct list_head *element; | 206 | struct list_head *element; |
209 | struct iwl_rx_mem_buffer *rxb; | 207 | struct iwl_rx_mem_buffer *rxb; |
@@ -253,9 +251,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
253 | */ | 251 | */ |
254 | static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | 252 | static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) |
255 | { | 253 | { |
256 | struct iwl_trans_pcie *trans_pcie = | 254 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
257 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
258 | |||
259 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 255 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
260 | struct list_head *element; | 256 | struct list_head *element; |
261 | struct iwl_rx_mem_buffer *rxb; | 257 | struct iwl_rx_mem_buffer *rxb; |
@@ -278,8 +274,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
278 | gfp_mask |= __GFP_COMP; | 274 | gfp_mask |= __GFP_COMP; |
279 | 275 | ||
280 | /* Alloc a new receive buffer */ | 276 | /* Alloc a new receive buffer */ |
281 | page = alloc_pages(gfp_mask, | 277 | page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); |
282 | trans_pcie->rx_page_order); | ||
283 | if (!page) { | 278 | if (!page) { |
284 | if (net_ratelimit()) | 279 | if (net_ratelimit()) |
285 | IWL_DEBUG_INFO(trans, "alloc_pages failed, " | 280 | IWL_DEBUG_INFO(trans, "alloc_pages failed, " |
@@ -315,9 +310,10 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
315 | BUG_ON(rxb->page); | 310 | BUG_ON(rxb->page); |
316 | rxb->page = page; | 311 | rxb->page = page; |
317 | /* Get physical address of the RB */ | 312 | /* Get physical address of the RB */ |
318 | rxb->page_dma = dma_map_page(trans->dev, page, 0, | 313 | rxb->page_dma = |
319 | PAGE_SIZE << trans_pcie->rx_page_order, | 314 | dma_map_page(trans->dev, page, 0, |
320 | DMA_FROM_DEVICE); | 315 | PAGE_SIZE << trans_pcie->rx_page_order, |
316 | DMA_FROM_DEVICE); | ||
321 | /* dma address must be no more than 36 bits */ | 317 | /* dma address must be no more than 36 bits */ |
322 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | 318 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); |
323 | /* and also 256 byte aligned! */ | 319 | /* and also 256 byte aligned! */ |
@@ -465,8 +461,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
465 | if (rxb->page != NULL) { | 461 | if (rxb->page != NULL) { |
466 | rxb->page_dma = | 462 | rxb->page_dma = |
467 | dma_map_page(trans->dev, rxb->page, 0, | 463 | dma_map_page(trans->dev, rxb->page, 0, |
468 | PAGE_SIZE << trans_pcie->rx_page_order, | 464 | PAGE_SIZE << trans_pcie->rx_page_order, |
469 | DMA_FROM_DEVICE); | 465 | DMA_FROM_DEVICE); |
470 | list_add_tail(&rxb->list, &rxq->rx_free); | 466 | list_add_tail(&rxb->list, &rxq->rx_free); |
471 | rxq->free_count++; | 467 | rxq->free_count++; |
472 | } else | 468 | } else |
@@ -497,7 +493,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
497 | 493 | ||
498 | /* Rx interrupt, but nothing sent from uCode */ | 494 | /* Rx interrupt, but nothing sent from uCode */ |
499 | if (i == r) | 495 | if (i == r) |
500 | IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); | 496 | IWL_DEBUG_RX(trans, "HW = SW = %d\n", r); |
501 | 497 | ||
502 | /* calculate total frames need to be restock after handling RX */ | 498 | /* calculate total frames need to be restock after handling RX */ |
503 | total_empty = r - rxq->write_actual; | 499 | total_empty = r - rxq->write_actual; |
@@ -513,8 +509,8 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
513 | rxb = rxq->queue[i]; | 509 | rxb = rxq->queue[i]; |
514 | rxq->queue[i] = NULL; | 510 | rxq->queue[i] = NULL; |
515 | 511 | ||
516 | IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb); | 512 | IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d (%p)\n", |
517 | 513 | r, i, rxb); | |
518 | iwl_rx_handle_rxbuf(trans, rxb); | 514 | iwl_rx_handle_rxbuf(trans, rxb); |
519 | 515 | ||
520 | i = (i + 1) & RX_QUEUE_MASK; | 516 | i = (i + 1) & RX_QUEUE_MASK; |
@@ -546,12 +542,12 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
546 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ | 542 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ |
547 | if (trans->cfg->internal_wimax_coex && | 543 | if (trans->cfg->internal_wimax_coex && |
548 | (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & | 544 | (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & |
549 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 545 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
550 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & | 546 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & |
551 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 547 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
552 | struct iwl_trans_pcie *trans_pcie; | 548 | struct iwl_trans_pcie *trans_pcie = |
549 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
553 | 550 | ||
554 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
555 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 551 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
556 | iwl_op_mode_wimax_active(trans->op_mode); | 552 | iwl_op_mode_wimax_active(trans->op_mode); |
557 | wake_up(&trans->wait_command_queue); | 553 | wake_up(&trans->wait_command_queue); |
@@ -567,6 +563,8 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
567 | /* tasklet for iwlagn interrupt */ | 563 | /* tasklet for iwlagn interrupt */ |
568 | void iwl_irq_tasklet(struct iwl_trans *trans) | 564 | void iwl_irq_tasklet(struct iwl_trans *trans) |
569 | { | 565 | { |
566 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
567 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
570 | u32 inta = 0; | 568 | u32 inta = 0; |
571 | u32 handled = 0; | 569 | u32 handled = 0; |
572 | unsigned long flags; | 570 | unsigned long flags; |
@@ -575,10 +573,6 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
575 | u32 inta_mask; | 573 | u32 inta_mask; |
576 | #endif | 574 | #endif |
577 | 575 | ||
578 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
579 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
580 | |||
581 | |||
582 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 576 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
583 | 577 | ||
584 | /* Ack/clear/reset pending uCode interrupts. | 578 | /* Ack/clear/reset pending uCode interrupts. |
@@ -593,7 +587,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
593 | * interrupt coalescing can still be achieved. | 587 | * interrupt coalescing can still be achieved. |
594 | */ | 588 | */ |
595 | iwl_write32(trans, CSR_INT, | 589 | iwl_write32(trans, CSR_INT, |
596 | trans_pcie->inta | ~trans_pcie->inta_mask); | 590 | trans_pcie->inta | ~trans_pcie->inta_mask); |
597 | 591 | ||
598 | inta = trans_pcie->inta; | 592 | inta = trans_pcie->inta; |
599 | 593 | ||
@@ -602,7 +596,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
602 | /* just for debug */ | 596 | /* just for debug */ |
603 | inta_mask = iwl_read32(trans, CSR_INT_MASK); | 597 | inta_mask = iwl_read32(trans, CSR_INT_MASK); |
604 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", | 598 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", |
605 | inta, inta_mask); | 599 | inta, inta_mask); |
606 | } | 600 | } |
607 | #endif | 601 | #endif |
608 | 602 | ||
@@ -651,7 +645,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
651 | 645 | ||
652 | hw_rfkill = iwl_is_rfkill_set(trans); | 646 | hw_rfkill = iwl_is_rfkill_set(trans); |
653 | IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", | 647 | IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", |
654 | hw_rfkill ? "disable radio" : "enable radio"); | 648 | hw_rfkill ? "disable radio" : "enable radio"); |
655 | 649 | ||
656 | isr_stats->rfkill++; | 650 | isr_stats->rfkill++; |
657 | 651 | ||
@@ -693,7 +687,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
693 | * Rx "responses" (frame-received notification), and other | 687 | * Rx "responses" (frame-received notification), and other |
694 | * notifications from uCode come through here*/ | 688 | * notifications from uCode come through here*/ |
695 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | | 689 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | |
696 | CSR_INT_BIT_RX_PERIODIC)) { | 690 | CSR_INT_BIT_RX_PERIODIC)) { |
697 | IWL_DEBUG_ISR(trans, "Rx interrupt\n"); | 691 | IWL_DEBUG_ISR(trans, "Rx interrupt\n"); |
698 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 692 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
699 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 693 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
@@ -733,7 +727,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
733 | */ | 727 | */ |
734 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 728 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
735 | iwl_write8(trans, CSR_INT_PERIODIC_REG, | 729 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
736 | CSR_INT_PERIODIC_ENA); | 730 | CSR_INT_PERIODIC_ENA); |
737 | 731 | ||
738 | isr_stats->rx++; | 732 | isr_stats->rx++; |
739 | } | 733 | } |
@@ -782,8 +776,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
782 | /* Free dram table */ | 776 | /* Free dram table */ |
783 | void iwl_free_isr_ict(struct iwl_trans *trans) | 777 | void iwl_free_isr_ict(struct iwl_trans *trans) |
784 | { | 778 | { |
785 | struct iwl_trans_pcie *trans_pcie = | 779 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
786 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
787 | 780 | ||
788 | if (trans_pcie->ict_tbl) { | 781 | if (trans_pcie->ict_tbl) { |
789 | dma_free_coherent(trans->dev, ICT_SIZE, | 782 | dma_free_coherent(trans->dev, ICT_SIZE, |
@@ -802,8 +795,7 @@ void iwl_free_isr_ict(struct iwl_trans *trans) | |||
802 | */ | 795 | */ |
803 | int iwl_alloc_isr_ict(struct iwl_trans *trans) | 796 | int iwl_alloc_isr_ict(struct iwl_trans *trans) |
804 | { | 797 | { |
805 | struct iwl_trans_pcie *trans_pcie = | 798 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
806 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
807 | 799 | ||
808 | trans_pcie->ict_tbl = | 800 | trans_pcie->ict_tbl = |
809 | dma_alloc_coherent(trans->dev, ICT_SIZE, | 801 | dma_alloc_coherent(trans->dev, ICT_SIZE, |
@@ -837,10 +829,9 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) | |||
837 | */ | 829 | */ |
838 | void iwl_reset_ict(struct iwl_trans *trans) | 830 | void iwl_reset_ict(struct iwl_trans *trans) |
839 | { | 831 | { |
832 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
840 | u32 val; | 833 | u32 val; |
841 | unsigned long flags; | 834 | unsigned long flags; |
842 | struct iwl_trans_pcie *trans_pcie = | ||
843 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
844 | 835 | ||
845 | if (!trans_pcie->ict_tbl) | 836 | if (!trans_pcie->ict_tbl) |
846 | return; | 837 | return; |
@@ -868,9 +859,7 @@ void iwl_reset_ict(struct iwl_trans *trans) | |||
868 | /* Device is going down disable ict interrupt usage */ | 859 | /* Device is going down disable ict interrupt usage */ |
869 | void iwl_disable_ict(struct iwl_trans *trans) | 860 | void iwl_disable_ict(struct iwl_trans *trans) |
870 | { | 861 | { |
871 | struct iwl_trans_pcie *trans_pcie = | 862 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
872 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
873 | |||
874 | unsigned long flags; | 863 | unsigned long flags; |
875 | 864 | ||
876 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 865 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
@@ -934,7 +923,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
934 | if (likely(inta)) | 923 | if (likely(inta)) |
935 | tasklet_schedule(&trans_pcie->irq_tasklet); | 924 | tasklet_schedule(&trans_pcie->irq_tasklet); |
936 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 925 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
937 | !trans_pcie->inta) | 926 | !trans_pcie->inta) |
938 | iwl_enable_interrupts(trans); | 927 | iwl_enable_interrupts(trans); |
939 | 928 | ||
940 | unplugged: | 929 | unplugged: |
@@ -945,7 +934,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
945 | /* re-enable interrupts here since we don't have anything to service. */ | 934 | /* re-enable interrupts here since we don't have anything to service. */ |
946 | /* only Re-enable if disabled by irq and no schedules tasklet. */ | 935 | /* only Re-enable if disabled by irq and no schedules tasklet. */ |
947 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 936 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
948 | !trans_pcie->inta) | 937 | !trans_pcie->inta) |
949 | iwl_enable_interrupts(trans); | 938 | iwl_enable_interrupts(trans); |
950 | 939 | ||
951 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 940 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
@@ -1036,7 +1025,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
1036 | 1025 | ||
1037 | inta = (0xff & val) | ((0xff00 & val) << 16); | 1026 | inta = (0xff & val) | ((0xff00 & val) << 16); |
1038 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | 1027 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", |
1039 | inta, inta_mask, val); | 1028 | inta, inta_mask, val); |
1040 | 1029 | ||
1041 | inta &= trans_pcie->inta_mask; | 1030 | inta &= trans_pcie->inta_mask; |
1042 | trans_pcie->inta |= inta; | 1031 | trans_pcie->inta |= inta; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index b849528d48dc..969f78f421df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -70,15 +70,12 @@ | |||
70 | 70 | ||
71 | #include "iwl-drv.h" | 71 | #include "iwl-drv.h" |
72 | #include "iwl-trans.h" | 72 | #include "iwl-trans.h" |
73 | #include "iwl-trans-pcie-int.h" | ||
74 | #include "iwl-csr.h" | 73 | #include "iwl-csr.h" |
75 | #include "iwl-prph.h" | 74 | #include "iwl-prph.h" |
76 | #include "iwl-eeprom.h" | ||
77 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
76 | #include "internal.h" | ||
78 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | 77 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ |
79 | #include "iwl-commands.h" | 78 | #include "dvm/commands.h" |
80 | |||
81 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) | ||
82 | 79 | ||
83 | #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ | 80 | #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ |
84 | (((1<<trans->cfg->base_params->num_of_queues) - 1) &\ | 81 | (((1<<trans->cfg->base_params->num_of_queues) - 1) &\ |
@@ -86,8 +83,7 @@ | |||
86 | 83 | ||
87 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) | 84 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) |
88 | { | 85 | { |
89 | struct iwl_trans_pcie *trans_pcie = | 86 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
90 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
91 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 87 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
92 | struct device *dev = trans->dev; | 88 | struct device *dev = trans->dev; |
93 | 89 | ||
@@ -114,7 +110,7 @@ static int iwl_trans_rx_alloc(struct iwl_trans *trans) | |||
114 | 110 | ||
115 | err_rb_stts: | 111 | err_rb_stts: |
116 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | 112 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, |
117 | rxq->bd, rxq->bd_dma); | 113 | rxq->bd, rxq->bd_dma); |
118 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | 114 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); |
119 | rxq->bd = NULL; | 115 | rxq->bd = NULL; |
120 | err_bd: | 116 | err_bd: |
@@ -123,8 +119,7 @@ err_bd: | |||
123 | 119 | ||
124 | static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | 120 | static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) |
125 | { | 121 | { |
126 | struct iwl_trans_pcie *trans_pcie = | 122 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
127 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
128 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 123 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
129 | int i; | 124 | int i; |
130 | 125 | ||
@@ -134,8 +129,8 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | |||
134 | * to an SKB, so we need to unmap and free potential storage */ | 129 | * to an SKB, so we need to unmap and free potential storage */ |
135 | if (rxq->pool[i].page != NULL) { | 130 | if (rxq->pool[i].page != NULL) { |
136 | dma_unmap_page(trans->dev, rxq->pool[i].page_dma, | 131 | dma_unmap_page(trans->dev, rxq->pool[i].page_dma, |
137 | PAGE_SIZE << trans_pcie->rx_page_order, | 132 | PAGE_SIZE << trans_pcie->rx_page_order, |
138 | DMA_FROM_DEVICE); | 133 | DMA_FROM_DEVICE); |
139 | __free_pages(rxq->pool[i].page, | 134 | __free_pages(rxq->pool[i].page, |
140 | trans_pcie->rx_page_order); | 135 | trans_pcie->rx_page_order); |
141 | rxq->pool[i].page = NULL; | 136 | rxq->pool[i].page = NULL; |
@@ -193,8 +188,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | |||
193 | 188 | ||
194 | static int iwl_rx_init(struct iwl_trans *trans) | 189 | static int iwl_rx_init(struct iwl_trans *trans) |
195 | { | 190 | { |
196 | struct iwl_trans_pcie *trans_pcie = | 191 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
197 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
198 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 192 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
199 | 193 | ||
200 | int i, err; | 194 | int i, err; |
@@ -236,10 +230,8 @@ static int iwl_rx_init(struct iwl_trans *trans) | |||
236 | 230 | ||
237 | static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) | 231 | static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) |
238 | { | 232 | { |
239 | struct iwl_trans_pcie *trans_pcie = | 233 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
240 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
241 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 234 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
242 | |||
243 | unsigned long flags; | 235 | unsigned long flags; |
244 | 236 | ||
245 | /*if rxq->bd is NULL, it means that nothing has been allocated, | 237 | /*if rxq->bd is NULL, it means that nothing has been allocated, |
@@ -274,11 +266,11 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans) | |||
274 | /* stop Rx DMA */ | 266 | /* stop Rx DMA */ |
275 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | 267 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); |
276 | return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, | 268 | return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, |
277 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | 269 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); |
278 | } | 270 | } |
279 | 271 | ||
280 | static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, | 272 | static int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, |
281 | struct iwl_dma_ptr *ptr, size_t size) | 273 | struct iwl_dma_ptr *ptr, size_t size) |
282 | { | 274 | { |
283 | if (WARN_ON(ptr->addr)) | 275 | if (WARN_ON(ptr->addr)) |
284 | return -EINVAL; | 276 | return -EINVAL; |
@@ -291,8 +283,8 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, | |||
291 | return 0; | 283 | return 0; |
292 | } | 284 | } |
293 | 285 | ||
294 | static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, | 286 | static void iwlagn_free_dma_ptr(struct iwl_trans *trans, |
295 | struct iwl_dma_ptr *ptr) | 287 | struct iwl_dma_ptr *ptr) |
296 | { | 288 | { |
297 | if (unlikely(!ptr->addr)) | 289 | if (unlikely(!ptr->addr)) |
298 | return; | 290 | return; |
@@ -329,12 +321,12 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) | |||
329 | } | 321 | } |
330 | 322 | ||
331 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, | 323 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, |
332 | struct iwl_tx_queue *txq, int slots_num, | 324 | struct iwl_tx_queue *txq, int slots_num, |
333 | u32 txq_id) | 325 | u32 txq_id) |
334 | { | 326 | { |
327 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
335 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; | 328 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; |
336 | int i; | 329 | int i; |
337 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
338 | 330 | ||
339 | if (WARN_ON(txq->entries || txq->tfds)) | 331 | if (WARN_ON(txq->entries || txq->tfds)) |
340 | return -EINVAL; | 332 | return -EINVAL; |
@@ -435,7 +427,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) | |||
435 | 427 | ||
436 | spin_lock_bh(&txq->lock); | 428 | spin_lock_bh(&txq->lock); |
437 | while (q->write_ptr != q->read_ptr) { | 429 | while (q->write_ptr != q->read_ptr) { |
438 | iwlagn_txq_free_tfd(trans, txq, dma_dir); | 430 | iwl_txq_free_tfd(trans, txq, dma_dir); |
439 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 431 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
440 | } | 432 | } |
441 | spin_unlock_bh(&txq->lock); | 433 | spin_unlock_bh(&txq->lock); |
@@ -455,6 +447,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | |||
455 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | 447 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
456 | struct device *dev = trans->dev; | 448 | struct device *dev = trans->dev; |
457 | int i; | 449 | int i; |
450 | |||
458 | if (WARN_ON(!txq)) | 451 | if (WARN_ON(!txq)) |
459 | return; | 452 | return; |
460 | 453 | ||
@@ -574,11 +567,11 @@ error: | |||
574 | } | 567 | } |
575 | static int iwl_tx_init(struct iwl_trans *trans) | 568 | static int iwl_tx_init(struct iwl_trans *trans) |
576 | { | 569 | { |
570 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
577 | int ret; | 571 | int ret; |
578 | int txq_id, slots_num; | 572 | int txq_id, slots_num; |
579 | unsigned long flags; | 573 | unsigned long flags; |
580 | bool alloc = false; | 574 | bool alloc = false; |
581 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
582 | 575 | ||
583 | if (!trans_pcie->txq) { | 576 | if (!trans_pcie->txq) { |
584 | ret = iwl_trans_tx_alloc(trans); | 577 | ret = iwl_trans_tx_alloc(trans); |
@@ -643,10 +636,9 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) | |||
643 | 636 | ||
644 | static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) | 637 | static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) |
645 | { | 638 | { |
639 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
646 | int pos; | 640 | int pos; |
647 | u16 pci_lnk_ctl; | 641 | u16 pci_lnk_ctl; |
648 | struct iwl_trans_pcie *trans_pcie = | ||
649 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
650 | 642 | ||
651 | struct pci_dev *pci_dev = trans_pcie->pci_dev; | 643 | struct pci_dev *pci_dev = trans_pcie->pci_dev; |
652 | 644 | ||
@@ -700,14 +692,14 @@ static int iwl_apm_init(struct iwl_trans *trans) | |||
700 | 692 | ||
701 | /* Disable L0S exit timer (platform NMI Work/Around) */ | 693 | /* Disable L0S exit timer (platform NMI Work/Around) */ |
702 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, | 694 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, |
703 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | 695 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); |
704 | 696 | ||
705 | /* | 697 | /* |
706 | * Disable L0s without affecting L1; | 698 | * Disable L0s without affecting L1; |
707 | * don't wait for ICH L0s (ICH bug W/A) | 699 | * don't wait for ICH L0s (ICH bug W/A) |
708 | */ | 700 | */ |
709 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, | 701 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, |
710 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | 702 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); |
711 | 703 | ||
712 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | 704 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ |
713 | iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | 705 | iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); |
@@ -717,7 +709,7 @@ static int iwl_apm_init(struct iwl_trans *trans) | |||
717 | * wake device's PCI Express link L1a -> L0s | 709 | * wake device's PCI Express link L1a -> L0s |
718 | */ | 710 | */ |
719 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | 711 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
720 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | 712 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); |
721 | 713 | ||
722 | iwl_apm_config(trans); | 714 | iwl_apm_config(trans); |
723 | 715 | ||
@@ -738,8 +730,8 @@ static int iwl_apm_init(struct iwl_trans *trans) | |||
738 | * and accesses to uCode SRAM. | 730 | * and accesses to uCode SRAM. |
739 | */ | 731 | */ |
740 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | 732 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, |
741 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 733 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
742 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 734 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); |
743 | if (ret < 0) { | 735 | if (ret < 0) { |
744 | IWL_DEBUG_INFO(trans, "Failed to init the card\n"); | 736 | IWL_DEBUG_INFO(trans, "Failed to init the card\n"); |
745 | goto out; | 737 | goto out; |
@@ -773,8 +765,8 @@ static int iwl_apm_stop_master(struct iwl_trans *trans) | |||
773 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | 765 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); |
774 | 766 | ||
775 | ret = iwl_poll_bit(trans, CSR_RESET, | 767 | ret = iwl_poll_bit(trans, CSR_RESET, |
776 | CSR_RESET_REG_FLAG_MASTER_DISABLED, | 768 | CSR_RESET_REG_FLAG_MASTER_DISABLED, |
777 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | 769 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); |
778 | if (ret) | 770 | if (ret) |
779 | IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); | 771 | IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); |
780 | 772 | ||
@@ -816,8 +808,7 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
816 | iwl_apm_init(trans); | 808 | iwl_apm_init(trans); |
817 | 809 | ||
818 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | 810 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ |
819 | iwl_write8(trans, CSR_INT_COALESCING, | 811 | iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); |
820 | IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
821 | 812 | ||
822 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 813 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
823 | 814 | ||
@@ -836,8 +827,8 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
836 | 827 | ||
837 | if (trans->cfg->base_params->shadow_reg_enable) { | 828 | if (trans->cfg->base_params->shadow_reg_enable) { |
838 | /* enable shadow regs in HW */ | 829 | /* enable shadow regs in HW */ |
839 | iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, | 830 | iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); |
840 | 0x800FFFFF); | 831 | IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n"); |
841 | } | 832 | } |
842 | 833 | ||
843 | return 0; | 834 | return 0; |
@@ -851,13 +842,13 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) | |||
851 | int ret; | 842 | int ret; |
852 | 843 | ||
853 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | 844 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
854 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); | 845 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); |
855 | 846 | ||
856 | /* See if we got it */ | 847 | /* See if we got it */ |
857 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | 848 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, |
858 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | 849 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, |
859 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | 850 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, |
860 | HW_READY_TIMEOUT); | 851 | HW_READY_TIMEOUT); |
861 | 852 | ||
862 | IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); | 853 | IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); |
863 | return ret; | 854 | return ret; |
@@ -877,11 +868,11 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans) | |||
877 | 868 | ||
878 | /* If HW is not ready, prepare the conditions to check again */ | 869 | /* If HW is not ready, prepare the conditions to check again */ |
879 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | 870 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
880 | CSR_HW_IF_CONFIG_REG_PREPARE); | 871 | CSR_HW_IF_CONFIG_REG_PREPARE); |
881 | 872 | ||
882 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | 873 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, |
883 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, | 874 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, |
884 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); | 875 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); |
885 | 876 | ||
886 | if (ret < 0) | 877 | if (ret < 0) |
887 | return ret; | 878 | return ret; |
@@ -908,32 +899,33 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num, | |||
908 | trans_pcie->ucode_write_complete = false; | 899 | trans_pcie->ucode_write_complete = false; |
909 | 900 | ||
910 | iwl_write_direct32(trans, | 901 | iwl_write_direct32(trans, |
911 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 902 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), |
912 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | 903 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); |
913 | 904 | ||
914 | iwl_write_direct32(trans, | 905 | iwl_write_direct32(trans, |
915 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | 906 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), |
907 | dst_addr); | ||
916 | 908 | ||
917 | iwl_write_direct32(trans, | 909 | iwl_write_direct32(trans, |
918 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | 910 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), |
919 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | 911 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); |
920 | 912 | ||
921 | iwl_write_direct32(trans, | 913 | iwl_write_direct32(trans, |
922 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | 914 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), |
923 | (iwl_get_dma_hi_addr(phy_addr) | 915 | (iwl_get_dma_hi_addr(phy_addr) |
924 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | 916 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); |
925 | 917 | ||
926 | iwl_write_direct32(trans, | 918 | iwl_write_direct32(trans, |
927 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | 919 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), |
928 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | 920 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | |
929 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | 921 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | |
930 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | 922 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); |
931 | 923 | ||
932 | iwl_write_direct32(trans, | 924 | iwl_write_direct32(trans, |
933 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 925 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), |
934 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | 926 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | |
935 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 927 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
936 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 928 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
937 | 929 | ||
938 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", | 930 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", |
939 | section_num); | 931 | section_num); |
@@ -1038,6 +1030,10 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1038 | 1030 | ||
1039 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1031 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
1040 | 1032 | ||
1033 | /* make sure all queue are not stopped/used */ | ||
1034 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | ||
1035 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | ||
1036 | |||
1041 | trans_pcie->scd_base_addr = | 1037 | trans_pcie->scd_base_addr = |
1042 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); | 1038 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); |
1043 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | 1039 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; |
@@ -1058,64 +1054,33 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1058 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, | 1054 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, |
1059 | trans_pcie->scd_bc_tbls.dma >> 10); | 1055 | trans_pcie->scd_bc_tbls.dma >> 10); |
1060 | 1056 | ||
1057 | for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { | ||
1058 | int fifo = trans_pcie->setup_q_to_fifo[i]; | ||
1059 | |||
1060 | __iwl_trans_pcie_txq_enable(trans, i, fifo, IWL_INVALID_STATION, | ||
1061 | IWL_TID_NON_QOS, | ||
1062 | SCD_FRAME_LIMIT, 0); | ||
1063 | } | ||
1064 | |||
1065 | /* Activate all Tx DMA/FIFO channels */ | ||
1066 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | ||
1067 | |||
1061 | /* Enable DMA channel */ | 1068 | /* Enable DMA channel */ |
1062 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | 1069 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) |
1063 | iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | 1070 | iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), |
1064 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | 1071 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | |
1065 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | 1072 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); |
1066 | 1073 | ||
1067 | /* Update FH chicken bits */ | 1074 | /* Update FH chicken bits */ |
1068 | reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); | 1075 | reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); |
1069 | iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, | 1076 | iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, |
1070 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | 1077 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); |
1071 | 1078 | ||
1072 | iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, | ||
1073 | SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)); | ||
1074 | iwl_write_prph(trans, SCD_AGGR_SEL, 0); | ||
1075 | |||
1076 | /* initiate the queues */ | ||
1077 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { | ||
1078 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); | ||
1079 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
1080 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
1081 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
1082 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
1083 | SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
1084 | sizeof(u32), | ||
1085 | ((SCD_WIN_SIZE << | ||
1086 | SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
1087 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
1088 | ((SCD_FRAME_LIMIT << | ||
1089 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
1090 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
1091 | } | ||
1092 | |||
1093 | iwl_write_prph(trans, SCD_INTERRUPT_MASK, | ||
1094 | IWL_MASK(0, trans->cfg->base_params->num_of_queues)); | ||
1095 | |||
1096 | /* Activate all Tx DMA/FIFO channels */ | ||
1097 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | ||
1098 | |||
1099 | iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); | ||
1100 | |||
1101 | /* make sure all queue are not stopped/used */ | ||
1102 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | ||
1103 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | ||
1104 | |||
1105 | for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { | ||
1106 | int fifo = trans_pcie->setup_q_to_fifo[i]; | ||
1107 | |||
1108 | set_bit(i, trans_pcie->queue_used); | ||
1109 | |||
1110 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], | ||
1111 | fifo, true); | ||
1112 | } | ||
1113 | |||
1114 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1079 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1115 | 1080 | ||
1116 | /* Enable L1-Active */ | 1081 | /* Enable L1-Active */ |
1117 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, | 1082 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, |
1118 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1083 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
1119 | } | 1084 | } |
1120 | 1085 | ||
1121 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) | 1086 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) |
@@ -1129,9 +1094,9 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) | |||
1129 | */ | 1094 | */ |
1130 | static int iwl_trans_tx_stop(struct iwl_trans *trans) | 1095 | static int iwl_trans_tx_stop(struct iwl_trans *trans) |
1131 | { | 1096 | { |
1097 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1132 | int ch, txq_id, ret; | 1098 | int ch, txq_id, ret; |
1133 | unsigned long flags; | 1099 | unsigned long flags; |
1134 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1135 | 1100 | ||
1136 | /* Turn off all Tx DMA fifos */ | 1101 | /* Turn off all Tx DMA fifos */ |
1137 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1102 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
@@ -1143,13 +1108,13 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) | |||
1143 | iwl_write_direct32(trans, | 1108 | iwl_write_direct32(trans, |
1144 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | 1109 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); |
1145 | ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, | 1110 | ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, |
1146 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | 1111 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); |
1147 | 1000); | ||
1148 | if (ret < 0) | 1112 | if (ret < 0) |
1149 | IWL_ERR(trans, "Failing on timeout while stopping" | 1113 | IWL_ERR(trans, |
1150 | " DMA channel %d [0x%08x]", ch, | 1114 | "Failing on timeout while stopping DMA channel %d [0x%08x]", |
1151 | iwl_read_direct32(trans, | 1115 | ch, |
1152 | FH_TSSR_TX_STATUS_REG)); | 1116 | iwl_read_direct32(trans, |
1117 | FH_TSSR_TX_STATUS_REG)); | ||
1153 | } | 1118 | } |
1154 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1119 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1155 | 1120 | ||
@@ -1168,8 +1133,8 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) | |||
1168 | 1133 | ||
1169 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | 1134 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) |
1170 | { | 1135 | { |
1171 | unsigned long flags; | ||
1172 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1136 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1137 | unsigned long flags; | ||
1173 | 1138 | ||
1174 | /* tell the device to stop sending interrupts */ | 1139 | /* tell the device to stop sending interrupts */ |
1175 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 1140 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
@@ -1199,7 +1164,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1199 | 1164 | ||
1200 | /* Make sure (redundant) we've released our request to stay awake */ | 1165 | /* Make sure (redundant) we've released our request to stay awake */ |
1201 | iwl_clear_bit(trans, CSR_GP_CNTRL, | 1166 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
1202 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1167 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
1203 | 1168 | ||
1204 | /* Stop the device, and put it in low power state */ | 1169 | /* Stop the device, and put it in low power state */ |
1205 | iwl_apm_stop(trans); | 1170 | iwl_apm_stop(trans); |
@@ -1273,8 +1238,9 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1273 | txq->entries[q->write_ptr].cmd = dev_cmd; | 1238 | txq->entries[q->write_ptr].cmd = dev_cmd; |
1274 | 1239 | ||
1275 | dev_cmd->hdr.cmd = REPLY_TX; | 1240 | dev_cmd->hdr.cmd = REPLY_TX; |
1276 | dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | 1241 | dev_cmd->hdr.sequence = |
1277 | INDEX_TO_SEQ(q->write_ptr))); | 1242 | cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | |
1243 | INDEX_TO_SEQ(q->write_ptr))); | ||
1278 | 1244 | ||
1279 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 1245 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
1280 | out_meta = &txq->entries[q->write_ptr].meta; | 1246 | out_meta = &txq->entries[q->write_ptr].meta; |
@@ -1339,7 +1305,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1339 | 1305 | ||
1340 | /* take back ownership of DMA buffer to enable update */ | 1306 | /* take back ownership of DMA buffer to enable update */ |
1341 | dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, | 1307 | dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, |
1342 | DMA_BIDIRECTIONAL); | 1308 | DMA_BIDIRECTIONAL); |
1343 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | 1309 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); |
1344 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | 1310 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); |
1345 | 1311 | ||
@@ -1351,7 +1317,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1351 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); | 1317 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); |
1352 | 1318 | ||
1353 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, | 1319 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, |
1354 | DMA_BIDIRECTIONAL); | 1320 | DMA_BIDIRECTIONAL); |
1355 | 1321 | ||
1356 | trace_iwlwifi_dev_tx(trans->dev, | 1322 | trace_iwlwifi_dev_tx(trans->dev, |
1357 | &txq->tfds[txq->q.write_ptr], | 1323 | &txq->tfds[txq->q.write_ptr], |
@@ -1390,8 +1356,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1390 | 1356 | ||
1391 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | 1357 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) |
1392 | { | 1358 | { |
1393 | struct iwl_trans_pcie *trans_pcie = | 1359 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1394 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1395 | int err; | 1360 | int err; |
1396 | bool hw_rfkill; | 1361 | bool hw_rfkill; |
1397 | 1362 | ||
@@ -1404,7 +1369,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
1404 | iwl_alloc_isr_ict(trans); | 1369 | iwl_alloc_isr_ict(trans); |
1405 | 1370 | ||
1406 | err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED, | 1371 | err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED, |
1407 | DRV_NAME, trans); | 1372 | DRV_NAME, trans); |
1408 | if (err) { | 1373 | if (err) { |
1409 | IWL_ERR(trans, "Error allocating IRQ %d\n", | 1374 | IWL_ERR(trans, "Error allocating IRQ %d\n", |
1410 | trans_pcie->irq); | 1375 | trans_pcie->irq); |
@@ -1442,9 +1407,9 @@ error: | |||
1442 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | 1407 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, |
1443 | bool op_mode_leaving) | 1408 | bool op_mode_leaving) |
1444 | { | 1409 | { |
1410 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1445 | bool hw_rfkill; | 1411 | bool hw_rfkill; |
1446 | unsigned long flags; | 1412 | unsigned long flags; |
1447 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1448 | 1413 | ||
1449 | iwl_apm_stop(trans); | 1414 | iwl_apm_stop(trans); |
1450 | 1415 | ||
@@ -1548,8 +1513,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1548 | 1513 | ||
1549 | void iwl_trans_pcie_free(struct iwl_trans *trans) | 1514 | void iwl_trans_pcie_free(struct iwl_trans *trans) |
1550 | { | 1515 | { |
1551 | struct iwl_trans_pcie *trans_pcie = | 1516 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1552 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1553 | 1517 | ||
1554 | iwl_trans_pcie_tx_free(trans); | 1518 | iwl_trans_pcie_tx_free(trans); |
1555 | #ifndef CONFIG_IWLWIFI_IDI | 1519 | #ifndef CONFIG_IWLWIFI_IDI |
@@ -1564,6 +1528,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1564 | iounmap(trans_pcie->hw_base); | 1528 | iounmap(trans_pcie->hw_base); |
1565 | pci_release_regions(trans_pcie->pci_dev); | 1529 | pci_release_regions(trans_pcie->pci_dev); |
1566 | pci_disable_device(trans_pcie->pci_dev); | 1530 | pci_disable_device(trans_pcie->pci_dev); |
1531 | kmem_cache_destroy(trans->dev_cmd_pool); | ||
1567 | 1532 | ||
1568 | kfree(trans); | 1533 | kfree(trans); |
1569 | } | 1534 | } |
@@ -1811,8 +1776,8 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
1811 | }; | 1776 | }; |
1812 | 1777 | ||
1813 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | 1778 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, |
1814 | char __user *user_buf, | 1779 | char __user *user_buf, |
1815 | size_t count, loff_t *ppos) | 1780 | size_t count, loff_t *ppos) |
1816 | { | 1781 | { |
1817 | struct iwl_trans *trans = file->private_data; | 1782 | struct iwl_trans *trans = file->private_data; |
1818 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1783 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
@@ -1848,11 +1813,11 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
1848 | } | 1813 | } |
1849 | 1814 | ||
1850 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | 1815 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, |
1851 | char __user *user_buf, | 1816 | char __user *user_buf, |
1852 | size_t count, loff_t *ppos) { | 1817 | size_t count, loff_t *ppos) |
1818 | { | ||
1853 | struct iwl_trans *trans = file->private_data; | 1819 | struct iwl_trans *trans = file->private_data; |
1854 | struct iwl_trans_pcie *trans_pcie = | 1820 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1855 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1856 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 1821 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
1857 | char buf[256]; | 1822 | char buf[256]; |
1858 | int pos = 0; | 1823 | int pos = 0; |
@@ -1876,11 +1841,10 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1876 | 1841 | ||
1877 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | 1842 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, |
1878 | char __user *user_buf, | 1843 | char __user *user_buf, |
1879 | size_t count, loff_t *ppos) { | 1844 | size_t count, loff_t *ppos) |
1880 | 1845 | { | |
1881 | struct iwl_trans *trans = file->private_data; | 1846 | struct iwl_trans *trans = file->private_data; |
1882 | struct iwl_trans_pcie *trans_pcie = | 1847 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1883 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1884 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | 1848 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; |
1885 | 1849 | ||
1886 | int pos = 0; | 1850 | int pos = 0; |
@@ -1938,8 +1902,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
1938 | size_t count, loff_t *ppos) | 1902 | size_t count, loff_t *ppos) |
1939 | { | 1903 | { |
1940 | struct iwl_trans *trans = file->private_data; | 1904 | struct iwl_trans *trans = file->private_data; |
1941 | struct iwl_trans_pcie *trans_pcie = | 1905 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1942 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1943 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | 1906 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; |
1944 | 1907 | ||
1945 | char buf[8]; | 1908 | char buf[8]; |
@@ -1959,8 +1922,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
1959 | } | 1922 | } |
1960 | 1923 | ||
1961 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | 1924 | static ssize_t iwl_dbgfs_csr_write(struct file *file, |
1962 | const char __user *user_buf, | 1925 | const char __user *user_buf, |
1963 | size_t count, loff_t *ppos) | 1926 | size_t count, loff_t *ppos) |
1964 | { | 1927 | { |
1965 | struct iwl_trans *trans = file->private_data; | 1928 | struct iwl_trans *trans = file->private_data; |
1966 | char buf[8]; | 1929 | char buf[8]; |
@@ -1980,8 +1943,8 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, | |||
1980 | } | 1943 | } |
1981 | 1944 | ||
1982 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | 1945 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, |
1983 | char __user *user_buf, | 1946 | char __user *user_buf, |
1984 | size_t count, loff_t *ppos) | 1947 | size_t count, loff_t *ppos) |
1985 | { | 1948 | { |
1986 | struct iwl_trans *trans = file->private_data; | 1949 | struct iwl_trans *trans = file->private_data; |
1987 | char *buf; | 1950 | char *buf; |
@@ -2024,7 +1987,7 @@ DEBUGFS_WRITE_FILE_OPS(fw_restart); | |||
2024 | * | 1987 | * |
2025 | */ | 1988 | */ |
2026 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | 1989 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, |
2027 | struct dentry *dir) | 1990 | struct dentry *dir) |
2028 | { | 1991 | { |
2029 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); | 1992 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); |
2030 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); | 1993 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); |
@@ -2036,9 +1999,10 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
2036 | } | 1999 | } |
2037 | #else | 2000 | #else |
2038 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | 2001 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, |
2039 | struct dentry *dir) | 2002 | struct dentry *dir) |
2040 | { return 0; } | 2003 | { |
2041 | 2004 | return 0; | |
2005 | } | ||
2042 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | 2006 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ |
2043 | 2007 | ||
2044 | static const struct iwl_trans_ops trans_ops_pcie = { | 2008 | static const struct iwl_trans_ops trans_ops_pcie = { |
@@ -2055,8 +2019,8 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
2055 | .tx = iwl_trans_pcie_tx, | 2019 | .tx = iwl_trans_pcie_tx, |
2056 | .reclaim = iwl_trans_pcie_reclaim, | 2020 | .reclaim = iwl_trans_pcie_reclaim, |
2057 | 2021 | ||
2058 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | 2022 | .txq_disable = iwl_trans_pcie_txq_disable, |
2059 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | 2023 | .txq_enable = iwl_trans_pcie_txq_enable, |
2060 | 2024 | ||
2061 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 2025 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
2062 | 2026 | ||
@@ -2079,11 +2043,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2079 | { | 2043 | { |
2080 | struct iwl_trans_pcie *trans_pcie; | 2044 | struct iwl_trans_pcie *trans_pcie; |
2081 | struct iwl_trans *trans; | 2045 | struct iwl_trans *trans; |
2046 | char cmd_pool_name[100]; | ||
2082 | u16 pci_cmd; | 2047 | u16 pci_cmd; |
2083 | int err; | 2048 | int err; |
2084 | 2049 | ||
2085 | trans = kzalloc(sizeof(struct iwl_trans) + | 2050 | trans = kzalloc(sizeof(struct iwl_trans) + |
2086 | sizeof(struct iwl_trans_pcie), GFP_KERNEL); | 2051 | sizeof(struct iwl_trans_pcie), GFP_KERNEL); |
2087 | 2052 | ||
2088 | if (WARN_ON(!trans)) | 2053 | if (WARN_ON(!trans)) |
2089 | return NULL; | 2054 | return NULL; |
@@ -2099,7 +2064,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2099 | /* W/A - seems to solve weird behavior. We need to remove this if we | 2064 | /* W/A - seems to solve weird behavior. We need to remove this if we |
2100 | * don't want to stay in L1 all the time. This wastes a lot of power */ | 2065 | * don't want to stay in L1 all the time. This wastes a lot of power */ |
2101 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | 2066 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | |
2102 | PCIE_LINK_STATE_CLKPM); | 2067 | PCIE_LINK_STATE_CLKPM); |
2103 | 2068 | ||
2104 | if (pci_enable_device(pdev)) { | 2069 | if (pci_enable_device(pdev)) { |
2105 | err = -ENODEV; | 2070 | err = -ENODEV; |
@@ -2115,7 +2080,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2115 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 2080 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
2116 | if (!err) | 2081 | if (!err) |
2117 | err = pci_set_consistent_dma_mask(pdev, | 2082 | err = pci_set_consistent_dma_mask(pdev, |
2118 | DMA_BIT_MASK(32)); | 2083 | DMA_BIT_MASK(32)); |
2119 | /* both attempts failed: */ | 2084 | /* both attempts failed: */ |
2120 | if (err) { | 2085 | if (err) { |
2121 | dev_printk(KERN_ERR, &pdev->dev, | 2086 | dev_printk(KERN_ERR, &pdev->dev, |
@@ -2138,13 +2103,13 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2138 | } | 2103 | } |
2139 | 2104 | ||
2140 | dev_printk(KERN_INFO, &pdev->dev, | 2105 | dev_printk(KERN_INFO, &pdev->dev, |
2141 | "pci_resource_len = 0x%08llx\n", | 2106 | "pci_resource_len = 0x%08llx\n", |
2142 | (unsigned long long) pci_resource_len(pdev, 0)); | 2107 | (unsigned long long) pci_resource_len(pdev, 0)); |
2143 | dev_printk(KERN_INFO, &pdev->dev, | 2108 | dev_printk(KERN_INFO, &pdev->dev, |
2144 | "pci_resource_base = %p\n", trans_pcie->hw_base); | 2109 | "pci_resource_base = %p\n", trans_pcie->hw_base); |
2145 | 2110 | ||
2146 | dev_printk(KERN_INFO, &pdev->dev, | 2111 | dev_printk(KERN_INFO, &pdev->dev, |
2147 | "HW Revision ID = 0x%X\n", pdev->revision); | 2112 | "HW Revision ID = 0x%X\n", pdev->revision); |
2148 | 2113 | ||
2149 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 2114 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
2150 | * PCI Tx retries from interfering with C3 CPU state */ | 2115 | * PCI Tx retries from interfering with C3 CPU state */ |
@@ -2153,7 +2118,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2153 | err = pci_enable_msi(pdev); | 2118 | err = pci_enable_msi(pdev); |
2154 | if (err) | 2119 | if (err) |
2155 | dev_printk(KERN_ERR, &pdev->dev, | 2120 | dev_printk(KERN_ERR, &pdev->dev, |
2156 | "pci_enable_msi failed(0X%x)", err); | 2121 | "pci_enable_msi failed(0X%x)", err); |
2157 | 2122 | ||
2158 | trans->dev = &pdev->dev; | 2123 | trans->dev = &pdev->dev; |
2159 | trans_pcie->irq = pdev->irq; | 2124 | trans_pcie->irq = pdev->irq; |
@@ -2175,8 +2140,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2175 | init_waitqueue_head(&trans->wait_command_queue); | 2140 | init_waitqueue_head(&trans->wait_command_queue); |
2176 | spin_lock_init(&trans->reg_lock); | 2141 | spin_lock_init(&trans->reg_lock); |
2177 | 2142 | ||
2143 | snprintf(cmd_pool_name, sizeof(cmd_pool_name), "iwl_cmd_pool:%s", | ||
2144 | dev_name(trans->dev)); | ||
2145 | |||
2146 | trans->dev_cmd_headroom = 0; | ||
2147 | trans->dev_cmd_pool = | ||
2148 | kmem_cache_create(cmd_pool_name, | ||
2149 | sizeof(struct iwl_device_cmd) | ||
2150 | + trans->dev_cmd_headroom, | ||
2151 | sizeof(void *), | ||
2152 | SLAB_HWCACHE_ALIGN, | ||
2153 | NULL); | ||
2154 | |||
2155 | if (!trans->dev_cmd_pool) | ||
2156 | goto out_pci_disable_msi; | ||
2157 | |||
2178 | return trans; | 2158 | return trans; |
2179 | 2159 | ||
2160 | out_pci_disable_msi: | ||
2161 | pci_disable_msi(pdev); | ||
2180 | out_pci_release_regions: | 2162 | out_pci_release_regions: |
2181 | pci_release_regions(pdev); | 2163 | pci_release_regions(pdev); |
2182 | out_pci_disable_device: | 2164 | out_pci_disable_device: |
@@ -2185,4 +2167,3 @@ out_no_pci: | |||
2185 | kfree(trans); | 2167 | kfree(trans); |
2186 | return NULL; | 2168 | return NULL; |
2187 | } | 2169 | } |
2188 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index a8750238ee09..35e82161ca43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -34,11 +34,10 @@ | |||
34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
35 | #include "iwl-prph.h" | 35 | #include "iwl-prph.h" |
36 | #include "iwl-io.h" | 36 | #include "iwl-io.h" |
37 | #include "iwl-agn-hw.h" | ||
38 | #include "iwl-op-mode.h" | 37 | #include "iwl-op-mode.h" |
39 | #include "iwl-trans-pcie-int.h" | 38 | #include "internal.h" |
40 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | 39 | /* FIXME: need to abstract out TX command (once we know what it looks like) */ |
41 | #include "iwl-commands.h" | 40 | #include "dvm/commands.h" |
42 | 41 | ||
43 | #define IWL_TX_CRC_SIZE 4 | 42 | #define IWL_TX_CRC_SIZE 4 |
44 | #define IWL_TX_DELIMITER_SIZE 4 | 43 | #define IWL_TX_DELIMITER_SIZE 4 |
@@ -47,12 +46,11 @@ | |||
47 | * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 46 | * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
48 | */ | 47 | */ |
49 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | 48 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, |
50 | struct iwl_tx_queue *txq, | 49 | struct iwl_tx_queue *txq, |
51 | u16 byte_cnt) | 50 | u16 byte_cnt) |
52 | { | 51 | { |
53 | struct iwlagn_scd_bc_tbl *scd_bc_tbl; | 52 | struct iwlagn_scd_bc_tbl *scd_bc_tbl; |
54 | struct iwl_trans_pcie *trans_pcie = | 53 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
55 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
56 | int write_ptr = txq->q.write_ptr; | 54 | int write_ptr = txq->q.write_ptr; |
57 | int txq_id = txq->q.id; | 55 | int txq_id = txq->q.id; |
58 | u8 sec_ctl = 0; | 56 | u8 sec_ctl = 0; |
@@ -178,8 +176,8 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) | |||
178 | return tfd->num_tbs & 0x1f; | 176 | return tfd->num_tbs & 0x1f; |
179 | } | 177 | } |
180 | 178 | ||
181 | static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, | 179 | static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, |
182 | struct iwl_tfd *tfd, enum dma_data_direction dma_dir) | 180 | struct iwl_tfd *tfd, enum dma_data_direction dma_dir) |
183 | { | 181 | { |
184 | int i; | 182 | int i; |
185 | int num_tbs; | 183 | int num_tbs; |
@@ -209,7 +207,7 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, | |||
209 | } | 207 | } |
210 | 208 | ||
211 | /** | 209 | /** |
212 | * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | 210 | * iwl_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] |
213 | * @trans - transport private data | 211 | * @trans - transport private data |
214 | * @txq - tx queue | 212 | * @txq - tx queue |
215 | * @dma_dir - the direction of the DMA mapping | 213 | * @dma_dir - the direction of the DMA mapping |
@@ -217,8 +215,8 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, | |||
217 | * Does NOT advance any TFD circular buffer read/write indexes | 215 | * Does NOT advance any TFD circular buffer read/write indexes |
218 | * Does NOT free the TFD itself (which is within circular buffer) | 216 | * Does NOT free the TFD itself (which is within circular buffer) |
219 | */ | 217 | */ |
220 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 218 | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
221 | enum dma_data_direction dma_dir) | 219 | enum dma_data_direction dma_dir) |
222 | { | 220 | { |
223 | struct iwl_tfd *tfd_tmp = txq->tfds; | 221 | struct iwl_tfd *tfd_tmp = txq->tfds; |
224 | 222 | ||
@@ -229,8 +227,8 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | |||
229 | lockdep_assert_held(&txq->lock); | 227 | lockdep_assert_held(&txq->lock); |
230 | 228 | ||
231 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ | 229 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ |
232 | iwlagn_unmap_tfd(trans, &txq->entries[idx].meta, | 230 | iwl_unmap_tfd(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr], |
233 | &tfd_tmp[rd_ptr], dma_dir); | 231 | dma_dir); |
234 | 232 | ||
235 | /* free SKB */ | 233 | /* free SKB */ |
236 | if (txq->entries) { | 234 | if (txq->entries) { |
@@ -270,7 +268,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, | |||
270 | /* Each TFD can point to a maximum 20 Tx buffers */ | 268 | /* Each TFD can point to a maximum 20 Tx buffers */ |
271 | if (num_tbs >= IWL_NUM_OF_TBS) { | 269 | if (num_tbs >= IWL_NUM_OF_TBS) { |
272 | IWL_ERR(trans, "Error can not send more than %d chunks\n", | 270 | IWL_ERR(trans, "Error can not send more than %d chunks\n", |
273 | IWL_NUM_OF_TBS); | 271 | IWL_NUM_OF_TBS); |
274 | return -EINVAL; | 272 | return -EINVAL; |
275 | } | 273 | } |
276 | 274 | ||
@@ -279,7 +277,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, | |||
279 | 277 | ||
280 | if (unlikely(addr & ~IWL_TX_DMA_MASK)) | 278 | if (unlikely(addr & ~IWL_TX_DMA_MASK)) |
281 | IWL_ERR(trans, "Unaligned address = %llx\n", | 279 | IWL_ERR(trans, "Unaligned address = %llx\n", |
282 | (unsigned long long)addr); | 280 | (unsigned long long)addr); |
283 | 281 | ||
284 | iwl_tfd_set_tb(tfd, num_tbs, addr, len); | 282 | iwl_tfd_set_tb(tfd, num_tbs, addr, len); |
285 | 283 | ||
@@ -383,15 +381,13 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, | |||
383 | } | 381 | } |
384 | 382 | ||
385 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, | 383 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, |
386 | u16 txq_id) | 384 | u16 txq_id) |
387 | { | 385 | { |
386 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
388 | u32 tbl_dw_addr; | 387 | u32 tbl_dw_addr; |
389 | u32 tbl_dw; | 388 | u32 tbl_dw; |
390 | u16 scd_q2ratid; | 389 | u16 scd_q2ratid; |
391 | 390 | ||
392 | struct iwl_trans_pcie *trans_pcie = | ||
393 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
394 | |||
395 | scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; | 391 | scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; |
396 | 392 | ||
397 | tbl_dw_addr = trans_pcie->scd_base_addr + | 393 | tbl_dw_addr = trans_pcie->scd_base_addr + |
@@ -419,12 +415,11 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) | |||
419 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | 415 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); |
420 | } | 416 | } |
421 | 417 | ||
422 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, | 418 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index) |
423 | int txq_id, u32 index) | ||
424 | { | 419 | { |
425 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d\n", txq_id, index & 0xff); | 420 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d\n", txq_id, index & 0xff); |
426 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | 421 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
427 | (index & 0xff) | (txq_id << 8)); | 422 | (index & 0xff) | (txq_id << 8)); |
428 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); | 423 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); |
429 | } | 424 | } |
430 | 425 | ||
@@ -447,29 +442,34 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | |||
447 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | 442 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
448 | } | 443 | } |
449 | 444 | ||
450 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | 445 | void __iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, |
451 | int sta_id, int tid, int frame_limit, u16 ssn) | 446 | int fifo, int sta_id, int tid, |
447 | int frame_limit, u16 ssn) | ||
452 | { | 448 | { |
453 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 449 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
454 | unsigned long flags; | 450 | |
455 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | 451 | lockdep_assert_held(&trans_pcie->irq_lock); |
456 | 452 | ||
457 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 453 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
458 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 454 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
459 | 455 | ||
460 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
461 | |||
462 | /* Stop this Tx queue before configuring it */ | 456 | /* Stop this Tx queue before configuring it */ |
463 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 457 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); |
464 | 458 | ||
465 | /* Map receiver-address / traffic-ID to this queue */ | 459 | /* Set this queue as a chain-building queue unless it is CMD queue */ |
466 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | 460 | if (txq_id != trans_pcie->cmd_queue) |
461 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | ||
462 | |||
463 | /* If this queue is mapped to a certain station: it is an AGG queue */ | ||
464 | if (sta_id != IWL_INVALID_STATION) { | ||
465 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | ||
467 | 466 | ||
468 | /* Set this queue as a chain-building queue */ | 467 | /* Map receiver-address / traffic-ID to this queue */ |
469 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | 468 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); |
470 | 469 | ||
471 | /* enable aggregations for the queue */ | 470 | /* enable aggregations for the queue */ |
472 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | 471 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); |
472 | } | ||
473 | 473 | ||
474 | /* Place first TFD at index corresponding to start sequence number. | 474 | /* Place first TFD at index corresponding to start sequence number. |
475 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 475 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
@@ -479,22 +479,34 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | |||
479 | 479 | ||
480 | /* Set up Tx window size and frame limit for this queue */ | 480 | /* Set up Tx window size and frame limit for this queue */ |
481 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 481 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
482 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); | ||
483 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||
482 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | 484 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), |
483 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 485 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |
484 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | 486 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |
485 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | 487 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |
486 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 488 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
487 | 489 | ||
488 | iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
489 | |||
490 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 490 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ |
491 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 491 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], |
492 | fifo, true); | 492 | fifo, true); |
493 | } | ||
494 | |||
495 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | ||
496 | int sta_id, int tid, int frame_limit, u16 ssn) | ||
497 | { | ||
498 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
499 | unsigned long flags; | ||
500 | |||
501 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||
502 | |||
503 | __iwl_trans_pcie_txq_enable(trans, txq_id, fifo, sta_id, | ||
504 | tid, frame_limit, ssn); | ||
493 | 505 | ||
494 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 506 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
495 | } | 507 | } |
496 | 508 | ||
497 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) | 509 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) |
498 | { | 510 | { |
499 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 511 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
500 | 512 | ||
@@ -511,8 +523,6 @@ void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) | |||
511 | trans_pcie->txq[txq_id].q.write_ptr = 0; | 523 | trans_pcie->txq[txq_id].q.write_ptr = 0; |
512 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); | 524 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); |
513 | 525 | ||
514 | iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, BIT(txq_id)); | ||
515 | |||
516 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 526 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], |
517 | 0, false); | 527 | 0, false); |
518 | } | 528 | } |
@@ -615,13 +625,13 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
615 | } | 625 | } |
616 | 626 | ||
617 | IWL_DEBUG_HC(trans, | 627 | IWL_DEBUG_HC(trans, |
618 | "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", | 628 | "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", |
619 | trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd), | 629 | trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd), |
620 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, | 630 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), |
621 | q->write_ptr, idx, trans_pcie->cmd_queue); | 631 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); |
622 | 632 | ||
623 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, | 633 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, |
624 | DMA_BIDIRECTIONAL); | 634 | DMA_BIDIRECTIONAL); |
625 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 635 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { |
626 | idx = -ENOMEM; | 636 | idx = -ENOMEM; |
627 | goto out; | 637 | goto out; |
@@ -630,8 +640,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
630 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 640 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
631 | dma_unmap_len_set(out_meta, len, copy_size); | 641 | dma_unmap_len_set(out_meta, len, copy_size); |
632 | 642 | ||
633 | iwlagn_txq_attach_buf_to_tfd(trans, txq, | 643 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1); |
634 | phys_addr, copy_size, 1); | ||
635 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING | 644 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING |
636 | trace_bufs[0] = &out_cmd->hdr; | 645 | trace_bufs[0] = &out_cmd->hdr; |
637 | trace_lens[0] = copy_size; | 646 | trace_lens[0] = copy_size; |
@@ -643,13 +652,12 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
643 | continue; | 652 | continue; |
644 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | 653 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) |
645 | continue; | 654 | continue; |
646 | phys_addr = dma_map_single(trans->dev, | 655 | phys_addr = dma_map_single(trans->dev, (void *)cmd->data[i], |
647 | (void *)cmd->data[i], | ||
648 | cmd->len[i], DMA_BIDIRECTIONAL); | 656 | cmd->len[i], DMA_BIDIRECTIONAL); |
649 | if (dma_mapping_error(trans->dev, phys_addr)) { | 657 | if (dma_mapping_error(trans->dev, phys_addr)) { |
650 | iwlagn_unmap_tfd(trans, out_meta, | 658 | iwl_unmap_tfd(trans, out_meta, |
651 | &txq->tfds[q->write_ptr], | 659 | &txq->tfds[q->write_ptr], |
652 | DMA_BIDIRECTIONAL); | 660 | DMA_BIDIRECTIONAL); |
653 | idx = -ENOMEM; | 661 | idx = -ENOMEM; |
654 | goto out; | 662 | goto out; |
655 | } | 663 | } |
@@ -723,9 +731,10 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, | |||
723 | lockdep_assert_held(&txq->lock); | 731 | lockdep_assert_held(&txq->lock); |
724 | 732 | ||
725 | if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { | 733 | if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { |
726 | IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " | 734 | IWL_ERR(trans, |
727 | "index %d is out of range [0-%d] %d %d.\n", __func__, | 735 | "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", |
728 | txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr); | 736 | __func__, txq_id, idx, q->n_bd, |
737 | q->write_ptr, q->read_ptr); | ||
729 | return; | 738 | return; |
730 | } | 739 | } |
731 | 740 | ||
@@ -733,8 +742,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, | |||
733 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 742 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
734 | 743 | ||
735 | if (nfreed++ > 0) { | 744 | if (nfreed++ > 0) { |
736 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx, | 745 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", |
737 | q->write_ptr, q->read_ptr); | 746 | idx, q->write_ptr, q->read_ptr); |
738 | iwl_op_mode_nic_error(trans->op_mode); | 747 | iwl_op_mode_nic_error(trans->op_mode); |
739 | } | 748 | } |
740 | 749 | ||
@@ -771,9 +780,9 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
771 | * in the queue management code. */ | 780 | * in the queue management code. */ |
772 | if (WARN(txq_id != trans_pcie->cmd_queue, | 781 | if (WARN(txq_id != trans_pcie->cmd_queue, |
773 | "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", | 782 | "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", |
774 | txq_id, trans_pcie->cmd_queue, sequence, | 783 | txq_id, trans_pcie->cmd_queue, sequence, |
775 | trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr, | 784 | trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr, |
776 | trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) { | 785 | trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) { |
777 | iwl_print_hex_error(trans, pkt, 32); | 786 | iwl_print_hex_error(trans, pkt, 32); |
778 | return; | 787 | return; |
779 | } | 788 | } |
@@ -784,8 +793,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
784 | cmd = txq->entries[cmd_index].cmd; | 793 | cmd = txq->entries[cmd_index].cmd; |
785 | meta = &txq->entries[cmd_index].meta; | 794 | meta = &txq->entries[cmd_index].meta; |
786 | 795 | ||
787 | iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], | 796 | iwl_unmap_tfd(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); |
788 | DMA_BIDIRECTIONAL); | ||
789 | 797 | ||
790 | /* Input error checking is done when commands are added to queue. */ | 798 | /* Input error checking is done when commands are added to queue. */ |
791 | if (meta->flags & CMD_WANT_SKB) { | 799 | if (meta->flags & CMD_WANT_SKB) { |
@@ -870,8 +878,9 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
870 | } | 878 | } |
871 | 879 | ||
872 | ret = wait_event_timeout(trans->wait_command_queue, | 880 | ret = wait_event_timeout(trans->wait_command_queue, |
873 | !test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status), | 881 | !test_bit(STATUS_HCMD_ACTIVE, |
874 | HOST_COMPLETE_TIMEOUT); | 882 | &trans_pcie->status), |
883 | HOST_COMPLETE_TIMEOUT); | ||
875 | if (!ret) { | 884 | if (!ret) { |
876 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { | 885 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { |
877 | struct iwl_tx_queue *txq = | 886 | struct iwl_tx_queue *txq = |
@@ -956,10 +965,10 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | |||
956 | 965 | ||
957 | if ((index >= q->n_bd) || | 966 | if ((index >= q->n_bd) || |
958 | (iwl_queue_used(q, last_to_free) == 0)) { | 967 | (iwl_queue_used(q, last_to_free) == 0)) { |
959 | IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " | 968 | IWL_ERR(trans, |
960 | "last_to_free %d is out of range [0-%d] %d %d.\n", | 969 | "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", |
961 | __func__, txq_id, last_to_free, q->n_bd, | 970 | __func__, txq_id, last_to_free, q->n_bd, |
962 | q->write_ptr, q->read_ptr); | 971 | q->write_ptr, q->read_ptr); |
963 | return 0; | 972 | return 0; |
964 | } | 973 | } |
965 | 974 | ||
@@ -979,7 +988,7 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | |||
979 | 988 | ||
980 | iwlagn_txq_inval_byte_cnt_tbl(trans, txq); | 989 | iwlagn_txq_inval_byte_cnt_tbl(trans, txq); |
981 | 990 | ||
982 | iwlagn_txq_free_tfd(trans, txq, DMA_TO_DEVICE); | 991 | iwl_txq_free_tfd(trans, txq, DMA_TO_DEVICE); |
983 | freed++; | 992 | freed++; |
984 | } | 993 | } |
985 | 994 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 2fa879b015b6..f4a203049fb4 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -435,24 +435,40 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) | |||
435 | * Set Channel | 435 | * Set Channel |
436 | */ | 436 | */ |
437 | 437 | ||
438 | static int lbs_cfg_set_channel(struct wiphy *wiphy, | 438 | static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy, |
439 | struct net_device *netdev, | 439 | struct ieee80211_channel *channel, |
440 | struct ieee80211_channel *channel, | 440 | enum nl80211_channel_type channel_type) |
441 | enum nl80211_channel_type channel_type) | ||
442 | { | 441 | { |
443 | struct lbs_private *priv = wiphy_priv(wiphy); | 442 | struct lbs_private *priv = wiphy_priv(wiphy); |
444 | int ret = -ENOTSUPP; | 443 | int ret = -ENOTSUPP; |
445 | 444 | ||
446 | lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d", | 445 | lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", |
447 | netdev_name(netdev), channel->center_freq, channel_type); | 446 | channel->center_freq, channel_type); |
448 | 447 | ||
449 | if (channel_type != NL80211_CHAN_NO_HT) | 448 | if (channel_type != NL80211_CHAN_NO_HT) |
450 | goto out; | 449 | goto out; |
451 | 450 | ||
452 | if (netdev == priv->mesh_dev) | 451 | ret = lbs_set_channel(priv, channel->hw_value); |
453 | ret = lbs_mesh_set_channel(priv, channel->hw_value); | 452 | |
454 | else | 453 | out: |
455 | ret = lbs_set_channel(priv, channel->hw_value); | 454 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
455 | return ret; | ||
456 | } | ||
457 | |||
458 | static int lbs_cfg_set_mesh_channel(struct wiphy *wiphy, | ||
459 | struct net_device *netdev, | ||
460 | struct ieee80211_channel *channel) | ||
461 | { | ||
462 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
463 | int ret = -ENOTSUPP; | ||
464 | |||
465 | lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d", | ||
466 | netdev_name(netdev), channel->center_freq); | ||
467 | |||
468 | if (netdev != priv->mesh_dev) | ||
469 | goto out; | ||
470 | |||
471 | ret = lbs_mesh_set_channel(priv, channel->hw_value); | ||
456 | 472 | ||
457 | out: | 473 | out: |
458 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 474 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
@@ -2029,7 +2045,8 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
2029 | */ | 2045 | */ |
2030 | 2046 | ||
2031 | static struct cfg80211_ops lbs_cfg80211_ops = { | 2047 | static struct cfg80211_ops lbs_cfg80211_ops = { |
2032 | .set_channel = lbs_cfg_set_channel, | 2048 | .set_monitor_channel = lbs_cfg_set_monitor_channel, |
2049 | .libertas_set_mesh_channel = lbs_cfg_set_mesh_channel, | ||
2033 | .scan = lbs_cfg_scan, | 2050 | .scan = lbs_cfg_scan, |
2034 | .connect = lbs_cfg_connect, | 2051 | .connect = lbs_cfg_connect, |
2035 | .disconnect = lbs_cfg_disconnect, | 2052 | .disconnect = lbs_cfg_disconnect, |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 672005430aca..60996ce89f77 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -58,6 +58,7 @@ struct lbs_private { | |||
58 | uint16_t mesh_tlv; | 58 | uint16_t mesh_tlv; |
59 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; | 59 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; |
60 | u8 mesh_ssid_len; | 60 | u8 mesh_ssid_len; |
61 | u8 mesh_channel; | ||
61 | #endif | 62 | #endif |
62 | 63 | ||
63 | /* Debugfs */ | 64 | /* Debugfs */ |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index e87c031b298f..97807751ebcf 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -131,16 +131,13 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, | |||
131 | 131 | ||
132 | int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel) | 132 | int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel) |
133 | { | 133 | { |
134 | priv->mesh_channel = channel; | ||
134 | return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel); | 135 | return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel); |
135 | } | 136 | } |
136 | 137 | ||
137 | static uint16_t lbs_mesh_get_channel(struct lbs_private *priv) | 138 | static uint16_t lbs_mesh_get_channel(struct lbs_private *priv) |
138 | { | 139 | { |
139 | struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr; | 140 | return priv->mesh_channel ?: 1; |
140 | if (mesh_wdev->channel) | ||
141 | return mesh_wdev->channel->hw_value; | ||
142 | else | ||
143 | return 1; | ||
144 | } | 141 | } |
145 | 142 | ||
146 | /*************************************************************************** | 143 | /*************************************************************************** |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index c1cb004db913..0f18ef6a30c8 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -57,6 +57,68 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static void scan_delay_timer_fn(unsigned long data) | ||
61 | { | ||
62 | struct mwifiex_private *priv = (struct mwifiex_private *)data; | ||
63 | struct mwifiex_adapter *adapter = priv->adapter; | ||
64 | struct cmd_ctrl_node *cmd_node, *tmp_node; | ||
65 | unsigned long flags; | ||
66 | |||
67 | if (!mwifiex_wmm_lists_empty(adapter)) { | ||
68 | if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { | ||
69 | /* | ||
70 | * Abort scan operation by cancelling all pending scan | ||
71 | * command | ||
72 | */ | ||
73 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
74 | list_for_each_entry_safe(cmd_node, tmp_node, | ||
75 | &adapter->scan_pending_q, | ||
76 | list) { | ||
77 | list_del(&cmd_node->list); | ||
78 | cmd_node->wait_q_enabled = false; | ||
79 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
80 | } | ||
81 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
82 | flags); | ||
83 | |||
84 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
85 | adapter->scan_processing = false; | ||
86 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, | ||
87 | flags); | ||
88 | |||
89 | if (priv->user_scan_cfg) { | ||
90 | dev_dbg(priv->adapter->dev, | ||
91 | "info: %s: scan aborted\n", __func__); | ||
92 | cfg80211_scan_done(priv->scan_request, 1); | ||
93 | priv->scan_request = NULL; | ||
94 | kfree(priv->user_scan_cfg); | ||
95 | priv->user_scan_cfg = NULL; | ||
96 | } | ||
97 | } else { | ||
98 | /* | ||
99 | * Tx data queue is still not empty, delay scan | ||
100 | * operation further by 20msec. | ||
101 | */ | ||
102 | mod_timer(&priv->scan_delay_timer, jiffies + | ||
103 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | ||
104 | adapter->scan_delay_cnt++; | ||
105 | } | ||
106 | } else { | ||
107 | /* | ||
108 | * Tx data queue is empty. Get scan command from scan_pending_q | ||
109 | * and put to cmd_pending_q to resume scan operation | ||
110 | */ | ||
111 | adapter->scan_delay_cnt = 0; | ||
112 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
113 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
114 | struct cmd_ctrl_node, list); | ||
115 | list_del(&cmd_node->list); | ||
116 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
117 | |||
118 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | ||
119 | } | ||
120 | } | ||
121 | |||
60 | /* | 122 | /* |
61 | * This function initializes the private structure and sets default | 123 | * This function initializes the private structure and sets default |
62 | * values to the members. | 124 | * values to the members. |
@@ -136,6 +198,9 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) | |||
136 | 198 | ||
137 | priv->scan_block = false; | 199 | priv->scan_block = false; |
138 | 200 | ||
201 | setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn, | ||
202 | (unsigned long)priv); | ||
203 | |||
139 | return mwifiex_add_bss_prio_tbl(priv); | 204 | return mwifiex_add_bss_prio_tbl(priv); |
140 | } | 205 | } |
141 | 206 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 3192855c31c0..0f06f07a70e6 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -244,8 +244,8 @@ process_start: | |||
244 | } | 244 | } |
245 | } | 245 | } |
246 | 246 | ||
247 | if (!adapter->scan_processing && !adapter->data_sent && | 247 | if ((!adapter->scan_processing || adapter->scan_delay_cnt) && |
248 | !mwifiex_wmm_lists_empty(adapter)) { | 248 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { |
249 | mwifiex_wmm_process_tx(adapter); | 249 | mwifiex_wmm_process_tx(adapter); |
250 | if (adapter->hs_activated) { | 250 | if (adapter->hs_activated) { |
251 | adapter->is_hs_configured = false; | 251 | adapter->is_hs_configured = false; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index bd3b0bf94b9e..5b32221077c4 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -79,14 +79,17 @@ enum { | |||
79 | 79 | ||
80 | #define SCAN_BEACON_ENTRY_PAD 6 | 80 | #define SCAN_BEACON_ENTRY_PAD 6 |
81 | 81 | ||
82 | #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 200 | 82 | #define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110 |
83 | #define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 200 | 83 | #define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30 |
84 | #define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 110 | 84 | #define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30 |
85 | 85 | ||
86 | #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) | 86 | #define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) |
87 | 87 | ||
88 | #define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) | 88 | #define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) |
89 | 89 | ||
90 | #define MWIFIEX_MAX_SCAN_DELAY_CNT 50 | ||
91 | #define MWIFIEX_SCAN_DELAY_MSEC 20 | ||
92 | |||
90 | #define RSN_GTK_OUI_OFFSET 2 | 93 | #define RSN_GTK_OUI_OFFSET 2 |
91 | 94 | ||
92 | #define MWIFIEX_OUI_NOT_PRESENT 0 | 95 | #define MWIFIEX_OUI_NOT_PRESENT 0 |
@@ -482,6 +485,7 @@ struct mwifiex_private { | |||
482 | u16 proberesp_idx; | 485 | u16 proberesp_idx; |
483 | u16 assocresp_idx; | 486 | u16 assocresp_idx; |
484 | u16 rsn_idx; | 487 | u16 rsn_idx; |
488 | struct timer_list scan_delay_timer; | ||
485 | }; | 489 | }; |
486 | 490 | ||
487 | enum mwifiex_ba_status { | 491 | enum mwifiex_ba_status { |
@@ -686,6 +690,7 @@ struct mwifiex_adapter { | |||
686 | struct completion fw_load; | 690 | struct completion fw_load; |
687 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 691 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
688 | u16 max_mgmt_ie_index; | 692 | u16 max_mgmt_ie_index; |
693 | u8 scan_delay_cnt; | ||
689 | }; | 694 | }; |
690 | 695 | ||
691 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 696 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 8fa763fa629a..98c6aabd5a48 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -28,7 +28,10 @@ | |||
28 | /* The maximum number of channels the firmware can scan per command */ | 28 | /* The maximum number of channels the firmware can scan per command */ |
29 | #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 | 29 | #define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 |
30 | 30 | ||
31 | #define MWIFIEX_CHANNELS_PER_SCAN_CMD 4 | 31 | #define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4 |
32 | #define MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD 15 | ||
33 | #define MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD 27 | ||
34 | #define MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD 35 | ||
32 | 35 | ||
33 | /* Memory needed to store a max sized Channel List TLV for a firmware scan */ | 36 | /* Memory needed to store a max sized Channel List TLV for a firmware scan */ |
34 | #define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ | 37 | #define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ |
@@ -471,7 +474,7 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, | |||
471 | * This routine is used for any scan that is not provided with a | 474 | * This routine is used for any scan that is not provided with a |
472 | * specific channel list to scan. | 475 | * specific channel list to scan. |
473 | */ | 476 | */ |
474 | static void | 477 | static int |
475 | mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | 478 | mwifiex_scan_create_channel_list(struct mwifiex_private *priv, |
476 | const struct mwifiex_user_scan_cfg | 479 | const struct mwifiex_user_scan_cfg |
477 | *user_scan_in, | 480 | *user_scan_in, |
@@ -528,6 +531,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
528 | } | 531 | } |
529 | 532 | ||
530 | } | 533 | } |
534 | return chan_idx; | ||
531 | } | 535 | } |
532 | 536 | ||
533 | /* | 537 | /* |
@@ -727,6 +731,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
727 | u32 num_probes; | 731 | u32 num_probes; |
728 | u32 ssid_len; | 732 | u32 ssid_len; |
729 | u32 chan_idx; | 733 | u32 chan_idx; |
734 | u32 chan_num; | ||
730 | u32 scan_type; | 735 | u32 scan_type; |
731 | u16 scan_dur; | 736 | u16 scan_dur; |
732 | u8 channel; | 737 | u8 channel; |
@@ -850,7 +855,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
850 | if (*filtered_scan) | 855 | if (*filtered_scan) |
851 | *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; | 856 | *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; |
852 | else | 857 | else |
853 | *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD; | 858 | *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD; |
854 | 859 | ||
855 | /* If the input config or adapter has the number of Probes set, | 860 | /* If the input config or adapter has the number of Probes set, |
856 | add tlv */ | 861 | add tlv */ |
@@ -962,13 +967,28 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
962 | dev_dbg(adapter->dev, | 967 | dev_dbg(adapter->dev, |
963 | "info: Scan: Scanning current channel only\n"); | 968 | "info: Scan: Scanning current channel only\n"); |
964 | } | 969 | } |
965 | 970 | chan_num = chan_idx; | |
966 | } else { | 971 | } else { |
967 | dev_dbg(adapter->dev, | 972 | dev_dbg(adapter->dev, |
968 | "info: Scan: Creating full region channel list\n"); | 973 | "info: Scan: Creating full region channel list\n"); |
969 | mwifiex_scan_create_channel_list(priv, user_scan_in, | 974 | chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in, |
970 | scan_chan_list, | 975 | scan_chan_list, |
971 | *filtered_scan); | 976 | *filtered_scan); |
977 | } | ||
978 | |||
979 | /* | ||
980 | * In associated state we will reduce the number of channels scanned per | ||
981 | * scan command to avoid any traffic delay/loss. This number is decided | ||
982 | * based on total number of channels to be scanned due to constraints | ||
983 | * of command buffers. | ||
984 | */ | ||
985 | if (priv->media_connected) { | ||
986 | if (chan_num < MWIFIEX_LIMIT_1_CHANNEL_PER_SCAN_CMD) | ||
987 | *max_chan_per_scan = 1; | ||
988 | else if (chan_num < MWIFIEX_LIMIT_2_CHANNELS_PER_SCAN_CMD) | ||
989 | *max_chan_per_scan = 2; | ||
990 | else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD) | ||
991 | *max_chan_per_scan = 3; | ||
972 | } | 992 | } |
973 | } | 993 | } |
974 | 994 | ||
@@ -1769,14 +1789,23 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1769 | priv->user_scan_cfg = NULL; | 1789 | priv->user_scan_cfg = NULL; |
1770 | } | 1790 | } |
1771 | } else { | 1791 | } else { |
1772 | /* Get scan command from scan_pending_q and put to | 1792 | if (!mwifiex_wmm_lists_empty(adapter)) { |
1773 | cmd_pending_q */ | 1793 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1774 | cmd_node = list_first_entry(&adapter->scan_pending_q, | 1794 | flags); |
1775 | struct cmd_ctrl_node, list); | 1795 | adapter->scan_delay_cnt = 1; |
1776 | list_del(&cmd_node->list); | 1796 | mod_timer(&priv->scan_delay_timer, jiffies + |
1777 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 1797 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); |
1778 | 1798 | } else { | |
1779 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 1799 | /* Get scan command from scan_pending_q and put to |
1800 | cmd_pending_q */ | ||
1801 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
1802 | struct cmd_ctrl_node, list); | ||
1803 | list_del(&cmd_node->list); | ||
1804 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1805 | flags); | ||
1806 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||
1807 | true); | ||
1808 | } | ||
1780 | } | 1809 | } |
1781 | 1810 | ||
1782 | done: | 1811 | done: |
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index f7b15b8934fa..e15675585fb1 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c | |||
@@ -160,10 +160,9 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, | |||
160 | return err; | 160 | return err; |
161 | } | 161 | } |
162 | 162 | ||
163 | static int orinoco_set_channel(struct wiphy *wiphy, | 163 | static int orinoco_set_monitor_channel(struct wiphy *wiphy, |
164 | struct net_device *netdev, | 164 | struct ieee80211_channel *chan, |
165 | struct ieee80211_channel *chan, | 165 | enum nl80211_channel_type channel_type) |
166 | enum nl80211_channel_type channel_type) | ||
167 | { | 166 | { |
168 | struct orinoco_private *priv = wiphy_priv(wiphy); | 167 | struct orinoco_private *priv = wiphy_priv(wiphy); |
169 | int err = 0; | 168 | int err = 0; |
@@ -286,7 +285,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
286 | 285 | ||
287 | const struct cfg80211_ops orinoco_cfg_ops = { | 286 | const struct cfg80211_ops orinoco_cfg_ops = { |
288 | .change_virtual_intf = orinoco_change_vif, | 287 | .change_virtual_intf = orinoco_change_vif, |
289 | .set_channel = orinoco_set_channel, | 288 | .set_monitor_channel = orinoco_set_monitor_channel, |
290 | .scan = orinoco_scan, | 289 | .scan = orinoco_scan, |
291 | .set_wiphy_params = orinoco_set_wiphy_params, | 290 | .set_wiphy_params = orinoco_set_wiphy_params, |
292 | }; | 291 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 9348521e0832..1ca88cdc6ece 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -51,6 +51,7 @@ | |||
51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) | 51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) |
52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) | 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) |
53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) | 53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) |
54 | * RF5360 2.4G 1T1R | ||
54 | * RF5370 2.4G 1T1R | 55 | * RF5370 2.4G 1T1R |
55 | * RF5390 2.4G 1T1R | 56 | * RF5390 2.4G 1T1R |
56 | */ | 57 | */ |
@@ -67,9 +68,11 @@ | |||
67 | #define RF3320 0x000b | 68 | #define RF3320 0x000b |
68 | #define RF3322 0x000c | 69 | #define RF3322 0x000c |
69 | #define RF3053 0x000d | 70 | #define RF3053 0x000d |
71 | #define RF5360 0x5360 | ||
70 | #define RF5370 0x5370 | 72 | #define RF5370 0x5370 |
71 | #define RF5372 0x5372 | 73 | #define RF5372 0x5372 |
72 | #define RF5390 0x5390 | 74 | #define RF5390 0x5390 |
75 | #define RF5392 0x5392 | ||
73 | 76 | ||
74 | /* | 77 | /* |
75 | * Chipset revisions. | 78 | * Chipset revisions. |
@@ -1944,6 +1947,11 @@ struct mac_iveiv_entry { | |||
1944 | #define RFCSR49_TX FIELD8(0x3f) | 1947 | #define RFCSR49_TX FIELD8(0x3f) |
1945 | 1948 | ||
1946 | /* | 1949 | /* |
1950 | * RFCSR 50: | ||
1951 | */ | ||
1952 | #define RFCSR50_TX FIELD8(0x3f) | ||
1953 | |||
1954 | /* | ||
1947 | * RF registers | 1955 | * RF registers |
1948 | */ | 1956 | */ |
1949 | 1957 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index dfc90d34be6d..4d3747c3010b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1958,7 +1958,22 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
1958 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | 1958 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); |
1959 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | 1959 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); |
1960 | 1960 | ||
1961 | if (rt2x00_rt(rt2x00dev, RT5392)) { | ||
1962 | rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); | ||
1963 | if (info->default_power1 > RT5390_POWER_BOUND) | ||
1964 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, | ||
1965 | RT5390_POWER_BOUND); | ||
1966 | else | ||
1967 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, | ||
1968 | info->default_power2); | ||
1969 | rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); | ||
1970 | } | ||
1971 | |||
1961 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | 1972 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); |
1973 | if (rt2x00_rt(rt2x00dev, RT5392)) { | ||
1974 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); | ||
1975 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); | ||
1976 | } | ||
1962 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); | 1977 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); |
1963 | rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); | 1978 | rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); |
1964 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 1979 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
@@ -2060,9 +2075,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2060 | case RF3052: | 2075 | case RF3052: |
2061 | rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); | 2076 | rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); |
2062 | break; | 2077 | break; |
2078 | case RF5360: | ||
2063 | case RF5370: | 2079 | case RF5370: |
2064 | case RF5372: | 2080 | case RF5372: |
2065 | case RF5390: | 2081 | case RF5390: |
2082 | case RF5392: | ||
2066 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); | 2083 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); |
2067 | break; | 2084 | break; |
2068 | default: | 2085 | default: |
@@ -2549,9 +2566,11 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) | |||
2549 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | 2566 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); |
2550 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | 2567 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); |
2551 | break; | 2568 | break; |
2569 | case RF5360: | ||
2552 | case RF5370: | 2570 | case RF5370: |
2553 | case RF5372: | 2571 | case RF5372: |
2554 | case RF5390: | 2572 | case RF5390: |
2573 | case RF5392: | ||
2555 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | 2574 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); |
2556 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | 2575 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); |
2557 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | 2576 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); |
@@ -4263,9 +4282,11 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4263 | case RF3022: | 4282 | case RF3022: |
4264 | case RF3052: | 4283 | case RF3052: |
4265 | case RF3320: | 4284 | case RF3320: |
4285 | case RF5360: | ||
4266 | case RF5370: | 4286 | case RF5370: |
4267 | case RF5372: | 4287 | case RF5372: |
4268 | case RF5390: | 4288 | case RF5390: |
4289 | case RF5392: | ||
4269 | break; | 4290 | break; |
4270 | default: | 4291 | default: |
4271 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", | 4292 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", |
@@ -4577,9 +4598,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
4577 | rt2x00_rf(rt2x00dev, RF3021) || | 4598 | rt2x00_rf(rt2x00dev, RF3021) || |
4578 | rt2x00_rf(rt2x00dev, RF3022) || | 4599 | rt2x00_rf(rt2x00dev, RF3022) || |
4579 | rt2x00_rf(rt2x00dev, RF3320) || | 4600 | rt2x00_rf(rt2x00dev, RF3320) || |
4601 | rt2x00_rf(rt2x00dev, RF5360) || | ||
4580 | rt2x00_rf(rt2x00dev, RF5370) || | 4602 | rt2x00_rf(rt2x00dev, RF5370) || |
4581 | rt2x00_rf(rt2x00dev, RF5372) || | 4603 | rt2x00_rf(rt2x00dev, RF5372) || |
4582 | rt2x00_rf(rt2x00dev, RF5390)) { | 4604 | rt2x00_rf(rt2x00dev, RF5390) || |
4605 | rt2x00_rf(rt2x00dev, RF5392)) { | ||
4583 | spec->num_channels = 14; | 4606 | spec->num_channels = 14; |
4584 | spec->channels = rf_vals_3x; | 4607 | spec->channels = rf_vals_3x; |
4585 | } else if (rt2x00_rf(rt2x00dev, RF3052)) { | 4608 | } else if (rt2x00_rf(rt2x00dev, RF3052)) { |
@@ -4662,9 +4685,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
4662 | case RF3022: | 4685 | case RF3022: |
4663 | case RF3320: | 4686 | case RF3320: |
4664 | case RF3052: | 4687 | case RF3052: |
4688 | case RF5360: | ||
4665 | case RF5370: | 4689 | case RF5370: |
4666 | case RF5372: | 4690 | case RF5372: |
4667 | case RF5390: | 4691 | case RF5390: |
4692 | case RF5392: | ||
4668 | __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); | 4693 | __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); |
4669 | break; | 4694 | break; |
4670 | } | 4695 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index cad25bfebd7a..206158b67426 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1188,6 +1188,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1188 | { PCI_DEVICE(0x1814, 0x3593) }, | 1188 | { PCI_DEVICE(0x1814, 0x3593) }, |
1189 | #endif | 1189 | #endif |
1190 | #ifdef CONFIG_RT2800PCI_RT53XX | 1190 | #ifdef CONFIG_RT2800PCI_RT53XX |
1191 | { PCI_DEVICE(0x1814, 0x5360) }, | ||
1191 | { PCI_DEVICE(0x1814, 0x5362) }, | 1192 | { PCI_DEVICE(0x1814, 0x5362) }, |
1192 | { PCI_DEVICE(0x1814, 0x5390) }, | 1193 | { PCI_DEVICE(0x1814, 0x5390) }, |
1193 | { PCI_DEVICE(0x1814, 0x5392) }, | 1194 | { PCI_DEVICE(0x1814, 0x5392) }, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index bf78317a6adb..20a504072895 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1137,6 +1137,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1137 | #ifdef CONFIG_RT2800USB_RT33XX | 1137 | #ifdef CONFIG_RT2800USB_RT33XX |
1138 | /* Belkin */ | 1138 | /* Belkin */ |
1139 | { USB_DEVICE(0x050d, 0x945b) }, | 1139 | { USB_DEVICE(0x050d, 0x945b) }, |
1140 | /* D-Link */ | ||
1141 | { USB_DEVICE(0x2001, 0x3c17) }, | ||
1140 | /* Panasonic */ | 1142 | /* Panasonic */ |
1141 | { USB_DEVICE(0x083a, 0xb511) }, | 1143 | { USB_DEVICE(0x083a, 0xb511) }, |
1142 | /* Philips */ | 1144 | /* Philips */ |
@@ -1237,7 +1239,6 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1237 | /* D-Link */ | 1239 | /* D-Link */ |
1238 | { USB_DEVICE(0x07d1, 0x3c0b) }, | 1240 | { USB_DEVICE(0x07d1, 0x3c0b) }, |
1239 | { USB_DEVICE(0x07d1, 0x3c17) }, | 1241 | { USB_DEVICE(0x07d1, 0x3c17) }, |
1240 | { USB_DEVICE(0x2001, 0x3c17) }, | ||
1241 | /* Encore */ | 1242 | /* Encore */ |
1242 | { USB_DEVICE(0x203d, 0x14a1) }, | 1243 | { USB_DEVICE(0x203d, 0x14a1) }, |
1243 | /* Gemtek */ | 1244 | /* Gemtek */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e5404e576251..a6b88bd4a1a5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1161,6 +1161,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1161 | BIT(NL80211_IFTYPE_MESH_POINT) | | 1161 | BIT(NL80211_IFTYPE_MESH_POINT) | |
1162 | BIT(NL80211_IFTYPE_WDS); | 1162 | BIT(NL80211_IFTYPE_WDS); |
1163 | 1163 | ||
1164 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
1165 | |||
1164 | /* | 1166 | /* |
1165 | * Initialize work. | 1167 | * Initialize work. |
1166 | */ | 1168 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index dd24b2663b5e..4ff26c2159bf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -506,9 +506,19 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
506 | 506 | ||
507 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 507 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
508 | return 0; | 508 | return 0; |
509 | else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 509 | |
510 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | ||
511 | return -EOPNOTSUPP; | ||
512 | |||
513 | /* | ||
514 | * To support IBSS RSN, don't program group keys in IBSS, the | ||
515 | * hardware will then not attempt to decrypt the frames. | ||
516 | */ | ||
517 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
518 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
510 | return -EOPNOTSUPP; | 519 | return -EOPNOTSUPP; |
511 | else if (key->keylen > 32) | 520 | |
521 | if (key->keylen > 32) | ||
512 | return -ENOSPC; | 522 | return -ENOSPC; |
513 | 523 | ||
514 | memset(&crypto, 0, sizeof(crypto)); | 524 | memset(&crypto, 0, sizeof(crypto)); |
diff --git a/drivers/net/wireless/ti/Kconfig b/drivers/net/wireless/ti/Kconfig index 1a72932e2213..be800119d0a3 100644 --- a/drivers/net/wireless/ti/Kconfig +++ b/drivers/net/wireless/ti/Kconfig | |||
@@ -8,6 +8,7 @@ menuconfig WL_TI | |||
8 | if WL_TI | 8 | if WL_TI |
9 | source "drivers/net/wireless/ti/wl1251/Kconfig" | 9 | source "drivers/net/wireless/ti/wl1251/Kconfig" |
10 | source "drivers/net/wireless/ti/wl12xx/Kconfig" | 10 | source "drivers/net/wireless/ti/wl12xx/Kconfig" |
11 | source "drivers/net/wireless/ti/wl18xx/Kconfig" | ||
11 | 12 | ||
12 | # keep last for automatic dependencies | 13 | # keep last for automatic dependencies |
13 | source "drivers/net/wireless/ti/wlcore/Kconfig" | 14 | source "drivers/net/wireless/ti/wlcore/Kconfig" |
diff --git a/drivers/net/wireless/ti/Makefile b/drivers/net/wireless/ti/Makefile index 0a565622d4a4..4d6823983c04 100644 --- a/drivers/net/wireless/ti/Makefile +++ b/drivers/net/wireless/ti/Makefile | |||
@@ -2,3 +2,4 @@ obj-$(CONFIG_WLCORE) += wlcore/ | |||
2 | obj-$(CONFIG_WL12XX) += wl12xx/ | 2 | obj-$(CONFIG_WL12XX) += wl12xx/ |
3 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/ | 3 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/ |
4 | obj-$(CONFIG_WL1251) += wl1251/ | 4 | obj-$(CONFIG_WL1251) += wl1251/ |
5 | obj-$(CONFIG_WL18XX) += wl18xx/ | ||
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile index 87f64b14db35..da509aa7d009 100644 --- a/drivers/net/wireless/ti/wl12xx/Makefile +++ b/drivers/net/wireless/ti/wl12xx/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | wl12xx-objs = main.o cmd.o acx.o | 1 | wl12xx-objs = main.o cmd.o acx.o debugfs.o |
2 | 2 | ||
3 | obj-$(CONFIG_WL12XX) += wl12xx.o | 3 | obj-$(CONFIG_WL12XX) += wl12xx.o |
diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h index d1f5aba0afce..2a26868b837d 100644 --- a/drivers/net/wireless/ti/wl12xx/acx.h +++ b/drivers/net/wireless/ti/wl12xx/acx.h | |||
@@ -24,6 +24,21 @@ | |||
24 | #define __WL12XX_ACX_H__ | 24 | #define __WL12XX_ACX_H__ |
25 | 25 | ||
26 | #include "../wlcore/wlcore.h" | 26 | #include "../wlcore/wlcore.h" |
27 | #include "../wlcore/acx.h" | ||
28 | |||
29 | #define WL12XX_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ | ||
30 | WL1271_ACX_INTR_INIT_COMPLETE | \ | ||
31 | WL1271_ACX_INTR_EVENT_A | \ | ||
32 | WL1271_ACX_INTR_EVENT_B | \ | ||
33 | WL1271_ACX_INTR_CMD_COMPLETE | \ | ||
34 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
35 | WL1271_ACX_INTR_DATA) | ||
36 | |||
37 | #define WL12XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ | ||
38 | WL1271_ACX_INTR_EVENT_A | \ | ||
39 | WL1271_ACX_INTR_EVENT_B | \ | ||
40 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
41 | WL1271_ACX_INTR_DATA) | ||
27 | 42 | ||
28 | struct wl1271_acx_host_config_bitmap { | 43 | struct wl1271_acx_host_config_bitmap { |
29 | struct acx_header header; | 44 | struct acx_header header; |
@@ -31,6 +46,228 @@ struct wl1271_acx_host_config_bitmap { | |||
31 | __le32 host_cfg_bitmap; | 46 | __le32 host_cfg_bitmap; |
32 | } __packed; | 47 | } __packed; |
33 | 48 | ||
49 | struct wl12xx_acx_tx_statistics { | ||
50 | __le32 internal_desc_overflow; | ||
51 | } __packed; | ||
52 | |||
53 | struct wl12xx_acx_rx_statistics { | ||
54 | __le32 out_of_mem; | ||
55 | __le32 hdr_overflow; | ||
56 | __le32 hw_stuck; | ||
57 | __le32 dropped; | ||
58 | __le32 fcs_err; | ||
59 | __le32 xfr_hint_trig; | ||
60 | __le32 path_reset; | ||
61 | __le32 reset_counter; | ||
62 | } __packed; | ||
63 | |||
64 | struct wl12xx_acx_dma_statistics { | ||
65 | __le32 rx_requested; | ||
66 | __le32 rx_errors; | ||
67 | __le32 tx_requested; | ||
68 | __le32 tx_errors; | ||
69 | } __packed; | ||
70 | |||
71 | struct wl12xx_acx_isr_statistics { | ||
72 | /* host command complete */ | ||
73 | __le32 cmd_cmplt; | ||
74 | |||
75 | /* fiqisr() */ | ||
76 | __le32 fiqs; | ||
77 | |||
78 | /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ | ||
79 | __le32 rx_headers; | ||
80 | |||
81 | /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ | ||
82 | __le32 rx_completes; | ||
83 | |||
84 | /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ | ||
85 | __le32 rx_mem_overflow; | ||
86 | |||
87 | /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ | ||
88 | __le32 rx_rdys; | ||
89 | |||
90 | /* irqisr() */ | ||
91 | __le32 irqs; | ||
92 | |||
93 | /* (INT_STS_ND & INT_TRIG_TX_PROC) */ | ||
94 | __le32 tx_procs; | ||
95 | |||
96 | /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ | ||
97 | __le32 decrypt_done; | ||
98 | |||
99 | /* (INT_STS_ND & INT_TRIG_DMA0) */ | ||
100 | __le32 dma0_done; | ||
101 | |||
102 | /* (INT_STS_ND & INT_TRIG_DMA1) */ | ||
103 | __le32 dma1_done; | ||
104 | |||
105 | /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ | ||
106 | __le32 tx_exch_complete; | ||
107 | |||
108 | /* (INT_STS_ND & INT_TRIG_COMMAND) */ | ||
109 | __le32 commands; | ||
110 | |||
111 | /* (INT_STS_ND & INT_TRIG_RX_PROC) */ | ||
112 | __le32 rx_procs; | ||
113 | |||
114 | /* (INT_STS_ND & INT_TRIG_PM_802) */ | ||
115 | __le32 hw_pm_mode_changes; | ||
116 | |||
117 | /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ | ||
118 | __le32 host_acknowledges; | ||
119 | |||
120 | /* (INT_STS_ND & INT_TRIG_PM_PCI) */ | ||
121 | __le32 pci_pm; | ||
122 | |||
123 | /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ | ||
124 | __le32 wakeups; | ||
125 | |||
126 | /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ | ||
127 | __le32 low_rssi; | ||
128 | } __packed; | ||
129 | |||
130 | struct wl12xx_acx_wep_statistics { | ||
131 | /* WEP address keys configured */ | ||
132 | __le32 addr_key_count; | ||
133 | |||
134 | /* default keys configured */ | ||
135 | __le32 default_key_count; | ||
136 | |||
137 | __le32 reserved; | ||
138 | |||
139 | /* number of times that WEP key not found on lookup */ | ||
140 | __le32 key_not_found; | ||
141 | |||
142 | /* number of times that WEP key decryption failed */ | ||
143 | __le32 decrypt_fail; | ||
144 | |||
145 | /* WEP packets decrypted */ | ||
146 | __le32 packets; | ||
147 | |||
148 | /* WEP decrypt interrupts */ | ||
149 | __le32 interrupt; | ||
150 | } __packed; | ||
151 | |||
152 | #define ACX_MISSED_BEACONS_SPREAD 10 | ||
153 | |||
154 | struct wl12xx_acx_pwr_statistics { | ||
155 | /* the amount of enters into power save mode (both PD & ELP) */ | ||
156 | __le32 ps_enter; | ||
157 | |||
158 | /* the amount of enters into ELP mode */ | ||
159 | __le32 elp_enter; | ||
160 | |||
161 | /* the amount of missing beacon interrupts to the host */ | ||
162 | __le32 missing_bcns; | ||
163 | |||
164 | /* the amount of wake on host-access times */ | ||
165 | __le32 wake_on_host; | ||
166 | |||
167 | /* the amount of wake on timer-expire */ | ||
168 | __le32 wake_on_timer_exp; | ||
169 | |||
170 | /* the number of packets that were transmitted with PS bit set */ | ||
171 | __le32 tx_with_ps; | ||
172 | |||
173 | /* the number of packets that were transmitted with PS bit clear */ | ||
174 | __le32 tx_without_ps; | ||
175 | |||
176 | /* the number of received beacons */ | ||
177 | __le32 rcvd_beacons; | ||
178 | |||
179 | /* the number of entering into PowerOn (power save off) */ | ||
180 | __le32 power_save_off; | ||
181 | |||
182 | /* the number of entries into power save mode */ | ||
183 | __le16 enable_ps; | ||
184 | |||
185 | /* | ||
186 | * the number of exits from power save, not including failed PS | ||
187 | * transitions | ||
188 | */ | ||
189 | __le16 disable_ps; | ||
190 | |||
191 | /* | ||
192 | * the number of times the TSF counter was adjusted because | ||
193 | * of drift | ||
194 | */ | ||
195 | __le32 fix_tsf_ps; | ||
196 | |||
197 | /* Gives statistics about the spread continuous missed beacons. | ||
198 | * The 16 LSB are dedicated for the PS mode. | ||
199 | * The 16 MSB are dedicated for the PS mode. | ||
200 | * cont_miss_bcns_spread[0] - single missed beacon. | ||
201 | * cont_miss_bcns_spread[1] - two continuous missed beacons. | ||
202 | * cont_miss_bcns_spread[2] - three continuous missed beacons. | ||
203 | * ... | ||
204 | * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. | ||
205 | */ | ||
206 | __le32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; | ||
207 | |||
208 | /* the number of beacons in awake mode */ | ||
209 | __le32 rcvd_awake_beacons; | ||
210 | } __packed; | ||
211 | |||
212 | struct wl12xx_acx_mic_statistics { | ||
213 | __le32 rx_pkts; | ||
214 | __le32 calc_failure; | ||
215 | } __packed; | ||
216 | |||
217 | struct wl12xx_acx_aes_statistics { | ||
218 | __le32 encrypt_fail; | ||
219 | __le32 decrypt_fail; | ||
220 | __le32 encrypt_packets; | ||
221 | __le32 decrypt_packets; | ||
222 | __le32 encrypt_interrupt; | ||
223 | __le32 decrypt_interrupt; | ||
224 | } __packed; | ||
225 | |||
226 | struct wl12xx_acx_event_statistics { | ||
227 | __le32 heart_beat; | ||
228 | __le32 calibration; | ||
229 | __le32 rx_mismatch; | ||
230 | __le32 rx_mem_empty; | ||
231 | __le32 rx_pool; | ||
232 | __le32 oom_late; | ||
233 | __le32 phy_transmit_error; | ||
234 | __le32 tx_stuck; | ||
235 | } __packed; | ||
236 | |||
237 | struct wl12xx_acx_ps_statistics { | ||
238 | __le32 pspoll_timeouts; | ||
239 | __le32 upsd_timeouts; | ||
240 | __le32 upsd_max_sptime; | ||
241 | __le32 upsd_max_apturn; | ||
242 | __le32 pspoll_max_apturn; | ||
243 | __le32 pspoll_utilization; | ||
244 | __le32 upsd_utilization; | ||
245 | } __packed; | ||
246 | |||
247 | struct wl12xx_acx_rxpipe_statistics { | ||
248 | __le32 rx_prep_beacon_drop; | ||
249 | __le32 descr_host_int_trig_rx_data; | ||
250 | __le32 beacon_buffer_thres_host_int_trig_rx_data; | ||
251 | __le32 missed_beacon_host_int_trig_rx_data; | ||
252 | __le32 tx_xfr_host_int_trig_rx_data; | ||
253 | } __packed; | ||
254 | |||
255 | struct wl12xx_acx_statistics { | ||
256 | struct acx_header header; | ||
257 | |||
258 | struct wl12xx_acx_tx_statistics tx; | ||
259 | struct wl12xx_acx_rx_statistics rx; | ||
260 | struct wl12xx_acx_dma_statistics dma; | ||
261 | struct wl12xx_acx_isr_statistics isr; | ||
262 | struct wl12xx_acx_wep_statistics wep; | ||
263 | struct wl12xx_acx_pwr_statistics pwr; | ||
264 | struct wl12xx_acx_aes_statistics aes; | ||
265 | struct wl12xx_acx_mic_statistics mic; | ||
266 | struct wl12xx_acx_event_statistics event; | ||
267 | struct wl12xx_acx_ps_statistics ps; | ||
268 | struct wl12xx_acx_rxpipe_statistics rxpipe; | ||
269 | } __packed; | ||
270 | |||
34 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); | 271 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); |
35 | 272 | ||
36 | #endif /* __WL12XX_ACX_H__ */ | 273 | #endif /* __WL12XX_ACX_H__ */ |
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c index 8ffaeb5f2147..50ba7480b790 100644 --- a/drivers/net/wireless/ti/wl12xx/cmd.c +++ b/drivers/net/wireless/ti/wl12xx/cmd.c | |||
@@ -65,6 +65,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
65 | struct wl1271_general_parms_cmd *gen_parms; | 65 | struct wl1271_general_parms_cmd *gen_parms; |
66 | struct wl1271_ini_general_params *gp = | 66 | struct wl1271_ini_general_params *gp = |
67 | &((struct wl1271_nvs_file *)wl->nvs)->general_params; | 67 | &((struct wl1271_nvs_file *)wl->nvs)->general_params; |
68 | struct wl12xx_priv *priv = wl->priv; | ||
68 | bool answer = false; | 69 | bool answer = false; |
69 | int ret; | 70 | int ret; |
70 | 71 | ||
@@ -88,7 +89,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
88 | answer = true; | 89 | answer = true; |
89 | 90 | ||
90 | /* Override the REF CLK from the NVS with the one from platform data */ | 91 | /* Override the REF CLK from the NVS with the one from platform data */ |
91 | gen_parms->general_params.ref_clock = wl->ref_clock; | 92 | gen_parms->general_params.ref_clock = priv->ref_clock; |
92 | 93 | ||
93 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 94 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
94 | if (ret < 0) { | 95 | if (ret < 0) { |
@@ -118,6 +119,7 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) | |||
118 | struct wl128x_general_parms_cmd *gen_parms; | 119 | struct wl128x_general_parms_cmd *gen_parms; |
119 | struct wl128x_ini_general_params *gp = | 120 | struct wl128x_ini_general_params *gp = |
120 | &((struct wl128x_nvs_file *)wl->nvs)->general_params; | 121 | &((struct wl128x_nvs_file *)wl->nvs)->general_params; |
122 | struct wl12xx_priv *priv = wl->priv; | ||
121 | bool answer = false; | 123 | bool answer = false; |
122 | int ret; | 124 | int ret; |
123 | 125 | ||
@@ -141,8 +143,8 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) | |||
141 | answer = true; | 143 | answer = true; |
142 | 144 | ||
143 | /* Replace REF and TCXO CLKs with the ones from platform data */ | 145 | /* Replace REF and TCXO CLKs with the ones from platform data */ |
144 | gen_parms->general_params.ref_clock = wl->ref_clock; | 146 | gen_parms->general_params.ref_clock = priv->ref_clock; |
145 | gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; | 147 | gen_parms->general_params.tcxo_ref_clock = priv->tcxo_clock; |
146 | 148 | ||
147 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 149 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
148 | if (ret < 0) { | 150 | if (ret < 0) { |
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c new file mode 100644 index 000000000000..0521cbf858cf --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/debugfs.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * Copyright (C) 2011-2012 Texas Instruments | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include "../wlcore/debugfs.h" | ||
24 | #include "../wlcore/wlcore.h" | ||
25 | |||
26 | #include "wl12xx.h" | ||
27 | #include "acx.h" | ||
28 | #include "debugfs.h" | ||
29 | |||
30 | #define WL12XX_DEBUGFS_FWSTATS_FILE(a, b, c) \ | ||
31 | DEBUGFS_FWSTATS_FILE(a, b, c, wl12xx_acx_statistics) | ||
32 | |||
33 | WL12XX_DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); | ||
34 | |||
35 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); | ||
36 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); | ||
37 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); | ||
38 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); | ||
39 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); | ||
40 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); | ||
41 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); | ||
42 | WL12XX_DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); | ||
43 | |||
44 | WL12XX_DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); | ||
45 | WL12XX_DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); | ||
46 | WL12XX_DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); | ||
47 | WL12XX_DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); | ||
48 | |||
49 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); | ||
50 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); | ||
51 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); | ||
52 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); | ||
53 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); | ||
54 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); | ||
55 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); | ||
56 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); | ||
57 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); | ||
58 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); | ||
59 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); | ||
60 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); | ||
61 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); | ||
62 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); | ||
63 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); | ||
64 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); | ||
65 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); | ||
66 | WL12XX_DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); | ||
67 | |||
68 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); | ||
69 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); | ||
70 | /* skipping wep.reserved */ | ||
71 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); | ||
72 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); | ||
73 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); | ||
74 | WL12XX_DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); | ||
75 | |||
76 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); | ||
77 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); | ||
78 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); | ||
79 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); | ||
80 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); | ||
81 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); | ||
82 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); | ||
83 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); | ||
84 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); | ||
85 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); | ||
86 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); | ||
87 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); | ||
88 | /* skipping cont_miss_bcns_spread for now */ | ||
89 | WL12XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); | ||
90 | |||
91 | WL12XX_DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); | ||
92 | WL12XX_DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); | ||
93 | |||
94 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); | ||
95 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); | ||
96 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); | ||
97 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); | ||
98 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); | ||
99 | WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); | ||
100 | |||
101 | WL12XX_DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); | ||
102 | WL12XX_DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); | ||
103 | WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); | ||
104 | WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); | ||
105 | WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); | ||
106 | WL12XX_DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); | ||
107 | WL12XX_DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); | ||
108 | WL12XX_DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); | ||
109 | |||
110 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); | ||
111 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); | ||
112 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); | ||
113 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); | ||
114 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); | ||
115 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); | ||
116 | WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); | ||
117 | |||
118 | WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); | ||
119 | WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); | ||
120 | WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, | ||
121 | "%u"); | ||
122 | WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); | ||
123 | WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); | ||
124 | |||
125 | int wl12xx_debugfs_add_files(struct wl1271 *wl, | ||
126 | struct dentry *rootdir) | ||
127 | { | ||
128 | int ret = 0; | ||
129 | struct dentry *entry, *stats, *moddir; | ||
130 | |||
131 | moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); | ||
132 | if (!moddir || IS_ERR(moddir)) { | ||
133 | entry = moddir; | ||
134 | goto err; | ||
135 | } | ||
136 | |||
137 | stats = debugfs_create_dir("fw_stats", moddir); | ||
138 | if (!stats || IS_ERR(stats)) { | ||
139 | entry = stats; | ||
140 | goto err; | ||
141 | } | ||
142 | |||
143 | DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); | ||
144 | |||
145 | DEBUGFS_FWSTATS_ADD(rx, out_of_mem); | ||
146 | DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); | ||
147 | DEBUGFS_FWSTATS_ADD(rx, hw_stuck); | ||
148 | DEBUGFS_FWSTATS_ADD(rx, dropped); | ||
149 | DEBUGFS_FWSTATS_ADD(rx, fcs_err); | ||
150 | DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); | ||
151 | DEBUGFS_FWSTATS_ADD(rx, path_reset); | ||
152 | DEBUGFS_FWSTATS_ADD(rx, reset_counter); | ||
153 | |||
154 | DEBUGFS_FWSTATS_ADD(dma, rx_requested); | ||
155 | DEBUGFS_FWSTATS_ADD(dma, rx_errors); | ||
156 | DEBUGFS_FWSTATS_ADD(dma, tx_requested); | ||
157 | DEBUGFS_FWSTATS_ADD(dma, tx_errors); | ||
158 | |||
159 | DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); | ||
160 | DEBUGFS_FWSTATS_ADD(isr, fiqs); | ||
161 | DEBUGFS_FWSTATS_ADD(isr, rx_headers); | ||
162 | DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); | ||
163 | DEBUGFS_FWSTATS_ADD(isr, rx_rdys); | ||
164 | DEBUGFS_FWSTATS_ADD(isr, irqs); | ||
165 | DEBUGFS_FWSTATS_ADD(isr, tx_procs); | ||
166 | DEBUGFS_FWSTATS_ADD(isr, decrypt_done); | ||
167 | DEBUGFS_FWSTATS_ADD(isr, dma0_done); | ||
168 | DEBUGFS_FWSTATS_ADD(isr, dma1_done); | ||
169 | DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); | ||
170 | DEBUGFS_FWSTATS_ADD(isr, commands); | ||
171 | DEBUGFS_FWSTATS_ADD(isr, rx_procs); | ||
172 | DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); | ||
173 | DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); | ||
174 | DEBUGFS_FWSTATS_ADD(isr, pci_pm); | ||
175 | DEBUGFS_FWSTATS_ADD(isr, wakeups); | ||
176 | DEBUGFS_FWSTATS_ADD(isr, low_rssi); | ||
177 | |||
178 | DEBUGFS_FWSTATS_ADD(wep, addr_key_count); | ||
179 | DEBUGFS_FWSTATS_ADD(wep, default_key_count); | ||
180 | /* skipping wep.reserved */ | ||
181 | DEBUGFS_FWSTATS_ADD(wep, key_not_found); | ||
182 | DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); | ||
183 | DEBUGFS_FWSTATS_ADD(wep, packets); | ||
184 | DEBUGFS_FWSTATS_ADD(wep, interrupt); | ||
185 | |||
186 | DEBUGFS_FWSTATS_ADD(pwr, ps_enter); | ||
187 | DEBUGFS_FWSTATS_ADD(pwr, elp_enter); | ||
188 | DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); | ||
189 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); | ||
190 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); | ||
191 | DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); | ||
192 | DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); | ||
193 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); | ||
194 | DEBUGFS_FWSTATS_ADD(pwr, power_save_off); | ||
195 | DEBUGFS_FWSTATS_ADD(pwr, enable_ps); | ||
196 | DEBUGFS_FWSTATS_ADD(pwr, disable_ps); | ||
197 | DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); | ||
198 | /* skipping cont_miss_bcns_spread for now */ | ||
199 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); | ||
200 | |||
201 | DEBUGFS_FWSTATS_ADD(mic, rx_pkts); | ||
202 | DEBUGFS_FWSTATS_ADD(mic, calc_failure); | ||
203 | |||
204 | DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); | ||
205 | DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); | ||
206 | DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); | ||
207 | DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); | ||
208 | DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); | ||
209 | DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); | ||
210 | |||
211 | DEBUGFS_FWSTATS_ADD(event, heart_beat); | ||
212 | DEBUGFS_FWSTATS_ADD(event, calibration); | ||
213 | DEBUGFS_FWSTATS_ADD(event, rx_mismatch); | ||
214 | DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); | ||
215 | DEBUGFS_FWSTATS_ADD(event, rx_pool); | ||
216 | DEBUGFS_FWSTATS_ADD(event, oom_late); | ||
217 | DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); | ||
218 | DEBUGFS_FWSTATS_ADD(event, tx_stuck); | ||
219 | |||
220 | DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); | ||
221 | DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); | ||
222 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); | ||
223 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); | ||
224 | DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); | ||
225 | DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); | ||
226 | DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); | ||
227 | |||
228 | DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); | ||
229 | DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); | ||
230 | DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); | ||
231 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); | ||
232 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | ||
233 | |||
234 | return 0; | ||
235 | |||
236 | err: | ||
237 | if (IS_ERR(entry)) | ||
238 | ret = PTR_ERR(entry); | ||
239 | else | ||
240 | ret = -ENOMEM; | ||
241 | |||
242 | return ret; | ||
243 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.h b/drivers/net/wireless/ti/wl12xx/debugfs.h new file mode 100644 index 000000000000..96898e291b78 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/debugfs.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL12XX_DEBUGFS_H__ | ||
23 | #define __WL12XX_DEBUGFS_H__ | ||
24 | |||
25 | int wl12xx_debugfs_add_files(struct wl1271 *wl, | ||
26 | struct dentry *rootdir); | ||
27 | |||
28 | #endif /* __WL12XX_DEBUGFS_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index d7dd3def07b5..85d1600ee340 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -39,6 +39,10 @@ | |||
39 | #include "reg.h" | 39 | #include "reg.h" |
40 | #include "cmd.h" | 40 | #include "cmd.h" |
41 | #include "acx.h" | 41 | #include "acx.h" |
42 | #include "debugfs.h" | ||
43 | |||
44 | static char *fref_param; | ||
45 | static char *tcxo_param; | ||
42 | 46 | ||
43 | static struct wlcore_conf wl12xx_conf = { | 47 | static struct wlcore_conf wl12xx_conf = { |
44 | .sg = { | 48 | .sg = { |
@@ -212,7 +216,7 @@ static struct wlcore_conf wl12xx_conf = { | |||
212 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, | 216 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, |
213 | .suspend_listen_interval = 3, | 217 | .suspend_listen_interval = 3, |
214 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 218 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
215 | .bcn_filt_ie_count = 2, | 219 | .bcn_filt_ie_count = 3, |
216 | .bcn_filt_ie = { | 220 | .bcn_filt_ie = { |
217 | [0] = { | 221 | [0] = { |
218 | .ie = WLAN_EID_CHANNEL_SWITCH, | 222 | .ie = WLAN_EID_CHANNEL_SWITCH, |
@@ -222,9 +226,13 @@ static struct wlcore_conf wl12xx_conf = { | |||
222 | .ie = WLAN_EID_HT_OPERATION, | 226 | .ie = WLAN_EID_HT_OPERATION, |
223 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | 227 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, |
224 | }, | 228 | }, |
229 | [2] = { | ||
230 | .ie = WLAN_EID_ERP_INFO, | ||
231 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
232 | }, | ||
225 | }, | 233 | }, |
226 | .synch_fail_thold = 10, | 234 | .synch_fail_thold = 12, |
227 | .bss_lose_timeout = 100, | 235 | .bss_lose_timeout = 400, |
228 | .beacon_rx_timeout = 10000, | 236 | .beacon_rx_timeout = 10000, |
229 | .broadcast_timeout = 20000, | 237 | .broadcast_timeout = 20000, |
230 | .rx_broadcast_in_ps = 1, | 238 | .rx_broadcast_in_ps = 1, |
@@ -234,7 +242,7 @@ static struct wlcore_conf wl12xx_conf = { | |||
234 | .psm_entry_retries = 8, | 242 | .psm_entry_retries = 8, |
235 | .psm_exit_retries = 16, | 243 | .psm_exit_retries = 16, |
236 | .psm_entry_nullfunc_retries = 3, | 244 | .psm_entry_nullfunc_retries = 3, |
237 | .dynamic_ps_timeout = 40, | 245 | .dynamic_ps_timeout = 200, |
238 | .forced_ps = false, | 246 | .forced_ps = false, |
239 | .keep_alive_interval = 55000, | 247 | .keep_alive_interval = 55000, |
240 | .max_listen_interval = 20, | 248 | .max_listen_interval = 20, |
@@ -245,7 +253,7 @@ static struct wlcore_conf wl12xx_conf = { | |||
245 | }, | 253 | }, |
246 | .pm_config = { | 254 | .pm_config = { |
247 | .host_clk_settling_time = 5000, | 255 | .host_clk_settling_time = 5000, |
248 | .host_fast_wakeup_support = false | 256 | .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE, |
249 | }, | 257 | }, |
250 | .roam_trigger = { | 258 | .roam_trigger = { |
251 | .trigger_pacing = 1, | 259 | .trigger_pacing = 1, |
@@ -305,8 +313,8 @@ static struct wlcore_conf wl12xx_conf = { | |||
305 | .swallow_period = 5, | 313 | .swallow_period = 5, |
306 | .n_divider_fref_set_1 = 0xff, /* default */ | 314 | .n_divider_fref_set_1 = 0xff, /* default */ |
307 | .n_divider_fref_set_2 = 12, | 315 | .n_divider_fref_set_2 = 12, |
308 | .m_divider_fref_set_1 = 148, | 316 | .m_divider_fref_set_1 = 0xffff, |
309 | .m_divider_fref_set_2 = 0xffff, /* default */ | 317 | .m_divider_fref_set_2 = 148, /* default */ |
310 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | 318 | .coex_pll_stabilization_time = 0xffffffff, /* default */ |
311 | .ldo_stabilization_time = 0xffff, /* default */ | 319 | .ldo_stabilization_time = 0xffff, /* default */ |
312 | .fm_disturbed_band_margin = 0xff, /* default */ | 320 | .fm_disturbed_band_margin = 0xff, /* default */ |
@@ -593,7 +601,7 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
593 | { | 601 | { |
594 | if (wl->chip.id != CHIP_ID_1283_PG20) { | 602 | if (wl->chip.id != CHIP_ID_1283_PG20) { |
595 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 603 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
596 | struct wl1271_rx_mem_pool_addr rx_mem_addr; | 604 | struct wl127x_rx_mem_pool_addr rx_mem_addr; |
597 | 605 | ||
598 | /* | 606 | /* |
599 | * Choose the block we want to read | 607 | * Choose the block we want to read |
@@ -621,10 +629,8 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
621 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", | 629 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", |
622 | wl->chip.id); | 630 | wl->chip.id); |
623 | 631 | ||
624 | /* clear the alignment quirk, since we don't support it */ | 632 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
625 | wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | 633 | WLCORE_QUIRK_TKIP_HEADER_SPACE; |
626 | |||
627 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; | ||
628 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | 634 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
629 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | 635 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
630 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, | 636 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, |
@@ -639,10 +645,8 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
639 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 645 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
640 | wl->chip.id); | 646 | wl->chip.id); |
641 | 647 | ||
642 | /* clear the alignment quirk, since we don't support it */ | 648 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | |
643 | wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | 649 | WLCORE_QUIRK_TKIP_HEADER_SPACE; |
644 | |||
645 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; | ||
646 | wl->plt_fw_name = WL127X_PLT_FW_NAME; | 650 | wl->plt_fw_name = WL127X_PLT_FW_NAME; |
647 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | 651 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; |
648 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | 652 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; |
@@ -660,6 +664,11 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
660 | wl->plt_fw_name = WL128X_PLT_FW_NAME; | 664 | wl->plt_fw_name = WL128X_PLT_FW_NAME; |
661 | wl->sr_fw_name = WL128X_FW_NAME_SINGLE; | 665 | wl->sr_fw_name = WL128X_FW_NAME_SINGLE; |
662 | wl->mr_fw_name = WL128X_FW_NAME_MULTI; | 666 | wl->mr_fw_name = WL128X_FW_NAME_MULTI; |
667 | |||
668 | /* wl128x requires TX blocksize alignment */ | ||
669 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | ||
670 | WLCORE_QUIRK_TKIP_HEADER_SPACE; | ||
671 | |||
663 | break; | 672 | break; |
664 | case CHIP_ID_1283_PG10: | 673 | case CHIP_ID_1283_PG10: |
665 | default: | 674 | default: |
@@ -773,6 +782,7 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
773 | u16 spare_reg; | 782 | u16 spare_reg; |
774 | u16 pll_config; | 783 | u16 pll_config; |
775 | u8 input_freq; | 784 | u8 input_freq; |
785 | struct wl12xx_priv *priv = wl->priv; | ||
776 | 786 | ||
777 | /* Mask bits [3:1] in the sys_clk_cfg register */ | 787 | /* Mask bits [3:1] in the sys_clk_cfg register */ |
778 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 788 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); |
@@ -782,8 +792,8 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
782 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 792 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
783 | 793 | ||
784 | /* Handle special cases of the TCXO clock */ | 794 | /* Handle special cases of the TCXO clock */ |
785 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | 795 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || |
786 | wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) | 796 | priv->tcxo_clock == WL12XX_TCXOCLOCK_33_6) |
787 | return wl128x_manually_configure_mcs_pll(wl); | 797 | return wl128x_manually_configure_mcs_pll(wl); |
788 | 798 | ||
789 | /* Set the input frequency according to the selected clock source */ | 799 | /* Set the input frequency according to the selected clock source */ |
@@ -808,11 +818,12 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
808 | */ | 818 | */ |
809 | static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | 819 | static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) |
810 | { | 820 | { |
821 | struct wl12xx_priv *priv = wl->priv; | ||
811 | u16 sys_clk_cfg; | 822 | u16 sys_clk_cfg; |
812 | 823 | ||
813 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | 824 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ |
814 | if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || | 825 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || |
815 | wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { | 826 | priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) { |
816 | if (!wl128x_switch_tcxo_to_fref(wl)) | 827 | if (!wl128x_switch_tcxo_to_fref(wl)) |
817 | return -EINVAL; | 828 | return -EINVAL; |
818 | goto fref_clk; | 829 | goto fref_clk; |
@@ -826,8 +837,8 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
826 | goto fref_clk; | 837 | goto fref_clk; |
827 | 838 | ||
828 | /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ | 839 | /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ |
829 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || | 840 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || |
830 | wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { | 841 | priv->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { |
831 | if (!wl128x_switch_tcxo_to_fref(wl)) | 842 | if (!wl128x_switch_tcxo_to_fref(wl)) |
832 | return -EINVAL; | 843 | return -EINVAL; |
833 | goto fref_clk; | 844 | goto fref_clk; |
@@ -836,14 +847,14 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
836 | /* TCXO clock is selected */ | 847 | /* TCXO clock is selected */ |
837 | if (!wl128x_is_tcxo_valid(wl)) | 848 | if (!wl128x_is_tcxo_valid(wl)) |
838 | return -EINVAL; | 849 | return -EINVAL; |
839 | *selected_clock = wl->tcxo_clock; | 850 | *selected_clock = priv->tcxo_clock; |
840 | goto config_mcs_pll; | 851 | goto config_mcs_pll; |
841 | 852 | ||
842 | fref_clk: | 853 | fref_clk: |
843 | /* FREF clock is selected */ | 854 | /* FREF clock is selected */ |
844 | if (!wl128x_is_fref_valid(wl)) | 855 | if (!wl128x_is_fref_valid(wl)) |
845 | return -EINVAL; | 856 | return -EINVAL; |
846 | *selected_clock = wl->ref_clock; | 857 | *selected_clock = priv->ref_clock; |
847 | 858 | ||
848 | config_mcs_pll: | 859 | config_mcs_pll: |
849 | return wl128x_configure_mcs_pll(wl, *selected_clock); | 860 | return wl128x_configure_mcs_pll(wl, *selected_clock); |
@@ -851,25 +862,27 @@ config_mcs_pll: | |||
851 | 862 | ||
852 | static int wl127x_boot_clk(struct wl1271 *wl) | 863 | static int wl127x_boot_clk(struct wl1271 *wl) |
853 | { | 864 | { |
865 | struct wl12xx_priv *priv = wl->priv; | ||
854 | u32 pause; | 866 | u32 pause; |
855 | u32 clk; | 867 | u32 clk; |
856 | 868 | ||
857 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | 869 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
858 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; | 870 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; |
859 | 871 | ||
860 | if (wl->ref_clock == CONF_REF_CLK_19_2_E || | 872 | if (priv->ref_clock == CONF_REF_CLK_19_2_E || |
861 | wl->ref_clock == CONF_REF_CLK_38_4_E || | 873 | priv->ref_clock == CONF_REF_CLK_38_4_E || |
862 | wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) | 874 | priv->ref_clock == CONF_REF_CLK_38_4_M_XTAL) |
863 | /* ref clk: 19.2/38.4/38.4-XTAL */ | 875 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
864 | clk = 0x3; | 876 | clk = 0x3; |
865 | else if (wl->ref_clock == CONF_REF_CLK_26_E || | 877 | else if (priv->ref_clock == CONF_REF_CLK_26_E || |
866 | wl->ref_clock == CONF_REF_CLK_52_E) | 878 | priv->ref_clock == CONF_REF_CLK_26_M_XTAL || |
879 | priv->ref_clock == CONF_REF_CLK_52_E) | ||
867 | /* ref clk: 26/52 */ | 880 | /* ref clk: 26/52 */ |
868 | clk = 0x5; | 881 | clk = 0x5; |
869 | else | 882 | else |
870 | return -EINVAL; | 883 | return -EINVAL; |
871 | 884 | ||
872 | if (wl->ref_clock != CONF_REF_CLK_19_2_E) { | 885 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { |
873 | u16 val; | 886 | u16 val; |
874 | /* Set clock type (open drain) */ | 887 | /* Set clock type (open drain) */ |
875 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); | 888 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); |
@@ -939,6 +952,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
939 | 952 | ||
940 | static int wl12xx_pre_boot(struct wl1271 *wl) | 953 | static int wl12xx_pre_boot(struct wl1271 *wl) |
941 | { | 954 | { |
955 | struct wl12xx_priv *priv = wl->priv; | ||
942 | int ret = 0; | 956 | int ret = 0; |
943 | u32 clk; | 957 | u32 clk; |
944 | int selected_clock = -1; | 958 | int selected_clock = -1; |
@@ -970,7 +984,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
970 | if (wl->chip.id == CHIP_ID_1283_PG20) | 984 | if (wl->chip.id == CHIP_ID_1283_PG20) |
971 | clk |= ((selected_clock & 0x3) << 1) << 4; | 985 | clk |= ((selected_clock & 0x3) << 1) << 4; |
972 | else | 986 | else |
973 | clk |= (wl->ref_clock << 1) << 4; | 987 | clk |= (priv->ref_clock << 1) << 4; |
974 | 988 | ||
975 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); | 989 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); |
976 | 990 | ||
@@ -989,7 +1003,7 @@ out: | |||
989 | 1003 | ||
990 | static void wl12xx_pre_upload(struct wl1271 *wl) | 1004 | static void wl12xx_pre_upload(struct wl1271 *wl) |
991 | { | 1005 | { |
992 | u32 tmp; | 1006 | u32 tmp, polarity; |
993 | 1007 | ||
994 | /* write firmware's last address (ie. it's length) to | 1008 | /* write firmware's last address (ie. it's length) to |
995 | * ACX_EEPROMLESS_IND_REG */ | 1009 | * ACX_EEPROMLESS_IND_REG */ |
@@ -1009,23 +1023,23 @@ static void wl12xx_pre_upload(struct wl1271 *wl) | |||
1009 | 1023 | ||
1010 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1024 | if (wl->chip.id == CHIP_ID_1283_PG20) |
1011 | wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); | 1025 | wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); |
1012 | } | ||
1013 | |||
1014 | static void wl12xx_enable_interrupts(struct wl1271 *wl) | ||
1015 | { | ||
1016 | u32 polarity; | ||
1017 | 1026 | ||
1027 | /* polarity must be set before the firmware is loaded */ | ||
1018 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); | 1028 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); |
1019 | 1029 | ||
1020 | /* We use HIGH polarity, so unset the LOW bit */ | 1030 | /* We use HIGH polarity, so unset the LOW bit */ |
1021 | polarity &= ~POLARITY_LOW; | 1031 | polarity &= ~POLARITY_LOW; |
1022 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); | 1032 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); |
1023 | 1033 | ||
1024 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR); | 1034 | } |
1035 | |||
1036 | static void wl12xx_enable_interrupts(struct wl1271 *wl) | ||
1037 | { | ||
1038 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR); | ||
1025 | 1039 | ||
1026 | wlcore_enable_interrupts(wl); | 1040 | wlcore_enable_interrupts(wl); |
1027 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 1041 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
1028 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 1042 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); |
1029 | 1043 | ||
1030 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); | 1044 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); |
1031 | } | 1045 | } |
@@ -1149,7 +1163,8 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | |||
1149 | 1163 | ||
1150 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) | 1164 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) |
1151 | { | 1165 | { |
1152 | if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff)) | 1166 | if (wl->fw_status_1->tx_results_counter == |
1167 | (wl->tx_results_count & 0xff)) | ||
1153 | return; | 1168 | return; |
1154 | 1169 | ||
1155 | wl1271_tx_complete(wl); | 1170 | wl1271_tx_complete(wl); |
@@ -1288,10 +1303,90 @@ static void wl12xx_get_mac(struct wl1271 *wl) | |||
1288 | wl12xx_get_fuse_mac(wl); | 1303 | wl12xx_get_fuse_mac(wl); |
1289 | } | 1304 | } |
1290 | 1305 | ||
1306 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, | ||
1307 | struct wl1271_tx_hw_descr *desc, | ||
1308 | struct sk_buff *skb) | ||
1309 | { | ||
1310 | desc->wl12xx_reserved = 0; | ||
1311 | } | ||
1312 | |||
1313 | static int wl12xx_plt_init(struct wl1271 *wl) | ||
1314 | { | ||
1315 | int ret; | ||
1316 | |||
1317 | ret = wl->ops->boot(wl); | ||
1318 | if (ret < 0) | ||
1319 | goto out; | ||
1320 | |||
1321 | ret = wl->ops->hw_init(wl); | ||
1322 | if (ret < 0) | ||
1323 | goto out_irq_disable; | ||
1324 | |||
1325 | ret = wl1271_acx_init_mem_config(wl); | ||
1326 | if (ret < 0) | ||
1327 | goto out_irq_disable; | ||
1328 | |||
1329 | ret = wl12xx_acx_mem_cfg(wl); | ||
1330 | if (ret < 0) | ||
1331 | goto out_free_memmap; | ||
1332 | |||
1333 | /* Enable data path */ | ||
1334 | ret = wl1271_cmd_data_path(wl, 1); | ||
1335 | if (ret < 0) | ||
1336 | goto out_free_memmap; | ||
1337 | |||
1338 | /* Configure for CAM power saving (ie. always active) */ | ||
1339 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
1340 | if (ret < 0) | ||
1341 | goto out_free_memmap; | ||
1342 | |||
1343 | /* configure PM */ | ||
1344 | ret = wl1271_acx_pm_config(wl); | ||
1345 | if (ret < 0) | ||
1346 | goto out_free_memmap; | ||
1347 | |||
1348 | goto out; | ||
1349 | |||
1350 | out_free_memmap: | ||
1351 | kfree(wl->target_mem_map); | ||
1352 | wl->target_mem_map = NULL; | ||
1353 | |||
1354 | out_irq_disable: | ||
1355 | mutex_unlock(&wl->mutex); | ||
1356 | /* Unlocking the mutex in the middle of handling is | ||
1357 | inherently unsafe. In this case we deem it safe to do, | ||
1358 | because we need to let any possibly pending IRQ out of | ||
1359 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
1360 | work function will not do anything.) Also, any other | ||
1361 | possible concurrent operations will fail due to the | ||
1362 | current state, hence the wl1271 struct should be safe. */ | ||
1363 | wlcore_disable_interrupts(wl); | ||
1364 | mutex_lock(&wl->mutex); | ||
1365 | out: | ||
1366 | return ret; | ||
1367 | } | ||
1368 | |||
1369 | static int wl12xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) | ||
1370 | { | ||
1371 | if (is_gem) | ||
1372 | return WL12XX_TX_HW_BLOCK_GEM_SPARE; | ||
1373 | |||
1374 | return WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; | ||
1375 | } | ||
1376 | |||
1377 | static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | ||
1378 | struct ieee80211_vif *vif, | ||
1379 | struct ieee80211_sta *sta, | ||
1380 | struct ieee80211_key_conf *key_conf) | ||
1381 | { | ||
1382 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1383 | } | ||
1384 | |||
1291 | static struct wlcore_ops wl12xx_ops = { | 1385 | static struct wlcore_ops wl12xx_ops = { |
1292 | .identify_chip = wl12xx_identify_chip, | 1386 | .identify_chip = wl12xx_identify_chip, |
1293 | .identify_fw = wl12xx_identify_fw, | 1387 | .identify_fw = wl12xx_identify_fw, |
1294 | .boot = wl12xx_boot, | 1388 | .boot = wl12xx_boot, |
1389 | .plt_init = wl12xx_plt_init, | ||
1295 | .trigger_cmd = wl12xx_trigger_cmd, | 1390 | .trigger_cmd = wl12xx_trigger_cmd, |
1296 | .ack_event = wl12xx_ack_event, | 1391 | .ack_event = wl12xx_ack_event, |
1297 | .calc_tx_blocks = wl12xx_calc_tx_blocks, | 1392 | .calc_tx_blocks = wl12xx_calc_tx_blocks, |
@@ -1306,6 +1401,13 @@ static struct wlcore_ops wl12xx_ops = { | |||
1306 | .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, | 1401 | .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, |
1307 | .get_pg_ver = wl12xx_get_pg_ver, | 1402 | .get_pg_ver = wl12xx_get_pg_ver, |
1308 | .get_mac = wl12xx_get_mac, | 1403 | .get_mac = wl12xx_get_mac, |
1404 | .set_tx_desc_csum = wl12xx_set_tx_desc_csum, | ||
1405 | .set_rx_csum = NULL, | ||
1406 | .ap_get_mimo_wide_rate_mask = NULL, | ||
1407 | .debugfs_init = wl12xx_debugfs_add_files, | ||
1408 | .get_spare_blocks = wl12xx_get_spare_blocks, | ||
1409 | .set_key = wl12xx_set_key, | ||
1410 | .pre_pkt_send = NULL, | ||
1309 | }; | 1411 | }; |
1310 | 1412 | ||
1311 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { | 1413 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { |
@@ -1323,6 +1425,7 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { | |||
1323 | 1425 | ||
1324 | static int __devinit wl12xx_probe(struct platform_device *pdev) | 1426 | static int __devinit wl12xx_probe(struct platform_device *pdev) |
1325 | { | 1427 | { |
1428 | struct wl12xx_platform_data *pdata = pdev->dev.platform_data; | ||
1326 | struct wl1271 *wl; | 1429 | struct wl1271 *wl; |
1327 | struct ieee80211_hw *hw; | 1430 | struct ieee80211_hw *hw; |
1328 | struct wl12xx_priv *priv; | 1431 | struct wl12xx_priv *priv; |
@@ -1334,19 +1437,65 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) | |||
1334 | } | 1437 | } |
1335 | 1438 | ||
1336 | wl = hw->priv; | 1439 | wl = hw->priv; |
1440 | priv = wl->priv; | ||
1337 | wl->ops = &wl12xx_ops; | 1441 | wl->ops = &wl12xx_ops; |
1338 | wl->ptable = wl12xx_ptable; | 1442 | wl->ptable = wl12xx_ptable; |
1339 | wl->rtable = wl12xx_rtable; | 1443 | wl->rtable = wl12xx_rtable; |
1340 | wl->num_tx_desc = 16; | 1444 | wl->num_tx_desc = 16; |
1341 | wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; | 1445 | wl->num_rx_desc = 8; |
1342 | wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE; | ||
1343 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; | 1446 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; |
1344 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; | 1447 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; |
1345 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; | 1448 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; |
1346 | wl->fw_status_priv_len = 0; | 1449 | wl->fw_status_priv_len = 0; |
1347 | memcpy(&wl->ht_cap, &wl12xx_ht_cap, sizeof(wl12xx_ht_cap)); | 1450 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); |
1451 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap, | ||
1452 | sizeof(wl12xx_ht_cap)); | ||
1453 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap, | ||
1454 | sizeof(wl12xx_ht_cap)); | ||
1348 | wl12xx_conf_init(wl); | 1455 | wl12xx_conf_init(wl); |
1349 | 1456 | ||
1457 | if (!fref_param) { | ||
1458 | priv->ref_clock = pdata->board_ref_clock; | ||
1459 | } else { | ||
1460 | if (!strcmp(fref_param, "19.2")) | ||
1461 | priv->ref_clock = WL12XX_REFCLOCK_19; | ||
1462 | else if (!strcmp(fref_param, "26")) | ||
1463 | priv->ref_clock = WL12XX_REFCLOCK_26; | ||
1464 | else if (!strcmp(fref_param, "26x")) | ||
1465 | priv->ref_clock = WL12XX_REFCLOCK_26_XTAL; | ||
1466 | else if (!strcmp(fref_param, "38.4")) | ||
1467 | priv->ref_clock = WL12XX_REFCLOCK_38; | ||
1468 | else if (!strcmp(fref_param, "38.4x")) | ||
1469 | priv->ref_clock = WL12XX_REFCLOCK_38_XTAL; | ||
1470 | else if (!strcmp(fref_param, "52")) | ||
1471 | priv->ref_clock = WL12XX_REFCLOCK_52; | ||
1472 | else | ||
1473 | wl1271_error("Invalid fref parameter %s", fref_param); | ||
1474 | } | ||
1475 | |||
1476 | if (!tcxo_param) { | ||
1477 | priv->tcxo_clock = pdata->board_tcxo_clock; | ||
1478 | } else { | ||
1479 | if (!strcmp(tcxo_param, "19.2")) | ||
1480 | priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2; | ||
1481 | else if (!strcmp(tcxo_param, "26")) | ||
1482 | priv->tcxo_clock = WL12XX_TCXOCLOCK_26; | ||
1483 | else if (!strcmp(tcxo_param, "38.4")) | ||
1484 | priv->tcxo_clock = WL12XX_TCXOCLOCK_38_4; | ||
1485 | else if (!strcmp(tcxo_param, "52")) | ||
1486 | priv->tcxo_clock = WL12XX_TCXOCLOCK_52; | ||
1487 | else if (!strcmp(tcxo_param, "16.368")) | ||
1488 | priv->tcxo_clock = WL12XX_TCXOCLOCK_16_368; | ||
1489 | else if (!strcmp(tcxo_param, "32.736")) | ||
1490 | priv->tcxo_clock = WL12XX_TCXOCLOCK_32_736; | ||
1491 | else if (!strcmp(tcxo_param, "16.8")) | ||
1492 | priv->tcxo_clock = WL12XX_TCXOCLOCK_16_8; | ||
1493 | else if (!strcmp(tcxo_param, "33.6")) | ||
1494 | priv->tcxo_clock = WL12XX_TCXOCLOCK_33_6; | ||
1495 | else | ||
1496 | wl1271_error("Invalid tcxo parameter %s", tcxo_param); | ||
1497 | } | ||
1498 | |||
1350 | return wlcore_probe(wl, pdev); | 1499 | return wlcore_probe(wl, pdev); |
1351 | } | 1500 | } |
1352 | 1501 | ||
@@ -1378,6 +1527,13 @@ static void __exit wl12xx_exit(void) | |||
1378 | } | 1527 | } |
1379 | module_exit(wl12xx_exit); | 1528 | module_exit(wl12xx_exit); |
1380 | 1529 | ||
1530 | module_param_named(fref, fref_param, charp, 0); | ||
1531 | MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"); | ||
1532 | |||
1533 | module_param_named(tcxo, tcxo_param, charp, 0); | ||
1534 | MODULE_PARM_DESC(tcxo, | ||
1535 | "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6"); | ||
1536 | |||
1381 | MODULE_LICENSE("GPL v2"); | 1537 | MODULE_LICENSE("GPL v2"); |
1382 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 1538 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
1383 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); | 1539 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index 74cd332e23ef..de1132410876 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h | |||
@@ -24,8 +24,16 @@ | |||
24 | 24 | ||
25 | #include "conf.h" | 25 | #include "conf.h" |
26 | 26 | ||
27 | struct wl127x_rx_mem_pool_addr { | ||
28 | u32 addr; | ||
29 | u32 addr_extra; | ||
30 | }; | ||
31 | |||
27 | struct wl12xx_priv { | 32 | struct wl12xx_priv { |
28 | struct wl12xx_priv_conf conf; | 33 | struct wl12xx_priv_conf conf; |
34 | |||
35 | int ref_clock; | ||
36 | int tcxo_clock; | ||
29 | }; | 37 | }; |
30 | 38 | ||
31 | #endif /* __WL12XX_PRIV_H__ */ | 39 | #endif /* __WL12XX_PRIV_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/Kconfig b/drivers/net/wireless/ti/wl18xx/Kconfig new file mode 100644 index 000000000000..1cfdb2548821 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | config WL18XX | ||
2 | tristate "TI wl18xx support" | ||
3 | depends on MAC80211 | ||
4 | select WLCORE | ||
5 | ---help--- | ||
6 | This module adds support for wireless adapters based on TI | ||
7 | WiLink 8 chipsets. | ||
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile new file mode 100644 index 000000000000..67c098734c7f --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | wl18xx-objs = main.o acx.o tx.o io.o debugfs.o | ||
2 | |||
3 | obj-$(CONFIG_WL18XX) += wl18xx.o | ||
diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c new file mode 100644 index 000000000000..72840e23bf59 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/acx.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "../wlcore/cmd.h" | ||
23 | #include "../wlcore/debug.h" | ||
24 | #include "../wlcore/acx.h" | ||
25 | |||
26 | #include "acx.h" | ||
27 | |||
28 | int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, | ||
29 | u32 sdio_blk_size, u32 extra_mem_blks, | ||
30 | u32 len_field_size) | ||
31 | { | ||
32 | struct wl18xx_acx_host_config_bitmap *bitmap_conf; | ||
33 | int ret; | ||
34 | |||
35 | wl1271_debug(DEBUG_ACX, "acx cfg bitmap %d blk %d spare %d field %d", | ||
36 | host_cfg_bitmap, sdio_blk_size, extra_mem_blks, | ||
37 | len_field_size); | ||
38 | |||
39 | bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); | ||
40 | if (!bitmap_conf) { | ||
41 | ret = -ENOMEM; | ||
42 | goto out; | ||
43 | } | ||
44 | |||
45 | bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); | ||
46 | bitmap_conf->host_sdio_block_size = cpu_to_le32(sdio_blk_size); | ||
47 | bitmap_conf->extra_mem_blocks = cpu_to_le32(extra_mem_blks); | ||
48 | bitmap_conf->length_field_size = cpu_to_le32(len_field_size); | ||
49 | |||
50 | ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, | ||
51 | bitmap_conf, sizeof(*bitmap_conf)); | ||
52 | if (ret < 0) { | ||
53 | wl1271_warning("wl1271 bitmap config opt failed: %d", ret); | ||
54 | goto out; | ||
55 | } | ||
56 | |||
57 | out: | ||
58 | kfree(bitmap_conf); | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | int wl18xx_acx_set_checksum_state(struct wl1271 *wl) | ||
64 | { | ||
65 | struct wl18xx_acx_checksum_state *acx; | ||
66 | int ret; | ||
67 | |||
68 | wl1271_debug(DEBUG_ACX, "acx checksum state"); | ||
69 | |||
70 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
71 | if (!acx) { | ||
72 | ret = -ENOMEM; | ||
73 | goto out; | ||
74 | } | ||
75 | |||
76 | acx->checksum_state = CHECKSUM_OFFLOAD_ENABLED; | ||
77 | |||
78 | ret = wl1271_cmd_configure(wl, ACX_CHECKSUM_CONFIG, acx, sizeof(*acx)); | ||
79 | if (ret < 0) { | ||
80 | wl1271_warning("failed to set Tx checksum state: %d", ret); | ||
81 | goto out; | ||
82 | } | ||
83 | |||
84 | out: | ||
85 | kfree(acx); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | int wl18xx_acx_clear_statistics(struct wl1271 *wl) | ||
90 | { | ||
91 | struct wl18xx_acx_clear_statistics *acx; | ||
92 | int ret = 0; | ||
93 | |||
94 | wl1271_debug(DEBUG_ACX, "acx clear statistics"); | ||
95 | |||
96 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
97 | if (!acx) { | ||
98 | ret = -ENOMEM; | ||
99 | goto out; | ||
100 | } | ||
101 | |||
102 | ret = wl1271_cmd_configure(wl, ACX_CLEAR_STATISTICS, acx, sizeof(*acx)); | ||
103 | if (ret < 0) { | ||
104 | wl1271_warning("failed to clear firmware statistics: %d", ret); | ||
105 | goto out; | ||
106 | } | ||
107 | |||
108 | out: | ||
109 | kfree(acx); | ||
110 | return ret; | ||
111 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h new file mode 100644 index 000000000000..ebbaf611e97b --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/acx.h | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_ACX_H__ | ||
23 | #define __WL18XX_ACX_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | #include "../wlcore/acx.h" | ||
27 | |||
28 | enum { | ||
29 | ACX_CLEAR_STATISTICS = 0x0047, | ||
30 | }; | ||
31 | |||
32 | /* numbers of bits the length field takes (add 1 for the actual number) */ | ||
33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 | ||
34 | |||
35 | #define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | ||
36 | WL1271_ACX_INTR_INIT_COMPLETE | \ | ||
37 | WL1271_ACX_INTR_EVENT_A | \ | ||
38 | WL1271_ACX_INTR_EVENT_B | \ | ||
39 | WL1271_ACX_INTR_CMD_COMPLETE | \ | ||
40 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
41 | WL1271_ACX_INTR_DATA) | ||
42 | |||
43 | #define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \ | ||
44 | WL1271_ACX_SW_INTR_WATCHDOG) | ||
45 | |||
46 | #define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | ||
47 | WL1271_ACX_INTR_EVENT_A | \ | ||
48 | WL1271_ACX_INTR_EVENT_B | \ | ||
49 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
50 | WL1271_ACX_INTR_DATA) | ||
51 | |||
52 | #define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \ | ||
53 | WL1271_ACX_SW_INTR_WATCHDOG) | ||
54 | |||
55 | struct wl18xx_acx_host_config_bitmap { | ||
56 | struct acx_header header; | ||
57 | |||
58 | __le32 host_cfg_bitmap; | ||
59 | |||
60 | __le32 host_sdio_block_size; | ||
61 | |||
62 | /* extra mem blocks per frame in TX. */ | ||
63 | __le32 extra_mem_blocks; | ||
64 | |||
65 | /* | ||
66 | * number of bits of the length field in the first TX word | ||
67 | * (up to 15 - for using the entire 16 bits). | ||
68 | */ | ||
69 | __le32 length_field_size; | ||
70 | |||
71 | } __packed; | ||
72 | |||
73 | enum { | ||
74 | CHECKSUM_OFFLOAD_DISABLED = 0, | ||
75 | CHECKSUM_OFFLOAD_ENABLED = 1, | ||
76 | CHECKSUM_OFFLOAD_FAKE_RX = 2, | ||
77 | CHECKSUM_OFFLOAD_INVALID = 0xFF | ||
78 | }; | ||
79 | |||
80 | struct wl18xx_acx_checksum_state { | ||
81 | struct acx_header header; | ||
82 | |||
83 | /* enum acx_checksum_state */ | ||
84 | u8 checksum_state; | ||
85 | u8 pad[3]; | ||
86 | } __packed; | ||
87 | |||
88 | |||
89 | struct wl18xx_acx_error_stats { | ||
90 | u32 error_frame; | ||
91 | u32 error_null_Frame_tx_start; | ||
92 | u32 error_numll_frame_cts_start; | ||
93 | u32 error_bar_retry; | ||
94 | u32 error_frame_cts_nul_flid; | ||
95 | } __packed; | ||
96 | |||
97 | struct wl18xx_acx_debug_stats { | ||
98 | u32 debug1; | ||
99 | u32 debug2; | ||
100 | u32 debug3; | ||
101 | u32 debug4; | ||
102 | u32 debug5; | ||
103 | u32 debug6; | ||
104 | } __packed; | ||
105 | |||
106 | struct wl18xx_acx_ring_stats { | ||
107 | u32 prepared_descs; | ||
108 | u32 tx_cmplt; | ||
109 | } __packed; | ||
110 | |||
111 | struct wl18xx_acx_tx_stats { | ||
112 | u32 tx_prepared_descs; | ||
113 | u32 tx_cmplt; | ||
114 | u32 tx_template_prepared; | ||
115 | u32 tx_data_prepared; | ||
116 | u32 tx_template_programmed; | ||
117 | u32 tx_data_programmed; | ||
118 | u32 tx_burst_programmed; | ||
119 | u32 tx_starts; | ||
120 | u32 tx_imm_resp; | ||
121 | u32 tx_start_templates; | ||
122 | u32 tx_start_int_templates; | ||
123 | u32 tx_start_fw_gen; | ||
124 | u32 tx_start_data; | ||
125 | u32 tx_start_null_frame; | ||
126 | u32 tx_exch; | ||
127 | u32 tx_retry_template; | ||
128 | u32 tx_retry_data; | ||
129 | u32 tx_exch_pending; | ||
130 | u32 tx_exch_expiry; | ||
131 | u32 tx_done_template; | ||
132 | u32 tx_done_data; | ||
133 | u32 tx_done_int_template; | ||
134 | u32 tx_frame_checksum; | ||
135 | u32 tx_checksum_result; | ||
136 | u32 frag_called; | ||
137 | u32 frag_mpdu_alloc_failed; | ||
138 | u32 frag_init_called; | ||
139 | u32 frag_in_process_called; | ||
140 | u32 frag_tkip_called; | ||
141 | u32 frag_key_not_found; | ||
142 | u32 frag_need_fragmentation; | ||
143 | u32 frag_bad_mblk_num; | ||
144 | u32 frag_failed; | ||
145 | u32 frag_cache_hit; | ||
146 | u32 frag_cache_miss; | ||
147 | } __packed; | ||
148 | |||
149 | struct wl18xx_acx_rx_stats { | ||
150 | u32 rx_beacon_early_term; | ||
151 | u32 rx_out_of_mpdu_nodes; | ||
152 | u32 rx_hdr_overflow; | ||
153 | u32 rx_dropped_frame; | ||
154 | u32 rx_done_stage; | ||
155 | u32 rx_done; | ||
156 | u32 rx_defrag; | ||
157 | u32 rx_defrag_end; | ||
158 | u32 rx_cmplt; | ||
159 | u32 rx_pre_complt; | ||
160 | u32 rx_cmplt_task; | ||
161 | u32 rx_phy_hdr; | ||
162 | u32 rx_timeout; | ||
163 | u32 rx_timeout_wa; | ||
164 | u32 rx_wa_density_dropped_frame; | ||
165 | u32 rx_wa_ba_not_expected; | ||
166 | u32 rx_frame_checksum; | ||
167 | u32 rx_checksum_result; | ||
168 | u32 defrag_called; | ||
169 | u32 defrag_init_called; | ||
170 | u32 defrag_in_process_called; | ||
171 | u32 defrag_tkip_called; | ||
172 | u32 defrag_need_defrag; | ||
173 | u32 defrag_decrypt_failed; | ||
174 | u32 decrypt_key_not_found; | ||
175 | u32 defrag_need_decrypt; | ||
176 | u32 rx_tkip_replays; | ||
177 | } __packed; | ||
178 | |||
179 | struct wl18xx_acx_isr_stats { | ||
180 | u32 irqs; | ||
181 | } __packed; | ||
182 | |||
183 | #define PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD 10 | ||
184 | |||
185 | struct wl18xx_acx_pwr_stats { | ||
186 | u32 missing_bcns_cnt; | ||
187 | u32 rcvd_bcns_cnt; | ||
188 | u32 connection_out_of_sync; | ||
189 | u32 cont_miss_bcns_spread[PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD]; | ||
190 | u32 rcvd_awake_bcns_cnt; | ||
191 | } __packed; | ||
192 | |||
193 | struct wl18xx_acx_event_stats { | ||
194 | u32 calibration; | ||
195 | u32 rx_mismatch; | ||
196 | u32 rx_mem_empty; | ||
197 | } __packed; | ||
198 | |||
199 | struct wl18xx_acx_ps_poll_stats { | ||
200 | u32 ps_poll_timeouts; | ||
201 | u32 upsd_timeouts; | ||
202 | u32 upsd_max_ap_turn; | ||
203 | u32 ps_poll_max_ap_turn; | ||
204 | u32 ps_poll_utilization; | ||
205 | u32 upsd_utilization; | ||
206 | } __packed; | ||
207 | |||
208 | struct wl18xx_acx_rx_filter_stats { | ||
209 | u32 beacon_filter; | ||
210 | u32 arp_filter; | ||
211 | u32 mc_filter; | ||
212 | u32 dup_filter; | ||
213 | u32 data_filter; | ||
214 | u32 ibss_filter; | ||
215 | u32 protection_filter; | ||
216 | u32 accum_arp_pend_requests; | ||
217 | u32 max_arp_queue_dep; | ||
218 | } __packed; | ||
219 | |||
220 | struct wl18xx_acx_rx_rate_stats { | ||
221 | u32 rx_frames_per_rates[50]; | ||
222 | } __packed; | ||
223 | |||
224 | #define AGGR_STATS_TX_AGG 16 | ||
225 | #define AGGR_STATS_TX_RATE 16 | ||
226 | #define AGGR_STATS_RX_SIZE_LEN 16 | ||
227 | |||
228 | struct wl18xx_acx_aggr_stats { | ||
229 | u32 tx_agg_vs_rate[AGGR_STATS_TX_AGG * AGGR_STATS_TX_RATE]; | ||
230 | u32 rx_size[AGGR_STATS_RX_SIZE_LEN]; | ||
231 | } __packed; | ||
232 | |||
233 | #define PIPE_STATS_HW_FIFO 11 | ||
234 | |||
235 | struct wl18xx_acx_pipeline_stats { | ||
236 | u32 hs_tx_stat_fifo_int; | ||
237 | u32 hs_rx_stat_fifo_int; | ||
238 | u32 tcp_tx_stat_fifo_int; | ||
239 | u32 tcp_rx_stat_fifo_int; | ||
240 | u32 enc_tx_stat_fifo_int; | ||
241 | u32 enc_rx_stat_fifo_int; | ||
242 | u32 rx_complete_stat_fifo_int; | ||
243 | u32 pre_proc_swi; | ||
244 | u32 post_proc_swi; | ||
245 | u32 sec_frag_swi; | ||
246 | u32 pre_to_defrag_swi; | ||
247 | u32 defrag_to_csum_swi; | ||
248 | u32 csum_to_rx_xfer_swi; | ||
249 | u32 dec_packet_in; | ||
250 | u32 dec_packet_in_fifo_full; | ||
251 | u32 dec_packet_out; | ||
252 | u32 cs_rx_packet_in; | ||
253 | u32 cs_rx_packet_out; | ||
254 | u16 pipeline_fifo_full[PIPE_STATS_HW_FIFO]; | ||
255 | } __packed; | ||
256 | |||
257 | struct wl18xx_acx_mem_stats { | ||
258 | u32 rx_free_mem_blks; | ||
259 | u32 tx_free_mem_blks; | ||
260 | u32 fwlog_free_mem_blks; | ||
261 | u32 fw_gen_free_mem_blks; | ||
262 | } __packed; | ||
263 | |||
264 | struct wl18xx_acx_statistics { | ||
265 | struct acx_header header; | ||
266 | |||
267 | struct wl18xx_acx_error_stats error; | ||
268 | struct wl18xx_acx_debug_stats debug; | ||
269 | struct wl18xx_acx_tx_stats tx; | ||
270 | struct wl18xx_acx_rx_stats rx; | ||
271 | struct wl18xx_acx_isr_stats isr; | ||
272 | struct wl18xx_acx_pwr_stats pwr; | ||
273 | struct wl18xx_acx_ps_poll_stats ps_poll; | ||
274 | struct wl18xx_acx_rx_filter_stats rx_filter; | ||
275 | struct wl18xx_acx_rx_rate_stats rx_rate; | ||
276 | struct wl18xx_acx_aggr_stats aggr_size; | ||
277 | struct wl18xx_acx_pipeline_stats pipeline; | ||
278 | struct wl18xx_acx_mem_stats mem; | ||
279 | } __packed; | ||
280 | |||
281 | struct wl18xx_acx_clear_statistics { | ||
282 | struct acx_header header; | ||
283 | }; | ||
284 | |||
285 | int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, | ||
286 | u32 sdio_blk_size, u32 extra_mem_blks, | ||
287 | u32 len_field_size); | ||
288 | int wl18xx_acx_set_checksum_state(struct wl1271 *wl); | ||
289 | int wl18xx_acx_clear_statistics(struct wl1271 *wl); | ||
290 | |||
291 | #endif /* __WL18XX_ACX_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h new file mode 100644 index 000000000000..fac0b7e87e75 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/conf.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_CONF_H__ | ||
23 | #define __WL18XX_CONF_H__ | ||
24 | |||
25 | #define WL18XX_CONF_MAGIC 0x10e100ca | ||
26 | #define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0002) | ||
27 | #define WL18XX_CONF_MASK 0x0000ffff | ||
28 | #define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ | ||
29 | sizeof(struct wl18xx_priv_conf)) | ||
30 | |||
31 | #define NUM_OF_CHANNELS_11_ABG 150 | ||
32 | #define NUM_OF_CHANNELS_11_P 7 | ||
33 | #define WL18XX_NUM_OF_SUB_BANDS 9 | ||
34 | #define SRF_TABLE_LEN 16 | ||
35 | #define PIN_MUXING_SIZE 2 | ||
36 | |||
37 | struct wl18xx_mac_and_phy_params { | ||
38 | u8 phy_standalone; | ||
39 | u8 rdl; | ||
40 | u8 enable_clpc; | ||
41 | u8 enable_tx_low_pwr_on_siso_rdl; | ||
42 | u8 auto_detect; | ||
43 | u8 dedicated_fem; | ||
44 | |||
45 | u8 low_band_component; | ||
46 | |||
47 | /* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */ | ||
48 | u8 low_band_component_type; | ||
49 | |||
50 | u8 high_band_component; | ||
51 | |||
52 | /* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */ | ||
53 | u8 high_band_component_type; | ||
54 | u8 number_of_assembled_ant2_4; | ||
55 | u8 number_of_assembled_ant5; | ||
56 | u8 pin_muxing_platform_options[PIN_MUXING_SIZE]; | ||
57 | u8 external_pa_dc2dc; | ||
58 | u8 tcxo_ldo_voltage; | ||
59 | u8 xtal_itrim_val; | ||
60 | u8 srf_state; | ||
61 | u8 srf1[SRF_TABLE_LEN]; | ||
62 | u8 srf2[SRF_TABLE_LEN]; | ||
63 | u8 srf3[SRF_TABLE_LEN]; | ||
64 | u8 io_configuration; | ||
65 | u8 sdio_configuration; | ||
66 | u8 settings; | ||
67 | u8 rx_profile; | ||
68 | u8 per_chan_pwr_limit_arr_11abg[NUM_OF_CHANNELS_11_ABG]; | ||
69 | u8 pwr_limit_reference_11_abg; | ||
70 | u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P]; | ||
71 | u8 pwr_limit_reference_11p; | ||
72 | u8 per_sub_band_tx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; | ||
73 | u8 per_sub_band_rx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; | ||
74 | u8 primary_clock_setting_time; | ||
75 | u8 clock_valid_on_wake_up; | ||
76 | u8 secondary_clock_setting_time; | ||
77 | u8 board_type; | ||
78 | /* enable point saturation */ | ||
79 | u8 psat; | ||
80 | /* low/medium/high Tx power in dBm */ | ||
81 | s8 low_power_val; | ||
82 | s8 med_power_val; | ||
83 | s8 high_power_val; | ||
84 | u8 padding[1]; | ||
85 | } __packed; | ||
86 | |||
87 | struct wl18xx_priv_conf { | ||
88 | /* this structure is copied wholesale to FW */ | ||
89 | struct wl18xx_mac_and_phy_params phy; | ||
90 | } __packed; | ||
91 | |||
92 | #endif /* __WL18XX_CONF_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c new file mode 100644 index 000000000000..3ce6f1039af3 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c | |||
@@ -0,0 +1,403 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * Copyright (C) 2011-2012 Texas Instruments | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include "../wlcore/debugfs.h" | ||
24 | #include "../wlcore/wlcore.h" | ||
25 | |||
26 | #include "wl18xx.h" | ||
27 | #include "acx.h" | ||
28 | #include "debugfs.h" | ||
29 | |||
30 | #define WL18XX_DEBUGFS_FWSTATS_FILE(a, b, c) \ | ||
31 | DEBUGFS_FWSTATS_FILE(a, b, c, wl18xx_acx_statistics) | ||
32 | #define WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c) \ | ||
33 | DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c, wl18xx_acx_statistics) | ||
34 | |||
35 | |||
36 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug1, "%u"); | ||
37 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug2, "%u"); | ||
38 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug3, "%u"); | ||
39 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug4, "%u"); | ||
40 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug5, "%u"); | ||
41 | WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug6, "%u"); | ||
42 | |||
43 | WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame, "%u"); | ||
44 | WL18XX_DEBUGFS_FWSTATS_FILE(error, error_null_Frame_tx_start, "%u"); | ||
45 | WL18XX_DEBUGFS_FWSTATS_FILE(error, error_numll_frame_cts_start, "%u"); | ||
46 | WL18XX_DEBUGFS_FWSTATS_FILE(error, error_bar_retry, "%u"); | ||
47 | WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame_cts_nul_flid, "%u"); | ||
48 | |||
49 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_prepared_descs, "%u"); | ||
50 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_cmplt, "%u"); | ||
51 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_prepared, "%u"); | ||
52 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_prepared, "%u"); | ||
53 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_programmed, "%u"); | ||
54 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_programmed, "%u"); | ||
55 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_burst_programmed, "%u"); | ||
56 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_starts, "%u"); | ||
57 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_imm_resp, "%u"); | ||
58 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_templates, "%u"); | ||
59 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_int_templates, "%u"); | ||
60 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_fw_gen, "%u"); | ||
61 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_data, "%u"); | ||
62 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_null_frame, "%u"); | ||
63 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch, "%u"); | ||
64 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_template, "%u"); | ||
65 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_data, "%u"); | ||
66 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_pending, "%u"); | ||
67 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_expiry, "%u"); | ||
68 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_template, "%u"); | ||
69 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_data, "%u"); | ||
70 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_int_template, "%u"); | ||
71 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_frame_checksum, "%u"); | ||
72 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_checksum_result, "%u"); | ||
73 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_called, "%u"); | ||
74 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_mpdu_alloc_failed, "%u"); | ||
75 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_init_called, "%u"); | ||
76 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_in_process_called, "%u"); | ||
77 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_tkip_called, "%u"); | ||
78 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_key_not_found, "%u"); | ||
79 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_need_fragmentation, "%u"); | ||
80 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_bad_mblk_num, "%u"); | ||
81 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_failed, "%u"); | ||
82 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_hit, "%u"); | ||
83 | WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_miss, "%u"); | ||
84 | |||
85 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_beacon_early_term, "%u"); | ||
86 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_out_of_mpdu_nodes, "%u"); | ||
87 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hdr_overflow, "%u"); | ||
88 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_dropped_frame, "%u"); | ||
89 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_done, "%u"); | ||
90 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag, "%u"); | ||
91 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag_end, "%u"); | ||
92 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt, "%u"); | ||
93 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_pre_complt, "%u"); | ||
94 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt_task, "%u"); | ||
95 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_phy_hdr, "%u"); | ||
96 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout, "%u"); | ||
97 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout_wa, "%u"); | ||
98 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_density_dropped_frame, "%u"); | ||
99 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_ba_not_expected, "%u"); | ||
100 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_frame_checksum, "%u"); | ||
101 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_checksum_result, "%u"); | ||
102 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_called, "%u"); | ||
103 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_init_called, "%u"); | ||
104 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_in_process_called, "%u"); | ||
105 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_tkip_called, "%u"); | ||
106 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_defrag, "%u"); | ||
107 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_decrypt_failed, "%u"); | ||
108 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, decrypt_key_not_found, "%u"); | ||
109 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_decrypt, "%u"); | ||
110 | WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_tkip_replays, "%u"); | ||
111 | |||
112 | WL18XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); | ||
113 | |||
114 | WL18XX_DEBUGFS_FWSTATS_FILE(pwr, missing_bcns_cnt, "%u"); | ||
115 | WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_bcns_cnt, "%u"); | ||
116 | WL18XX_DEBUGFS_FWSTATS_FILE(pwr, connection_out_of_sync, "%u"); | ||
117 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pwr, cont_miss_bcns_spread, | ||
118 | PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD); | ||
119 | WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_bcns_cnt, "%u"); | ||
120 | |||
121 | |||
122 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_timeouts, "%u"); | ||
123 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_timeouts, "%u"); | ||
124 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_max_ap_turn, "%u"); | ||
125 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_max_ap_turn, "%u"); | ||
126 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_utilization, "%u"); | ||
127 | WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_utilization, "%u"); | ||
128 | |||
129 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, beacon_filter, "%u"); | ||
130 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, arp_filter, "%u"); | ||
131 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, mc_filter, "%u"); | ||
132 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, dup_filter, "%u"); | ||
133 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, data_filter, "%u"); | ||
134 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, ibss_filter, "%u"); | ||
135 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u"); | ||
136 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); | ||
137 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); | ||
138 | |||
139 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u"); | ||
140 | |||
141 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, | ||
142 | AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); | ||
143 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, rx_size, | ||
144 | AGGR_STATS_RX_SIZE_LEN); | ||
145 | |||
146 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, hs_tx_stat_fifo_int, "%u"); | ||
147 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_tx_stat_fifo_int, "%u"); | ||
148 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_rx_stat_fifo_int, "%u"); | ||
149 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_tx_stat_fifo_int, "%u"); | ||
150 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_rx_stat_fifo_int, "%u"); | ||
151 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, rx_complete_stat_fifo_int, "%u"); | ||
152 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_proc_swi, "%u"); | ||
153 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, post_proc_swi, "%u"); | ||
154 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, sec_frag_swi, "%u"); | ||
155 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_to_defrag_swi, "%u"); | ||
156 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, defrag_to_csum_swi, "%u"); | ||
157 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, csum_to_rx_xfer_swi, "%u"); | ||
158 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in, "%u"); | ||
159 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in_fifo_full, "%u"); | ||
160 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_out, "%u"); | ||
161 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_in, "%u"); | ||
162 | WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_out, "%u"); | ||
163 | |||
164 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pipeline, pipeline_fifo_full, | ||
165 | PIPE_STATS_HW_FIFO); | ||
166 | |||
167 | WL18XX_DEBUGFS_FWSTATS_FILE(mem, rx_free_mem_blks, "%u"); | ||
168 | WL18XX_DEBUGFS_FWSTATS_FILE(mem, tx_free_mem_blks, "%u"); | ||
169 | WL18XX_DEBUGFS_FWSTATS_FILE(mem, fwlog_free_mem_blks, "%u"); | ||
170 | WL18XX_DEBUGFS_FWSTATS_FILE(mem, fw_gen_free_mem_blks, "%u"); | ||
171 | |||
172 | static ssize_t conf_read(struct file *file, char __user *user_buf, | ||
173 | size_t count, loff_t *ppos) | ||
174 | { | ||
175 | struct wl1271 *wl = file->private_data; | ||
176 | struct wl18xx_priv *priv = wl->priv; | ||
177 | struct wlcore_conf_header header; | ||
178 | char *buf, *pos; | ||
179 | size_t len; | ||
180 | int ret; | ||
181 | |||
182 | len = WL18XX_CONF_SIZE; | ||
183 | buf = kmalloc(len, GFP_KERNEL); | ||
184 | if (!buf) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | header.magic = cpu_to_le32(WL18XX_CONF_MAGIC); | ||
188 | header.version = cpu_to_le32(WL18XX_CONF_VERSION); | ||
189 | header.checksum = 0; | ||
190 | |||
191 | mutex_lock(&wl->mutex); | ||
192 | |||
193 | pos = buf; | ||
194 | memcpy(pos, &header, sizeof(header)); | ||
195 | pos += sizeof(header); | ||
196 | memcpy(pos, &wl->conf, sizeof(wl->conf)); | ||
197 | pos += sizeof(wl->conf); | ||
198 | memcpy(pos, &priv->conf, sizeof(priv->conf)); | ||
199 | |||
200 | mutex_unlock(&wl->mutex); | ||
201 | |||
202 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
203 | |||
204 | kfree(buf); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static const struct file_operations conf_ops = { | ||
209 | .read = conf_read, | ||
210 | .open = simple_open, | ||
211 | .llseek = default_llseek, | ||
212 | }; | ||
213 | |||
214 | static ssize_t clear_fw_stats_write(struct file *file, | ||
215 | const char __user *user_buf, | ||
216 | size_t count, loff_t *ppos) | ||
217 | { | ||
218 | struct wl1271 *wl = file->private_data; | ||
219 | int ret; | ||
220 | |||
221 | mutex_lock(&wl->mutex); | ||
222 | |||
223 | if (wl->state == WL1271_STATE_OFF) | ||
224 | goto out; | ||
225 | |||
226 | ret = wl18xx_acx_clear_statistics(wl); | ||
227 | if (ret < 0) { | ||
228 | count = ret; | ||
229 | goto out; | ||
230 | } | ||
231 | out: | ||
232 | mutex_unlock(&wl->mutex); | ||
233 | return count; | ||
234 | } | ||
235 | |||
236 | static const struct file_operations clear_fw_stats_ops = { | ||
237 | .write = clear_fw_stats_write, | ||
238 | .open = simple_open, | ||
239 | .llseek = default_llseek, | ||
240 | }; | ||
241 | |||
242 | int wl18xx_debugfs_add_files(struct wl1271 *wl, | ||
243 | struct dentry *rootdir) | ||
244 | { | ||
245 | int ret = 0; | ||
246 | struct dentry *entry, *stats, *moddir; | ||
247 | |||
248 | moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); | ||
249 | if (!moddir || IS_ERR(moddir)) { | ||
250 | entry = moddir; | ||
251 | goto err; | ||
252 | } | ||
253 | |||
254 | stats = debugfs_create_dir("fw_stats", moddir); | ||
255 | if (!stats || IS_ERR(stats)) { | ||
256 | entry = stats; | ||
257 | goto err; | ||
258 | } | ||
259 | |||
260 | DEBUGFS_ADD(clear_fw_stats, stats); | ||
261 | |||
262 | DEBUGFS_FWSTATS_ADD(debug, debug1); | ||
263 | DEBUGFS_FWSTATS_ADD(debug, debug2); | ||
264 | DEBUGFS_FWSTATS_ADD(debug, debug3); | ||
265 | DEBUGFS_FWSTATS_ADD(debug, debug4); | ||
266 | DEBUGFS_FWSTATS_ADD(debug, debug5); | ||
267 | DEBUGFS_FWSTATS_ADD(debug, debug6); | ||
268 | |||
269 | DEBUGFS_FWSTATS_ADD(error, error_frame); | ||
270 | DEBUGFS_FWSTATS_ADD(error, error_null_Frame_tx_start); | ||
271 | DEBUGFS_FWSTATS_ADD(error, error_numll_frame_cts_start); | ||
272 | DEBUGFS_FWSTATS_ADD(error, error_bar_retry); | ||
273 | DEBUGFS_FWSTATS_ADD(error, error_frame_cts_nul_flid); | ||
274 | |||
275 | DEBUGFS_FWSTATS_ADD(tx, tx_prepared_descs); | ||
276 | DEBUGFS_FWSTATS_ADD(tx, tx_cmplt); | ||
277 | DEBUGFS_FWSTATS_ADD(tx, tx_template_prepared); | ||
278 | DEBUGFS_FWSTATS_ADD(tx, tx_data_prepared); | ||
279 | DEBUGFS_FWSTATS_ADD(tx, tx_template_programmed); | ||
280 | DEBUGFS_FWSTATS_ADD(tx, tx_data_programmed); | ||
281 | DEBUGFS_FWSTATS_ADD(tx, tx_burst_programmed); | ||
282 | DEBUGFS_FWSTATS_ADD(tx, tx_starts); | ||
283 | DEBUGFS_FWSTATS_ADD(tx, tx_imm_resp); | ||
284 | DEBUGFS_FWSTATS_ADD(tx, tx_start_templates); | ||
285 | DEBUGFS_FWSTATS_ADD(tx, tx_start_int_templates); | ||
286 | DEBUGFS_FWSTATS_ADD(tx, tx_start_fw_gen); | ||
287 | DEBUGFS_FWSTATS_ADD(tx, tx_start_data); | ||
288 | DEBUGFS_FWSTATS_ADD(tx, tx_start_null_frame); | ||
289 | DEBUGFS_FWSTATS_ADD(tx, tx_exch); | ||
290 | DEBUGFS_FWSTATS_ADD(tx, tx_retry_template); | ||
291 | DEBUGFS_FWSTATS_ADD(tx, tx_retry_data); | ||
292 | DEBUGFS_FWSTATS_ADD(tx, tx_exch_pending); | ||
293 | DEBUGFS_FWSTATS_ADD(tx, tx_exch_expiry); | ||
294 | DEBUGFS_FWSTATS_ADD(tx, tx_done_template); | ||
295 | DEBUGFS_FWSTATS_ADD(tx, tx_done_data); | ||
296 | DEBUGFS_FWSTATS_ADD(tx, tx_done_int_template); | ||
297 | DEBUGFS_FWSTATS_ADD(tx, tx_frame_checksum); | ||
298 | DEBUGFS_FWSTATS_ADD(tx, tx_checksum_result); | ||
299 | DEBUGFS_FWSTATS_ADD(tx, frag_called); | ||
300 | DEBUGFS_FWSTATS_ADD(tx, frag_mpdu_alloc_failed); | ||
301 | DEBUGFS_FWSTATS_ADD(tx, frag_init_called); | ||
302 | DEBUGFS_FWSTATS_ADD(tx, frag_in_process_called); | ||
303 | DEBUGFS_FWSTATS_ADD(tx, frag_tkip_called); | ||
304 | DEBUGFS_FWSTATS_ADD(tx, frag_key_not_found); | ||
305 | DEBUGFS_FWSTATS_ADD(tx, frag_need_fragmentation); | ||
306 | DEBUGFS_FWSTATS_ADD(tx, frag_bad_mblk_num); | ||
307 | DEBUGFS_FWSTATS_ADD(tx, frag_failed); | ||
308 | DEBUGFS_FWSTATS_ADD(tx, frag_cache_hit); | ||
309 | DEBUGFS_FWSTATS_ADD(tx, frag_cache_miss); | ||
310 | |||
311 | DEBUGFS_FWSTATS_ADD(rx, rx_beacon_early_term); | ||
312 | DEBUGFS_FWSTATS_ADD(rx, rx_out_of_mpdu_nodes); | ||
313 | DEBUGFS_FWSTATS_ADD(rx, rx_hdr_overflow); | ||
314 | DEBUGFS_FWSTATS_ADD(rx, rx_dropped_frame); | ||
315 | DEBUGFS_FWSTATS_ADD(rx, rx_done); | ||
316 | DEBUGFS_FWSTATS_ADD(rx, rx_defrag); | ||
317 | DEBUGFS_FWSTATS_ADD(rx, rx_defrag_end); | ||
318 | DEBUGFS_FWSTATS_ADD(rx, rx_cmplt); | ||
319 | DEBUGFS_FWSTATS_ADD(rx, rx_pre_complt); | ||
320 | DEBUGFS_FWSTATS_ADD(rx, rx_cmplt_task); | ||
321 | DEBUGFS_FWSTATS_ADD(rx, rx_phy_hdr); | ||
322 | DEBUGFS_FWSTATS_ADD(rx, rx_timeout); | ||
323 | DEBUGFS_FWSTATS_ADD(rx, rx_timeout_wa); | ||
324 | DEBUGFS_FWSTATS_ADD(rx, rx_wa_density_dropped_frame); | ||
325 | DEBUGFS_FWSTATS_ADD(rx, rx_wa_ba_not_expected); | ||
326 | DEBUGFS_FWSTATS_ADD(rx, rx_frame_checksum); | ||
327 | DEBUGFS_FWSTATS_ADD(rx, rx_checksum_result); | ||
328 | DEBUGFS_FWSTATS_ADD(rx, defrag_called); | ||
329 | DEBUGFS_FWSTATS_ADD(rx, defrag_init_called); | ||
330 | DEBUGFS_FWSTATS_ADD(rx, defrag_in_process_called); | ||
331 | DEBUGFS_FWSTATS_ADD(rx, defrag_tkip_called); | ||
332 | DEBUGFS_FWSTATS_ADD(rx, defrag_need_defrag); | ||
333 | DEBUGFS_FWSTATS_ADD(rx, defrag_decrypt_failed); | ||
334 | DEBUGFS_FWSTATS_ADD(rx, decrypt_key_not_found); | ||
335 | DEBUGFS_FWSTATS_ADD(rx, defrag_need_decrypt); | ||
336 | DEBUGFS_FWSTATS_ADD(rx, rx_tkip_replays); | ||
337 | |||
338 | DEBUGFS_FWSTATS_ADD(isr, irqs); | ||
339 | |||
340 | DEBUGFS_FWSTATS_ADD(pwr, missing_bcns_cnt); | ||
341 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_bcns_cnt); | ||
342 | DEBUGFS_FWSTATS_ADD(pwr, connection_out_of_sync); | ||
343 | DEBUGFS_FWSTATS_ADD(pwr, cont_miss_bcns_spread); | ||
344 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_bcns_cnt); | ||
345 | |||
346 | DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_timeouts); | ||
347 | DEBUGFS_FWSTATS_ADD(ps_poll, upsd_timeouts); | ||
348 | DEBUGFS_FWSTATS_ADD(ps_poll, upsd_max_ap_turn); | ||
349 | DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_max_ap_turn); | ||
350 | DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_utilization); | ||
351 | DEBUGFS_FWSTATS_ADD(ps_poll, upsd_utilization); | ||
352 | |||
353 | DEBUGFS_FWSTATS_ADD(rx_filter, beacon_filter); | ||
354 | DEBUGFS_FWSTATS_ADD(rx_filter, arp_filter); | ||
355 | DEBUGFS_FWSTATS_ADD(rx_filter, mc_filter); | ||
356 | DEBUGFS_FWSTATS_ADD(rx_filter, dup_filter); | ||
357 | DEBUGFS_FWSTATS_ADD(rx_filter, data_filter); | ||
358 | DEBUGFS_FWSTATS_ADD(rx_filter, ibss_filter); | ||
359 | DEBUGFS_FWSTATS_ADD(rx_filter, protection_filter); | ||
360 | DEBUGFS_FWSTATS_ADD(rx_filter, accum_arp_pend_requests); | ||
361 | DEBUGFS_FWSTATS_ADD(rx_filter, max_arp_queue_dep); | ||
362 | |||
363 | DEBUGFS_FWSTATS_ADD(rx_rate, rx_frames_per_rates); | ||
364 | |||
365 | DEBUGFS_FWSTATS_ADD(aggr_size, tx_agg_vs_rate); | ||
366 | DEBUGFS_FWSTATS_ADD(aggr_size, rx_size); | ||
367 | |||
368 | DEBUGFS_FWSTATS_ADD(pipeline, hs_tx_stat_fifo_int); | ||
369 | DEBUGFS_FWSTATS_ADD(pipeline, tcp_tx_stat_fifo_int); | ||
370 | DEBUGFS_FWSTATS_ADD(pipeline, tcp_rx_stat_fifo_int); | ||
371 | DEBUGFS_FWSTATS_ADD(pipeline, enc_tx_stat_fifo_int); | ||
372 | DEBUGFS_FWSTATS_ADD(pipeline, enc_rx_stat_fifo_int); | ||
373 | DEBUGFS_FWSTATS_ADD(pipeline, rx_complete_stat_fifo_int); | ||
374 | DEBUGFS_FWSTATS_ADD(pipeline, pre_proc_swi); | ||
375 | DEBUGFS_FWSTATS_ADD(pipeline, post_proc_swi); | ||
376 | DEBUGFS_FWSTATS_ADD(pipeline, sec_frag_swi); | ||
377 | DEBUGFS_FWSTATS_ADD(pipeline, pre_to_defrag_swi); | ||
378 | DEBUGFS_FWSTATS_ADD(pipeline, defrag_to_csum_swi); | ||
379 | DEBUGFS_FWSTATS_ADD(pipeline, csum_to_rx_xfer_swi); | ||
380 | DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in); | ||
381 | DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in_fifo_full); | ||
382 | DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_out); | ||
383 | DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_in); | ||
384 | DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_out); | ||
385 | DEBUGFS_FWSTATS_ADD(pipeline, pipeline_fifo_full); | ||
386 | |||
387 | DEBUGFS_FWSTATS_ADD(mem, rx_free_mem_blks); | ||
388 | DEBUGFS_FWSTATS_ADD(mem, tx_free_mem_blks); | ||
389 | DEBUGFS_FWSTATS_ADD(mem, fwlog_free_mem_blks); | ||
390 | DEBUGFS_FWSTATS_ADD(mem, fw_gen_free_mem_blks); | ||
391 | |||
392 | DEBUGFS_ADD(conf, moddir); | ||
393 | |||
394 | return 0; | ||
395 | |||
396 | err: | ||
397 | if (IS_ERR(entry)) | ||
398 | ret = PTR_ERR(entry); | ||
399 | else | ||
400 | ret = -ENOMEM; | ||
401 | |||
402 | return ret; | ||
403 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.h b/drivers/net/wireless/ti/wl18xx/debugfs.h new file mode 100644 index 000000000000..ed679bebf620 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/debugfs.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_DEBUGFS_H__ | ||
23 | #define __WL18XX_DEBUGFS_H__ | ||
24 | |||
25 | int wl18xx_debugfs_add_files(struct wl1271 *wl, | ||
26 | struct dentry *rootdir); | ||
27 | |||
28 | #endif /* __WL18XX_DEBUGFS_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c new file mode 100644 index 000000000000..598c057e722b --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/io.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "../wlcore/wlcore.h" | ||
23 | #include "../wlcore/io.h" | ||
24 | |||
25 | #include "io.h" | ||
26 | |||
27 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
28 | { | ||
29 | u32 tmp; | ||
30 | |||
31 | if (WARN_ON(addr % 2)) | ||
32 | return; | ||
33 | |||
34 | if ((addr % 4) == 0) { | ||
35 | tmp = wl1271_read32(wl, addr); | ||
36 | tmp = (tmp & 0xffff0000) | val; | ||
37 | wl1271_write32(wl, addr, tmp); | ||
38 | } else { | ||
39 | tmp = wl1271_read32(wl, addr - 2); | ||
40 | tmp = (tmp & 0xffff) | (val << 16); | ||
41 | wl1271_write32(wl, addr - 2, tmp); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) | ||
46 | { | ||
47 | u32 val; | ||
48 | |||
49 | if (WARN_ON(addr % 2)) | ||
50 | return 0; | ||
51 | |||
52 | if ((addr % 4) == 0) { | ||
53 | /* address is 4-bytes aligned */ | ||
54 | val = wl1271_read32(wl, addr); | ||
55 | return val & 0xffff; | ||
56 | } else { | ||
57 | val = wl1271_read32(wl, addr - 2); | ||
58 | return (val & 0xffff0000) >> 16; | ||
59 | } | ||
60 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h new file mode 100644 index 000000000000..be4e126ff617 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/io.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_IO_H__ | ||
23 | #define __WL18XX_IO_H__ | ||
24 | |||
25 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
26 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); | ||
27 | |||
28 | #endif /* __WL18XX_IO_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c new file mode 100644 index 000000000000..ed9c3650e08a --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -0,0 +1,1463 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/ip.h> | ||
25 | #include <linux/firmware.h> | ||
26 | |||
27 | #include "../wlcore/wlcore.h" | ||
28 | #include "../wlcore/debug.h" | ||
29 | #include "../wlcore/io.h" | ||
30 | #include "../wlcore/acx.h" | ||
31 | #include "../wlcore/tx.h" | ||
32 | #include "../wlcore/rx.h" | ||
33 | #include "../wlcore/io.h" | ||
34 | #include "../wlcore/boot.h" | ||
35 | |||
36 | #include "reg.h" | ||
37 | #include "conf.h" | ||
38 | #include "acx.h" | ||
39 | #include "tx.h" | ||
40 | #include "wl18xx.h" | ||
41 | #include "io.h" | ||
42 | #include "debugfs.h" | ||
43 | |||
44 | #define WL18XX_RX_CHECKSUM_MASK 0x40 | ||
45 | |||
46 | static char *ht_mode_param = "wide"; | ||
47 | static char *board_type_param = "hdk"; | ||
48 | static bool checksum_param = false; | ||
49 | static bool enable_11a_param = true; | ||
50 | |||
51 | /* phy paramters */ | ||
52 | static int dc2dc_param = -1; | ||
53 | static int n_antennas_2_param = -1; | ||
54 | static int n_antennas_5_param = -1; | ||
55 | static int low_band_component_param = -1; | ||
56 | static int low_band_component_type_param = -1; | ||
57 | static int high_band_component_param = -1; | ||
58 | static int high_band_component_type_param = -1; | ||
59 | static int pwr_limit_reference_11_abg_param = -1; | ||
60 | |||
61 | static const u8 wl18xx_rate_to_idx_2ghz[] = { | ||
62 | /* MCS rates are used only with 11n */ | ||
63 | 15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */ | ||
64 | 14, /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */ | ||
65 | 13, /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */ | ||
66 | 12, /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */ | ||
67 | 11, /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */ | ||
68 | 10, /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */ | ||
69 | 9, /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */ | ||
70 | 8, /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */ | ||
71 | 7, /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */ | ||
72 | 6, /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */ | ||
73 | 5, /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */ | ||
74 | 4, /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */ | ||
75 | 3, /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */ | ||
76 | 2, /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */ | ||
77 | 1, /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */ | ||
78 | 0, /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */ | ||
79 | |||
80 | 11, /* WL18XX_CONF_HW_RXTX_RATE_54 */ | ||
81 | 10, /* WL18XX_CONF_HW_RXTX_RATE_48 */ | ||
82 | 9, /* WL18XX_CONF_HW_RXTX_RATE_36 */ | ||
83 | 8, /* WL18XX_CONF_HW_RXTX_RATE_24 */ | ||
84 | |||
85 | /* TI-specific rate */ | ||
86 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22 */ | ||
87 | |||
88 | 7, /* WL18XX_CONF_HW_RXTX_RATE_18 */ | ||
89 | 6, /* WL18XX_CONF_HW_RXTX_RATE_12 */ | ||
90 | 3, /* WL18XX_CONF_HW_RXTX_RATE_11 */ | ||
91 | 5, /* WL18XX_CONF_HW_RXTX_RATE_9 */ | ||
92 | 4, /* WL18XX_CONF_HW_RXTX_RATE_6 */ | ||
93 | 2, /* WL18XX_CONF_HW_RXTX_RATE_5_5 */ | ||
94 | 1, /* WL18XX_CONF_HW_RXTX_RATE_2 */ | ||
95 | 0 /* WL18XX_CONF_HW_RXTX_RATE_1 */ | ||
96 | }; | ||
97 | |||
98 | static const u8 wl18xx_rate_to_idx_5ghz[] = { | ||
99 | /* MCS rates are used only with 11n */ | ||
100 | 15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */ | ||
101 | 14, /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */ | ||
102 | 13, /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */ | ||
103 | 12, /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */ | ||
104 | 11, /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */ | ||
105 | 10, /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */ | ||
106 | 9, /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */ | ||
107 | 8, /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */ | ||
108 | 7, /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */ | ||
109 | 6, /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */ | ||
110 | 5, /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */ | ||
111 | 4, /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */ | ||
112 | 3, /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */ | ||
113 | 2, /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */ | ||
114 | 1, /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */ | ||
115 | 0, /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */ | ||
116 | |||
117 | 7, /* WL18XX_CONF_HW_RXTX_RATE_54 */ | ||
118 | 6, /* WL18XX_CONF_HW_RXTX_RATE_48 */ | ||
119 | 5, /* WL18XX_CONF_HW_RXTX_RATE_36 */ | ||
120 | 4, /* WL18XX_CONF_HW_RXTX_RATE_24 */ | ||
121 | |||
122 | /* TI-specific rate */ | ||
123 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22 */ | ||
124 | |||
125 | 3, /* WL18XX_CONF_HW_RXTX_RATE_18 */ | ||
126 | 2, /* WL18XX_CONF_HW_RXTX_RATE_12 */ | ||
127 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_11 */ | ||
128 | 1, /* WL18XX_CONF_HW_RXTX_RATE_9 */ | ||
129 | 0, /* WL18XX_CONF_HW_RXTX_RATE_6 */ | ||
130 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_5_5 */ | ||
131 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_2 */ | ||
132 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_1 */ | ||
133 | }; | ||
134 | |||
135 | static const u8 *wl18xx_band_rate_to_idx[] = { | ||
136 | [IEEE80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz, | ||
137 | [IEEE80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz | ||
138 | }; | ||
139 | |||
140 | enum wl18xx_hw_rates { | ||
141 | WL18XX_CONF_HW_RXTX_RATE_MCS15 = 0, | ||
142 | WL18XX_CONF_HW_RXTX_RATE_MCS14, | ||
143 | WL18XX_CONF_HW_RXTX_RATE_MCS13, | ||
144 | WL18XX_CONF_HW_RXTX_RATE_MCS12, | ||
145 | WL18XX_CONF_HW_RXTX_RATE_MCS11, | ||
146 | WL18XX_CONF_HW_RXTX_RATE_MCS10, | ||
147 | WL18XX_CONF_HW_RXTX_RATE_MCS9, | ||
148 | WL18XX_CONF_HW_RXTX_RATE_MCS8, | ||
149 | WL18XX_CONF_HW_RXTX_RATE_MCS7, | ||
150 | WL18XX_CONF_HW_RXTX_RATE_MCS6, | ||
151 | WL18XX_CONF_HW_RXTX_RATE_MCS5, | ||
152 | WL18XX_CONF_HW_RXTX_RATE_MCS4, | ||
153 | WL18XX_CONF_HW_RXTX_RATE_MCS3, | ||
154 | WL18XX_CONF_HW_RXTX_RATE_MCS2, | ||
155 | WL18XX_CONF_HW_RXTX_RATE_MCS1, | ||
156 | WL18XX_CONF_HW_RXTX_RATE_MCS0, | ||
157 | WL18XX_CONF_HW_RXTX_RATE_54, | ||
158 | WL18XX_CONF_HW_RXTX_RATE_48, | ||
159 | WL18XX_CONF_HW_RXTX_RATE_36, | ||
160 | WL18XX_CONF_HW_RXTX_RATE_24, | ||
161 | WL18XX_CONF_HW_RXTX_RATE_22, | ||
162 | WL18XX_CONF_HW_RXTX_RATE_18, | ||
163 | WL18XX_CONF_HW_RXTX_RATE_12, | ||
164 | WL18XX_CONF_HW_RXTX_RATE_11, | ||
165 | WL18XX_CONF_HW_RXTX_RATE_9, | ||
166 | WL18XX_CONF_HW_RXTX_RATE_6, | ||
167 | WL18XX_CONF_HW_RXTX_RATE_5_5, | ||
168 | WL18XX_CONF_HW_RXTX_RATE_2, | ||
169 | WL18XX_CONF_HW_RXTX_RATE_1, | ||
170 | WL18XX_CONF_HW_RXTX_RATE_MAX, | ||
171 | }; | ||
172 | |||
173 | static struct wlcore_conf wl18xx_conf = { | ||
174 | .sg = { | ||
175 | .params = { | ||
176 | [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, | ||
177 | [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, | ||
178 | [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, | ||
179 | [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, | ||
180 | [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, | ||
181 | [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, | ||
182 | [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, | ||
183 | [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, | ||
184 | [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, | ||
185 | [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, | ||
186 | [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, | ||
187 | [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, | ||
188 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, | ||
189 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, | ||
190 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, | ||
191 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, | ||
192 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, | ||
193 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, | ||
194 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, | ||
195 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, | ||
196 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, | ||
197 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, | ||
198 | [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, | ||
199 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, | ||
200 | [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, | ||
201 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, | ||
202 | /* active scan params */ | ||
203 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
204 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
205 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
206 | /* passive scan params */ | ||
207 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, | ||
208 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, | ||
209 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
210 | /* passive scan in dual antenna params */ | ||
211 | [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, | ||
212 | [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, | ||
213 | [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, | ||
214 | /* general params */ | ||
215 | [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, | ||
216 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
217 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
218 | [CONF_SG_DHCP_TIME] = 5000, | ||
219 | [CONF_SG_RXT] = 1200, | ||
220 | [CONF_SG_TXT] = 1000, | ||
221 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
222 | [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, | ||
223 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
224 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
225 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
226 | [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, | ||
227 | [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, | ||
228 | [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, | ||
229 | /* AP params */ | ||
230 | [CONF_AP_BEACON_MISS_TX] = 3, | ||
231 | [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, | ||
232 | [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, | ||
233 | [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, | ||
234 | [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, | ||
235 | [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, | ||
236 | /* CTS Diluting params */ | ||
237 | [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, | ||
238 | [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, | ||
239 | }, | ||
240 | .state = CONF_SG_PROTECTIVE, | ||
241 | }, | ||
242 | .rx = { | ||
243 | .rx_msdu_life_time = 512000, | ||
244 | .packet_detection_threshold = 0, | ||
245 | .ps_poll_timeout = 15, | ||
246 | .upsd_timeout = 15, | ||
247 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, | ||
248 | .rx_cca_threshold = 0, | ||
249 | .irq_blk_threshold = 0xFFFF, | ||
250 | .irq_pkt_threshold = 0, | ||
251 | .irq_timeout = 600, | ||
252 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | ||
253 | }, | ||
254 | .tx = { | ||
255 | .tx_energy_detection = 0, | ||
256 | .sta_rc_conf = { | ||
257 | .enabled_rates = 0, | ||
258 | .short_retry_limit = 10, | ||
259 | .long_retry_limit = 10, | ||
260 | .aflags = 0, | ||
261 | }, | ||
262 | .ac_conf_count = 4, | ||
263 | .ac_conf = { | ||
264 | [CONF_TX_AC_BE] = { | ||
265 | .ac = CONF_TX_AC_BE, | ||
266 | .cw_min = 15, | ||
267 | .cw_max = 63, | ||
268 | .aifsn = 3, | ||
269 | .tx_op_limit = 0, | ||
270 | }, | ||
271 | [CONF_TX_AC_BK] = { | ||
272 | .ac = CONF_TX_AC_BK, | ||
273 | .cw_min = 15, | ||
274 | .cw_max = 63, | ||
275 | .aifsn = 7, | ||
276 | .tx_op_limit = 0, | ||
277 | }, | ||
278 | [CONF_TX_AC_VI] = { | ||
279 | .ac = CONF_TX_AC_VI, | ||
280 | .cw_min = 15, | ||
281 | .cw_max = 63, | ||
282 | .aifsn = CONF_TX_AIFS_PIFS, | ||
283 | .tx_op_limit = 3008, | ||
284 | }, | ||
285 | [CONF_TX_AC_VO] = { | ||
286 | .ac = CONF_TX_AC_VO, | ||
287 | .cw_min = 15, | ||
288 | .cw_max = 63, | ||
289 | .aifsn = CONF_TX_AIFS_PIFS, | ||
290 | .tx_op_limit = 1504, | ||
291 | }, | ||
292 | }, | ||
293 | .max_tx_retries = 100, | ||
294 | .ap_aging_period = 300, | ||
295 | .tid_conf_count = 4, | ||
296 | .tid_conf = { | ||
297 | [CONF_TX_AC_BE] = { | ||
298 | .queue_id = CONF_TX_AC_BE, | ||
299 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
300 | .tsid = CONF_TX_AC_BE, | ||
301 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
302 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
303 | .apsd_conf = {0, 0}, | ||
304 | }, | ||
305 | [CONF_TX_AC_BK] = { | ||
306 | .queue_id = CONF_TX_AC_BK, | ||
307 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
308 | .tsid = CONF_TX_AC_BK, | ||
309 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
310 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
311 | .apsd_conf = {0, 0}, | ||
312 | }, | ||
313 | [CONF_TX_AC_VI] = { | ||
314 | .queue_id = CONF_TX_AC_VI, | ||
315 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
316 | .tsid = CONF_TX_AC_VI, | ||
317 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
318 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
319 | .apsd_conf = {0, 0}, | ||
320 | }, | ||
321 | [CONF_TX_AC_VO] = { | ||
322 | .queue_id = CONF_TX_AC_VO, | ||
323 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
324 | .tsid = CONF_TX_AC_VO, | ||
325 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
326 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
327 | .apsd_conf = {0, 0}, | ||
328 | }, | ||
329 | }, | ||
330 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | ||
331 | .tx_compl_timeout = 350, | ||
332 | .tx_compl_threshold = 10, | ||
333 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
334 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
335 | .tmpl_short_retry_limit = 10, | ||
336 | .tmpl_long_retry_limit = 10, | ||
337 | .tx_watchdog_timeout = 5000, | ||
338 | }, | ||
339 | .conn = { | ||
340 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | ||
341 | .listen_interval = 1, | ||
342 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, | ||
343 | .suspend_listen_interval = 3, | ||
344 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | ||
345 | .bcn_filt_ie_count = 3, | ||
346 | .bcn_filt_ie = { | ||
347 | [0] = { | ||
348 | .ie = WLAN_EID_CHANNEL_SWITCH, | ||
349 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | ||
350 | }, | ||
351 | [1] = { | ||
352 | .ie = WLAN_EID_HT_OPERATION, | ||
353 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
354 | }, | ||
355 | [2] = { | ||
356 | .ie = WLAN_EID_ERP_INFO, | ||
357 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
358 | }, | ||
359 | }, | ||
360 | .synch_fail_thold = 12, | ||
361 | .bss_lose_timeout = 400, | ||
362 | .beacon_rx_timeout = 10000, | ||
363 | .broadcast_timeout = 20000, | ||
364 | .rx_broadcast_in_ps = 1, | ||
365 | .ps_poll_threshold = 10, | ||
366 | .bet_enable = CONF_BET_MODE_ENABLE, | ||
367 | .bet_max_consecutive = 50, | ||
368 | .psm_entry_retries = 8, | ||
369 | .psm_exit_retries = 16, | ||
370 | .psm_entry_nullfunc_retries = 3, | ||
371 | .dynamic_ps_timeout = 200, | ||
372 | .forced_ps = false, | ||
373 | .keep_alive_interval = 55000, | ||
374 | .max_listen_interval = 20, | ||
375 | }, | ||
376 | .itrim = { | ||
377 | .enable = false, | ||
378 | .timeout = 50000, | ||
379 | }, | ||
380 | .pm_config = { | ||
381 | .host_clk_settling_time = 5000, | ||
382 | .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE, | ||
383 | }, | ||
384 | .roam_trigger = { | ||
385 | .trigger_pacing = 1, | ||
386 | .avg_weight_rssi_beacon = 20, | ||
387 | .avg_weight_rssi_data = 10, | ||
388 | .avg_weight_snr_beacon = 20, | ||
389 | .avg_weight_snr_data = 10, | ||
390 | }, | ||
391 | .scan = { | ||
392 | .min_dwell_time_active = 7500, | ||
393 | .max_dwell_time_active = 30000, | ||
394 | .min_dwell_time_passive = 100000, | ||
395 | .max_dwell_time_passive = 100000, | ||
396 | .num_probe_reqs = 2, | ||
397 | .split_scan_timeout = 50000, | ||
398 | }, | ||
399 | .sched_scan = { | ||
400 | /* | ||
401 | * Values are in TU/1000 but since sched scan FW command | ||
402 | * params are in TUs rounding up may occur. | ||
403 | */ | ||
404 | .base_dwell_time = 7500, | ||
405 | .max_dwell_time_delta = 22500, | ||
406 | /* based on 250bits per probe @1Mbps */ | ||
407 | .dwell_time_delta_per_probe = 2000, | ||
408 | /* based on 250bits per probe @6Mbps (plus a bit more) */ | ||
409 | .dwell_time_delta_per_probe_5 = 350, | ||
410 | .dwell_time_passive = 100000, | ||
411 | .dwell_time_dfs = 150000, | ||
412 | .num_probe_reqs = 2, | ||
413 | .rssi_threshold = -90, | ||
414 | .snr_threshold = 0, | ||
415 | }, | ||
416 | .ht = { | ||
417 | .rx_ba_win_size = 10, | ||
418 | .tx_ba_win_size = 64, | ||
419 | .inactivity_timeout = 10000, | ||
420 | .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, | ||
421 | }, | ||
422 | .mem = { | ||
423 | .num_stations = 1, | ||
424 | .ssid_profiles = 1, | ||
425 | .rx_block_num = 40, | ||
426 | .tx_min_block_num = 40, | ||
427 | .dynamic_memory = 1, | ||
428 | .min_req_tx_blocks = 45, | ||
429 | .min_req_rx_blocks = 22, | ||
430 | .tx_min = 27, | ||
431 | }, | ||
432 | .fm_coex = { | ||
433 | .enable = true, | ||
434 | .swallow_period = 5, | ||
435 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
436 | .n_divider_fref_set_2 = 12, | ||
437 | .m_divider_fref_set_1 = 0xffff, | ||
438 | .m_divider_fref_set_2 = 148, /* default */ | ||
439 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
440 | .ldo_stabilization_time = 0xffff, /* default */ | ||
441 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
442 | .swallow_clk_diff = 0xff, /* default */ | ||
443 | }, | ||
444 | .rx_streaming = { | ||
445 | .duration = 150, | ||
446 | .queues = 0x1, | ||
447 | .interval = 20, | ||
448 | .always = 0, | ||
449 | }, | ||
450 | .fwlog = { | ||
451 | .mode = WL12XX_FWLOG_ON_DEMAND, | ||
452 | .mem_blocks = 2, | ||
453 | .severity = 0, | ||
454 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | ||
455 | .output = WL12XX_FWLOG_OUTPUT_HOST, | ||
456 | .threshold = 0, | ||
457 | }, | ||
458 | .rate = { | ||
459 | .rate_retry_score = 32000, | ||
460 | .per_add = 8192, | ||
461 | .per_th1 = 2048, | ||
462 | .per_th2 = 4096, | ||
463 | .max_per = 8100, | ||
464 | .inverse_curiosity_factor = 5, | ||
465 | .tx_fail_low_th = 4, | ||
466 | .tx_fail_high_th = 10, | ||
467 | .per_alpha_shift = 4, | ||
468 | .per_add_shift = 13, | ||
469 | .per_beta1_shift = 10, | ||
470 | .per_beta2_shift = 8, | ||
471 | .rate_check_up = 2, | ||
472 | .rate_check_down = 12, | ||
473 | .rate_retry_policy = { | ||
474 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
475 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
476 | 0x00, 0x00, 0x00, | ||
477 | }, | ||
478 | }, | ||
479 | .hangover = { | ||
480 | .recover_time = 0, | ||
481 | .hangover_period = 20, | ||
482 | .dynamic_mode = 1, | ||
483 | .early_termination_mode = 1, | ||
484 | .max_period = 20, | ||
485 | .min_period = 1, | ||
486 | .increase_delta = 1, | ||
487 | .decrease_delta = 2, | ||
488 | .quiet_time = 4, | ||
489 | .increase_time = 1, | ||
490 | .window_size = 16, | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | ||
495 | .phy = { | ||
496 | .phy_standalone = 0x00, | ||
497 | .primary_clock_setting_time = 0x05, | ||
498 | .clock_valid_on_wake_up = 0x00, | ||
499 | .secondary_clock_setting_time = 0x05, | ||
500 | .rdl = 0x01, | ||
501 | .auto_detect = 0x00, | ||
502 | .dedicated_fem = FEM_NONE, | ||
503 | .low_band_component = COMPONENT_2_WAY_SWITCH, | ||
504 | .low_band_component_type = 0x05, | ||
505 | .high_band_component = COMPONENT_2_WAY_SWITCH, | ||
506 | .high_band_component_type = 0x09, | ||
507 | .tcxo_ldo_voltage = 0x00, | ||
508 | .xtal_itrim_val = 0x04, | ||
509 | .srf_state = 0x00, | ||
510 | .io_configuration = 0x01, | ||
511 | .sdio_configuration = 0x00, | ||
512 | .settings = 0x00, | ||
513 | .enable_clpc = 0x00, | ||
514 | .enable_tx_low_pwr_on_siso_rdl = 0x00, | ||
515 | .rx_profile = 0x00, | ||
516 | .pwr_limit_reference_11_abg = 0xc8, | ||
517 | .psat = 0, | ||
518 | .low_power_val = 0x00, | ||
519 | .med_power_val = 0x0a, | ||
520 | .high_power_val = 0x1e, | ||
521 | .external_pa_dc2dc = 0, | ||
522 | .number_of_assembled_ant2_4 = 1, | ||
523 | .number_of_assembled_ant5 = 1, | ||
524 | }, | ||
525 | }; | ||
526 | |||
527 | static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = { | ||
528 | [PART_TOP_PRCM_ELP_SOC] = { | ||
529 | .mem = { .start = 0x00A02000, .size = 0x00010000 }, | ||
530 | .reg = { .start = 0x00807000, .size = 0x00005000 }, | ||
531 | .mem2 = { .start = 0x00800000, .size = 0x0000B000 }, | ||
532 | .mem3 = { .start = 0x00000000, .size = 0x00000000 }, | ||
533 | }, | ||
534 | [PART_DOWN] = { | ||
535 | .mem = { .start = 0x00000000, .size = 0x00014000 }, | ||
536 | .reg = { .start = 0x00810000, .size = 0x0000BFFF }, | ||
537 | .mem2 = { .start = 0x00000000, .size = 0x00000000 }, | ||
538 | .mem3 = { .start = 0x00000000, .size = 0x00000000 }, | ||
539 | }, | ||
540 | [PART_BOOT] = { | ||
541 | .mem = { .start = 0x00700000, .size = 0x0000030c }, | ||
542 | .reg = { .start = 0x00802000, .size = 0x00014578 }, | ||
543 | .mem2 = { .start = 0x00B00404, .size = 0x00001000 }, | ||
544 | .mem3 = { .start = 0x00C00000, .size = 0x00000400 }, | ||
545 | }, | ||
546 | [PART_WORK] = { | ||
547 | .mem = { .start = 0x00800000, .size = 0x000050FC }, | ||
548 | .reg = { .start = 0x00B00404, .size = 0x00001000 }, | ||
549 | .mem2 = { .start = 0x00C00000, .size = 0x00000400 }, | ||
550 | .mem3 = { .start = 0x00000000, .size = 0x00000000 }, | ||
551 | }, | ||
552 | [PART_PHY_INIT] = { | ||
553 | .mem = { .start = 0x80926000, | ||
554 | .size = sizeof(struct wl18xx_mac_and_phy_params) }, | ||
555 | .reg = { .start = 0x00000000, .size = 0x00000000 }, | ||
556 | .mem2 = { .start = 0x00000000, .size = 0x00000000 }, | ||
557 | .mem3 = { .start = 0x00000000, .size = 0x00000000 }, | ||
558 | }, | ||
559 | }; | ||
560 | |||
561 | static const int wl18xx_rtable[REG_TABLE_LEN] = { | ||
562 | [REG_ECPU_CONTROL] = WL18XX_REG_ECPU_CONTROL, | ||
563 | [REG_INTERRUPT_NO_CLEAR] = WL18XX_REG_INTERRUPT_NO_CLEAR, | ||
564 | [REG_INTERRUPT_ACK] = WL18XX_REG_INTERRUPT_ACK, | ||
565 | [REG_COMMAND_MAILBOX_PTR] = WL18XX_REG_COMMAND_MAILBOX_PTR, | ||
566 | [REG_EVENT_MAILBOX_PTR] = WL18XX_REG_EVENT_MAILBOX_PTR, | ||
567 | [REG_INTERRUPT_TRIG] = WL18XX_REG_INTERRUPT_TRIG_H, | ||
568 | [REG_INTERRUPT_MASK] = WL18XX_REG_INTERRUPT_MASK, | ||
569 | [REG_PC_ON_RECOVERY] = WL18XX_SCR_PAD4, | ||
570 | [REG_CHIP_ID_B] = WL18XX_REG_CHIP_ID_B, | ||
571 | [REG_CMD_MBOX_ADDRESS] = WL18XX_CMD_MBOX_ADDRESS, | ||
572 | |||
573 | /* data access memory addresses, used with partition translation */ | ||
574 | [REG_SLV_MEM_DATA] = WL18XX_SLV_MEM_DATA, | ||
575 | [REG_SLV_REG_DATA] = WL18XX_SLV_REG_DATA, | ||
576 | |||
577 | /* raw data access memory addresses */ | ||
578 | [REG_RAW_FW_STATUS_ADDR] = WL18XX_FW_STATUS_ADDR, | ||
579 | }; | ||
580 | |||
581 | static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { | ||
582 | [CLOCK_CONFIG_16_2_M] = { 7, 104, 801, 4, true }, | ||
583 | [CLOCK_CONFIG_16_368_M] = { 9, 132, 3751, 4, true }, | ||
584 | [CLOCK_CONFIG_16_8_M] = { 7, 100, 0, 0, false }, | ||
585 | [CLOCK_CONFIG_19_2_M] = { 8, 100, 0, 0, false }, | ||
586 | [CLOCK_CONFIG_26_M] = { 13, 120, 0, 0, false }, | ||
587 | [CLOCK_CONFIG_32_736_M] = { 9, 132, 3751, 4, true }, | ||
588 | [CLOCK_CONFIG_33_6_M] = { 7, 100, 0, 0, false }, | ||
589 | [CLOCK_CONFIG_38_468_M] = { 8, 100, 0, 0, false }, | ||
590 | [CLOCK_CONFIG_52_M] = { 13, 120, 0, 0, false }, | ||
591 | }; | ||
592 | |||
593 | /* TODO: maybe move to a new header file? */ | ||
594 | #define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin" | ||
595 | |||
596 | static int wl18xx_identify_chip(struct wl1271 *wl) | ||
597 | { | ||
598 | int ret = 0; | ||
599 | |||
600 | switch (wl->chip.id) { | ||
601 | case CHIP_ID_185x_PG20: | ||
602 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG20)", | ||
603 | wl->chip.id); | ||
604 | wl->sr_fw_name = WL18XX_FW_NAME; | ||
605 | /* wl18xx uses the same firmware for PLT */ | ||
606 | wl->plt_fw_name = WL18XX_FW_NAME; | ||
607 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | ||
608 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
609 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | ||
610 | |||
611 | break; | ||
612 | case CHIP_ID_185x_PG10: | ||
613 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)", | ||
614 | wl->chip.id); | ||
615 | wl->sr_fw_name = WL18XX_FW_NAME; | ||
616 | /* wl18xx uses the same firmware for PLT */ | ||
617 | wl->plt_fw_name = WL18XX_FW_NAME; | ||
618 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | ||
619 | WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | | ||
620 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
621 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
622 | |||
623 | /* PG 1.0 has some problems with MCS_13, so disable it */ | ||
624 | wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5); | ||
625 | |||
626 | break; | ||
627 | default: | ||
628 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | ||
629 | ret = -ENODEV; | ||
630 | goto out; | ||
631 | } | ||
632 | |||
633 | out: | ||
634 | return ret; | ||
635 | } | ||
636 | |||
637 | static void wl18xx_set_clk(struct wl1271 *wl) | ||
638 | { | ||
639 | u32 clk_freq; | ||
640 | |||
641 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | ||
642 | |||
643 | /* TODO: PG2: apparently we need to read the clk type */ | ||
644 | |||
645 | clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); | ||
646 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, | ||
647 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, | ||
648 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, | ||
649 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); | ||
650 | |||
651 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); | ||
652 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); | ||
653 | |||
654 | if (wl18xx_clk_table[clk_freq].swallow) { | ||
655 | /* first the 16 lower bits */ | ||
656 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, | ||
657 | wl18xx_clk_table[clk_freq].q & | ||
658 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); | ||
659 | /* then the 16 higher bits, masked out */ | ||
660 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, | ||
661 | (wl18xx_clk_table[clk_freq].q >> 16) & | ||
662 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); | ||
663 | |||
664 | /* first the 16 lower bits */ | ||
665 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, | ||
666 | wl18xx_clk_table[clk_freq].p & | ||
667 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); | ||
668 | /* then the 16 higher bits, masked out */ | ||
669 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, | ||
670 | (wl18xx_clk_table[clk_freq].p >> 16) & | ||
671 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); | ||
672 | } else { | ||
673 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, | ||
674 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | static void wl18xx_boot_soft_reset(struct wl1271 *wl) | ||
679 | { | ||
680 | /* disable Rx/Tx */ | ||
681 | wl1271_write32(wl, WL18XX_ENABLE, 0x0); | ||
682 | |||
683 | /* disable auto calibration on start*/ | ||
684 | wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff); | ||
685 | } | ||
686 | |||
687 | static int wl18xx_pre_boot(struct wl1271 *wl) | ||
688 | { | ||
689 | wl18xx_set_clk(wl); | ||
690 | |||
691 | /* Continue the ELP wake up sequence */ | ||
692 | wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | ||
693 | udelay(500); | ||
694 | |||
695 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
696 | |||
697 | /* Disable interrupts */ | ||
698 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | ||
699 | |||
700 | wl18xx_boot_soft_reset(wl); | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static void wl18xx_pre_upload(struct wl1271 *wl) | ||
706 | { | ||
707 | u32 tmp; | ||
708 | |||
709 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
710 | |||
711 | /* TODO: check if this is all needed */ | ||
712 | wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); | ||
713 | |||
714 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | ||
715 | |||
716 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | ||
717 | |||
718 | tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); | ||
719 | } | ||
720 | |||
721 | static void wl18xx_set_mac_and_phy(struct wl1271 *wl) | ||
722 | { | ||
723 | struct wl18xx_priv *priv = wl->priv; | ||
724 | size_t len; | ||
725 | |||
726 | /* the parameters struct is smaller for PG1 */ | ||
727 | if (wl->chip.id == CHIP_ID_185x_PG10) | ||
728 | len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1; | ||
729 | else | ||
730 | len = sizeof(struct wl18xx_mac_and_phy_params); | ||
731 | |||
732 | wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); | ||
733 | wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, | ||
734 | false); | ||
735 | } | ||
736 | |||
737 | static void wl18xx_enable_interrupts(struct wl1271 *wl) | ||
738 | { | ||
739 | u32 event_mask, intr_mask; | ||
740 | |||
741 | if (wl->chip.id == CHIP_ID_185x_PG10) { | ||
742 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1; | ||
743 | intr_mask = WL18XX_INTR_MASK_PG1; | ||
744 | } else { | ||
745 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2; | ||
746 | intr_mask = WL18XX_INTR_MASK_PG2; | ||
747 | } | ||
748 | |||
749 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); | ||
750 | |||
751 | wlcore_enable_interrupts(wl); | ||
752 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | ||
753 | WL1271_ACX_INTR_ALL & ~intr_mask); | ||
754 | } | ||
755 | |||
756 | static int wl18xx_boot(struct wl1271 *wl) | ||
757 | { | ||
758 | int ret; | ||
759 | |||
760 | ret = wl18xx_pre_boot(wl); | ||
761 | if (ret < 0) | ||
762 | goto out; | ||
763 | |||
764 | wl18xx_pre_upload(wl); | ||
765 | |||
766 | ret = wlcore_boot_upload_firmware(wl); | ||
767 | if (ret < 0) | ||
768 | goto out; | ||
769 | |||
770 | wl18xx_set_mac_and_phy(wl); | ||
771 | |||
772 | ret = wlcore_boot_run_firmware(wl); | ||
773 | if (ret < 0) | ||
774 | goto out; | ||
775 | |||
776 | wl18xx_enable_interrupts(wl); | ||
777 | |||
778 | out: | ||
779 | return ret; | ||
780 | } | ||
781 | |||
782 | static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | ||
783 | void *buf, size_t len) | ||
784 | { | ||
785 | struct wl18xx_priv *priv = wl->priv; | ||
786 | |||
787 | memcpy(priv->cmd_buf, buf, len); | ||
788 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); | ||
789 | |||
790 | wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE, | ||
791 | false); | ||
792 | } | ||
793 | |||
794 | static void wl18xx_ack_event(struct wl1271 *wl) | ||
795 | { | ||
796 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK); | ||
797 | } | ||
798 | |||
799 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | ||
800 | { | ||
801 | u32 blk_size = WL18XX_TX_HW_BLOCK_SIZE; | ||
802 | return (len + blk_size - 1) / blk_size + spare_blks; | ||
803 | } | ||
804 | |||
805 | static void | ||
806 | wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | ||
807 | u32 blks, u32 spare_blks) | ||
808 | { | ||
809 | desc->wl18xx_mem.total_mem_blocks = blks; | ||
810 | } | ||
811 | |||
812 | static void | ||
813 | wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | ||
814 | struct sk_buff *skb) | ||
815 | { | ||
816 | desc->length = cpu_to_le16(skb->len); | ||
817 | |||
818 | /* if only the last frame is to be padded, we unset this bit on Tx */ | ||
819 | if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) | ||
820 | desc->wl18xx_mem.ctrl = WL18XX_TX_CTRL_NOT_PADDED; | ||
821 | else | ||
822 | desc->wl18xx_mem.ctrl = 0; | ||
823 | |||
824 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " | ||
825 | "len: %d life: %d mem: %d", desc->hlid, | ||
826 | le16_to_cpu(desc->length), | ||
827 | le16_to_cpu(desc->life_time), | ||
828 | desc->wl18xx_mem.total_mem_blocks); | ||
829 | } | ||
830 | |||
831 | static enum wl_rx_buf_align | ||
832 | wl18xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | ||
833 | { | ||
834 | if (rx_desc & RX_BUF_PADDED_PAYLOAD) | ||
835 | return WLCORE_RX_BUF_PADDED; | ||
836 | |||
837 | return WLCORE_RX_BUF_ALIGNED; | ||
838 | } | ||
839 | |||
840 | static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | ||
841 | u32 data_len) | ||
842 | { | ||
843 | struct wl1271_rx_descriptor *desc = rx_data; | ||
844 | |||
845 | /* invalid packet */ | ||
846 | if (data_len < sizeof(*desc)) | ||
847 | return 0; | ||
848 | |||
849 | return data_len - sizeof(*desc); | ||
850 | } | ||
851 | |||
852 | static void wl18xx_tx_immediate_completion(struct wl1271 *wl) | ||
853 | { | ||
854 | wl18xx_tx_immediate_complete(wl); | ||
855 | } | ||
856 | |||
857 | static int wl18xx_set_host_cfg_bitmap(struct wl1271 *wl, u32 extra_mem_blk) | ||
858 | { | ||
859 | int ret; | ||
860 | u32 sdio_align_size = 0; | ||
861 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE | | ||
862 | HOST_IF_CFG_ADD_RX_ALIGNMENT; | ||
863 | |||
864 | /* Enable Tx SDIO padding */ | ||
865 | if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) { | ||
866 | host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; | ||
867 | sdio_align_size = WL12XX_BUS_BLOCK_SIZE; | ||
868 | } | ||
869 | |||
870 | /* Enable Rx SDIO padding */ | ||
871 | if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) { | ||
872 | host_cfg_bitmap |= HOST_IF_CFG_RX_PAD_TO_SDIO_BLK; | ||
873 | sdio_align_size = WL12XX_BUS_BLOCK_SIZE; | ||
874 | } | ||
875 | |||
876 | ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap, | ||
877 | sdio_align_size, extra_mem_blk, | ||
878 | WL18XX_HOST_IF_LEN_SIZE_FIELD); | ||
879 | if (ret < 0) | ||
880 | return ret; | ||
881 | |||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int wl18xx_hw_init(struct wl1271 *wl) | ||
886 | { | ||
887 | int ret; | ||
888 | struct wl18xx_priv *priv = wl->priv; | ||
889 | |||
890 | /* (re)init private structures. Relevant on recovery as well. */ | ||
891 | priv->last_fw_rls_idx = 0; | ||
892 | priv->extra_spare_vif_count = 0; | ||
893 | |||
894 | /* set the default amount of spare blocks in the bitmap */ | ||
895 | ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); | ||
896 | if (ret < 0) | ||
897 | return ret; | ||
898 | |||
899 | if (checksum_param) { | ||
900 | ret = wl18xx_acx_set_checksum_state(wl); | ||
901 | if (ret != 0) | ||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, | ||
909 | struct wl1271_tx_hw_descr *desc, | ||
910 | struct sk_buff *skb) | ||
911 | { | ||
912 | u32 ip_hdr_offset; | ||
913 | struct iphdr *ip_hdr; | ||
914 | |||
915 | if (!checksum_param) { | ||
916 | desc->wl18xx_checksum_data = 0; | ||
917 | return; | ||
918 | } | ||
919 | |||
920 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
921 | desc->wl18xx_checksum_data = 0; | ||
922 | return; | ||
923 | } | ||
924 | |||
925 | ip_hdr_offset = skb_network_header(skb) - skb_mac_header(skb); | ||
926 | if (WARN_ON(ip_hdr_offset >= (1<<7))) { | ||
927 | desc->wl18xx_checksum_data = 0; | ||
928 | return; | ||
929 | } | ||
930 | |||
931 | desc->wl18xx_checksum_data = ip_hdr_offset << 1; | ||
932 | |||
933 | /* FW is interested only in the LSB of the protocol TCP=0 UDP=1 */ | ||
934 | ip_hdr = (void *)skb_network_header(skb); | ||
935 | desc->wl18xx_checksum_data |= (ip_hdr->protocol & 0x01); | ||
936 | } | ||
937 | |||
938 | static void wl18xx_set_rx_csum(struct wl1271 *wl, | ||
939 | struct wl1271_rx_descriptor *desc, | ||
940 | struct sk_buff *skb) | ||
941 | { | ||
942 | if (desc->status & WL18XX_RX_CHECKSUM_MASK) | ||
943 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
944 | } | ||
945 | |||
946 | /* | ||
947 | * TODO: instead of having these two functions to get the rate mask, | ||
948 | * we should modify the wlvif->rate_set instead | ||
949 | */ | ||
950 | static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl, | ||
951 | struct wl12xx_vif *wlvif) | ||
952 | { | ||
953 | u32 hw_rate_set = wlvif->rate_set; | ||
954 | |||
955 | if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || | ||
956 | wlvif->channel_type == NL80211_CHAN_HT40PLUS) { | ||
957 | wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); | ||
958 | hw_rate_set |= CONF_TX_RATE_USE_WIDE_CHAN; | ||
959 | |||
960 | /* we don't support MIMO in wide-channel mode */ | ||
961 | hw_rate_set &= ~CONF_TX_MIMO_RATES; | ||
962 | } | ||
963 | |||
964 | return hw_rate_set; | ||
965 | } | ||
966 | |||
967 | static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | ||
968 | struct wl12xx_vif *wlvif) | ||
969 | { | ||
970 | if ((wlvif->channel_type == NL80211_CHAN_HT40MINUS || | ||
971 | wlvif->channel_type == NL80211_CHAN_HT40PLUS) && | ||
972 | !strcmp(ht_mode_param, "wide")) { | ||
973 | wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); | ||
974 | return CONF_TX_RATE_USE_WIDE_CHAN; | ||
975 | } else if (!strcmp(ht_mode_param, "mimo")) { | ||
976 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); | ||
977 | |||
978 | /* | ||
979 | * PG 1.0 has some problems with MCS_13, so disable it | ||
980 | * | ||
981 | * TODO: instead of hacking this in here, we should | ||
982 | * make it more general and change a bit in the | ||
983 | * wlvif->rate_set instead. | ||
984 | */ | ||
985 | if (wl->chip.id == CHIP_ID_185x_PG10) | ||
986 | return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13; | ||
987 | |||
988 | return CONF_TX_MIMO_RATES; | ||
989 | } else { | ||
990 | return 0; | ||
991 | } | ||
992 | } | ||
993 | |||
994 | static s8 wl18xx_get_pg_ver(struct wl1271 *wl) | ||
995 | { | ||
996 | u32 fuse; | ||
997 | |||
998 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | ||
999 | |||
1000 | fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); | ||
1001 | fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | ||
1002 | |||
1003 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
1004 | |||
1005 | return (s8)fuse; | ||
1006 | } | ||
1007 | |||
1008 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" | ||
1009 | static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev) | ||
1010 | { | ||
1011 | struct wl18xx_priv *priv = wl->priv; | ||
1012 | struct wlcore_conf_file *conf_file; | ||
1013 | const struct firmware *fw; | ||
1014 | int ret; | ||
1015 | |||
1016 | ret = request_firmware(&fw, WL18XX_CONF_FILE_NAME, dev); | ||
1017 | if (ret < 0) { | ||
1018 | wl1271_error("could not get configuration binary %s: %d", | ||
1019 | WL18XX_CONF_FILE_NAME, ret); | ||
1020 | goto out_fallback; | ||
1021 | } | ||
1022 | |||
1023 | if (fw->size != WL18XX_CONF_SIZE) { | ||
1024 | wl1271_error("configuration binary file size is wrong, " | ||
1025 | "expected %ld got %zd", | ||
1026 | WL18XX_CONF_SIZE, fw->size); | ||
1027 | ret = -EINVAL; | ||
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | conf_file = (struct wlcore_conf_file *) fw->data; | ||
1032 | |||
1033 | if (conf_file->header.magic != cpu_to_le32(WL18XX_CONF_MAGIC)) { | ||
1034 | wl1271_error("configuration binary file magic number mismatch, " | ||
1035 | "expected 0x%0x got 0x%0x", WL18XX_CONF_MAGIC, | ||
1036 | conf_file->header.magic); | ||
1037 | ret = -EINVAL; | ||
1038 | goto out; | ||
1039 | } | ||
1040 | |||
1041 | if (conf_file->header.version != cpu_to_le32(WL18XX_CONF_VERSION)) { | ||
1042 | wl1271_error("configuration binary file version not supported, " | ||
1043 | "expected 0x%08x got 0x%08x", | ||
1044 | WL18XX_CONF_VERSION, conf_file->header.version); | ||
1045 | ret = -EINVAL; | ||
1046 | goto out; | ||
1047 | } | ||
1048 | |||
1049 | memcpy(&wl->conf, &conf_file->core, sizeof(wl18xx_conf)); | ||
1050 | memcpy(&priv->conf, &conf_file->priv, sizeof(priv->conf)); | ||
1051 | |||
1052 | goto out; | ||
1053 | |||
1054 | out_fallback: | ||
1055 | wl1271_warning("falling back to default config"); | ||
1056 | |||
1057 | /* apply driver default configuration */ | ||
1058 | memcpy(&wl->conf, &wl18xx_conf, sizeof(wl18xx_conf)); | ||
1059 | /* apply default private configuration */ | ||
1060 | memcpy(&priv->conf, &wl18xx_default_priv_conf, sizeof(priv->conf)); | ||
1061 | |||
1062 | /* For now we just fallback */ | ||
1063 | return 0; | ||
1064 | |||
1065 | out: | ||
1066 | release_firmware(fw); | ||
1067 | return ret; | ||
1068 | } | ||
1069 | |||
1070 | static int wl18xx_plt_init(struct wl1271 *wl) | ||
1071 | { | ||
1072 | wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | ||
1073 | |||
1074 | return wl->ops->boot(wl); | ||
1075 | } | ||
1076 | |||
1077 | static void wl18xx_get_mac(struct wl1271 *wl) | ||
1078 | { | ||
1079 | u32 mac1, mac2; | ||
1080 | |||
1081 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | ||
1082 | |||
1083 | mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); | ||
1084 | mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); | ||
1085 | |||
1086 | /* these are the two parts of the BD_ADDR */ | ||
1087 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | ||
1088 | ((mac1 & 0xff000000) >> 24); | ||
1089 | wl->fuse_nic_addr = (mac1 & 0xffffff); | ||
1090 | |||
1091 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | ||
1092 | } | ||
1093 | |||
1094 | static int wl18xx_handle_static_data(struct wl1271 *wl, | ||
1095 | struct wl1271_static_data *static_data) | ||
1096 | { | ||
1097 | struct wl18xx_static_data_priv *static_data_priv = | ||
1098 | (struct wl18xx_static_data_priv *) static_data->priv; | ||
1099 | |||
1100 | wl1271_info("PHY firmware version: %s", static_data_priv->phy_version); | ||
1101 | |||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) | ||
1106 | { | ||
1107 | struct wl18xx_priv *priv = wl->priv; | ||
1108 | |||
1109 | /* If we have VIFs requiring extra spare, indulge them */ | ||
1110 | if (priv->extra_spare_vif_count) | ||
1111 | return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; | ||
1112 | |||
1113 | return WL18XX_TX_HW_BLOCK_SPARE; | ||
1114 | } | ||
1115 | |||
1116 | static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | ||
1117 | struct ieee80211_vif *vif, | ||
1118 | struct ieee80211_sta *sta, | ||
1119 | struct ieee80211_key_conf *key_conf) | ||
1120 | { | ||
1121 | struct wl18xx_priv *priv = wl->priv; | ||
1122 | bool change_spare = false; | ||
1123 | int ret; | ||
1124 | |||
1125 | /* | ||
1126 | * when adding the first or removing the last GEM/TKIP interface, | ||
1127 | * we have to adjust the number of spare blocks. | ||
1128 | */ | ||
1129 | change_spare = (key_conf->cipher == WL1271_CIPHER_SUITE_GEM || | ||
1130 | key_conf->cipher == WLAN_CIPHER_SUITE_TKIP) && | ||
1131 | ((priv->extra_spare_vif_count == 0 && cmd == SET_KEY) || | ||
1132 | (priv->extra_spare_vif_count == 1 && cmd == DISABLE_KEY)); | ||
1133 | |||
1134 | /* no need to change spare - just regular set_key */ | ||
1135 | if (!change_spare) | ||
1136 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1137 | |||
1138 | /* | ||
1139 | * stop the queues and flush to ensure the next packets are | ||
1140 | * in sync with FW spare block accounting | ||
1141 | */ | ||
1142 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); | ||
1143 | wl1271_tx_flush(wl); | ||
1144 | |||
1145 | ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1146 | if (ret < 0) | ||
1147 | goto out; | ||
1148 | |||
1149 | /* key is now set, change the spare blocks */ | ||
1150 | if (cmd == SET_KEY) { | ||
1151 | ret = wl18xx_set_host_cfg_bitmap(wl, | ||
1152 | WL18XX_TX_HW_EXTRA_BLOCK_SPARE); | ||
1153 | if (ret < 0) | ||
1154 | goto out; | ||
1155 | |||
1156 | priv->extra_spare_vif_count++; | ||
1157 | } else { | ||
1158 | ret = wl18xx_set_host_cfg_bitmap(wl, | ||
1159 | WL18XX_TX_HW_BLOCK_SPARE); | ||
1160 | if (ret < 0) | ||
1161 | goto out; | ||
1162 | |||
1163 | priv->extra_spare_vif_count--; | ||
1164 | } | ||
1165 | |||
1166 | out: | ||
1167 | wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); | ||
1168 | return ret; | ||
1169 | } | ||
1170 | |||
1171 | static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, | ||
1172 | u32 buf_offset, u32 last_len) | ||
1173 | { | ||
1174 | if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) { | ||
1175 | struct wl1271_tx_hw_descr *last_desc; | ||
1176 | |||
1177 | /* get the last TX HW descriptor written to the aggr buf */ | ||
1178 | last_desc = (struct wl1271_tx_hw_descr *)(wl->aggr_buf + | ||
1179 | buf_offset - last_len); | ||
1180 | |||
1181 | /* the last frame is padded up to an SDIO block */ | ||
1182 | last_desc->wl18xx_mem.ctrl &= ~WL18XX_TX_CTRL_NOT_PADDED; | ||
1183 | return ALIGN(buf_offset, WL12XX_BUS_BLOCK_SIZE); | ||
1184 | } | ||
1185 | |||
1186 | /* no modifications */ | ||
1187 | return buf_offset; | ||
1188 | } | ||
1189 | |||
1190 | static struct wlcore_ops wl18xx_ops = { | ||
1191 | .identify_chip = wl18xx_identify_chip, | ||
1192 | .boot = wl18xx_boot, | ||
1193 | .plt_init = wl18xx_plt_init, | ||
1194 | .trigger_cmd = wl18xx_trigger_cmd, | ||
1195 | .ack_event = wl18xx_ack_event, | ||
1196 | .calc_tx_blocks = wl18xx_calc_tx_blocks, | ||
1197 | .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, | ||
1198 | .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, | ||
1199 | .get_rx_buf_align = wl18xx_get_rx_buf_align, | ||
1200 | .get_rx_packet_len = wl18xx_get_rx_packet_len, | ||
1201 | .tx_immediate_compl = wl18xx_tx_immediate_completion, | ||
1202 | .tx_delayed_compl = NULL, | ||
1203 | .hw_init = wl18xx_hw_init, | ||
1204 | .set_tx_desc_csum = wl18xx_set_tx_desc_csum, | ||
1205 | .get_pg_ver = wl18xx_get_pg_ver, | ||
1206 | .set_rx_csum = wl18xx_set_rx_csum, | ||
1207 | .sta_get_ap_rate_mask = wl18xx_sta_get_ap_rate_mask, | ||
1208 | .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, | ||
1209 | .get_mac = wl18xx_get_mac, | ||
1210 | .debugfs_init = wl18xx_debugfs_add_files, | ||
1211 | .handle_static_data = wl18xx_handle_static_data, | ||
1212 | .get_spare_blocks = wl18xx_get_spare_blocks, | ||
1213 | .set_key = wl18xx_set_key, | ||
1214 | .pre_pkt_send = wl18xx_pre_pkt_send, | ||
1215 | }; | ||
1216 | |||
1217 | /* HT cap appropriate for wide channels */ | ||
1218 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { | ||
1219 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | ||
1220 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, | ||
1221 | .ht_supported = true, | ||
1222 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | ||
1223 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
1224 | .mcs = { | ||
1225 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
1226 | .rx_highest = cpu_to_le16(150), | ||
1227 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
1228 | }, | ||
1229 | }; | ||
1230 | |||
1231 | /* HT cap appropriate for SISO 20 */ | ||
1232 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | ||
1233 | .cap = IEEE80211_HT_CAP_SGI_20, | ||
1234 | .ht_supported = true, | ||
1235 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | ||
1236 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
1237 | .mcs = { | ||
1238 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
1239 | .rx_highest = cpu_to_le16(72), | ||
1240 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
1241 | }, | ||
1242 | }; | ||
1243 | |||
1244 | /* HT cap appropriate for MIMO rates in 20mhz channel */ | ||
1245 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | ||
1246 | .cap = IEEE80211_HT_CAP_SGI_20, | ||
1247 | .ht_supported = true, | ||
1248 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | ||
1249 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
1250 | .mcs = { | ||
1251 | .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
1252 | .rx_highest = cpu_to_le16(144), | ||
1253 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
1254 | }, | ||
1255 | }; | ||
1256 | |||
1257 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = { | ||
1258 | .cap = IEEE80211_HT_CAP_SGI_20, | ||
1259 | .ht_supported = true, | ||
1260 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | ||
1261 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
1262 | .mcs = { | ||
1263 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
1264 | .rx_highest = cpu_to_le16(72), | ||
1265 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
1266 | }, | ||
1267 | }; | ||
1268 | |||
1269 | static int __devinit wl18xx_probe(struct platform_device *pdev) | ||
1270 | { | ||
1271 | struct wl1271 *wl; | ||
1272 | struct ieee80211_hw *hw; | ||
1273 | struct wl18xx_priv *priv; | ||
1274 | int ret; | ||
1275 | |||
1276 | hw = wlcore_alloc_hw(sizeof(*priv)); | ||
1277 | if (IS_ERR(hw)) { | ||
1278 | wl1271_error("can't allocate hw"); | ||
1279 | ret = PTR_ERR(hw); | ||
1280 | goto out; | ||
1281 | } | ||
1282 | |||
1283 | wl = hw->priv; | ||
1284 | priv = wl->priv; | ||
1285 | wl->ops = &wl18xx_ops; | ||
1286 | wl->ptable = wl18xx_ptable; | ||
1287 | wl->rtable = wl18xx_rtable; | ||
1288 | wl->num_tx_desc = 32; | ||
1289 | wl->num_rx_desc = 16; | ||
1290 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; | ||
1291 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; | ||
1292 | wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; | ||
1293 | wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv); | ||
1294 | wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); | ||
1295 | wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); | ||
1296 | |||
1297 | if (!strcmp(ht_mode_param, "wide")) { | ||
1298 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1299 | &wl18xx_siso40_ht_cap, | ||
1300 | sizeof(wl18xx_siso40_ht_cap)); | ||
1301 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1302 | &wl18xx_siso40_ht_cap, | ||
1303 | sizeof(wl18xx_siso40_ht_cap)); | ||
1304 | } else if (!strcmp(ht_mode_param, "mimo")) { | ||
1305 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1306 | &wl18xx_mimo_ht_cap_2ghz, | ||
1307 | sizeof(wl18xx_mimo_ht_cap_2ghz)); | ||
1308 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1309 | &wl18xx_mimo_ht_cap_5ghz, | ||
1310 | sizeof(wl18xx_mimo_ht_cap_5ghz)); | ||
1311 | } else if (!strcmp(ht_mode_param, "siso20")) { | ||
1312 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1313 | &wl18xx_siso20_ht_cap, | ||
1314 | sizeof(wl18xx_siso20_ht_cap)); | ||
1315 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1316 | &wl18xx_siso20_ht_cap, | ||
1317 | sizeof(wl18xx_siso20_ht_cap)); | ||
1318 | } else { | ||
1319 | wl1271_error("invalid ht_mode '%s'", ht_mode_param); | ||
1320 | ret = -EINVAL; | ||
1321 | goto out_free; | ||
1322 | } | ||
1323 | |||
1324 | ret = wl18xx_conf_init(wl, &pdev->dev); | ||
1325 | if (ret < 0) | ||
1326 | goto out_free; | ||
1327 | |||
1328 | if (!strcmp(board_type_param, "fpga")) { | ||
1329 | priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX; | ||
1330 | } else if (!strcmp(board_type_param, "hdk")) { | ||
1331 | priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX; | ||
1332 | /* HACK! Just for now we hardcode HDK to 0x06 */ | ||
1333 | priv->conf.phy.low_band_component_type = 0x06; | ||
1334 | } else if (!strcmp(board_type_param, "dvp")) { | ||
1335 | priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX; | ||
1336 | } else if (!strcmp(board_type_param, "evb")) { | ||
1337 | priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX; | ||
1338 | } else if (!strcmp(board_type_param, "com8")) { | ||
1339 | priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX; | ||
1340 | /* HACK! Just for now we hardcode COM8 to 0x06 */ | ||
1341 | priv->conf.phy.low_band_component_type = 0x06; | ||
1342 | } else { | ||
1343 | wl1271_error("invalid board type '%s'", board_type_param); | ||
1344 | ret = -EINVAL; | ||
1345 | goto out_free; | ||
1346 | } | ||
1347 | |||
1348 | /* If the module param is set, update it in conf */ | ||
1349 | if (low_band_component_param != -1) | ||
1350 | priv->conf.phy.low_band_component = low_band_component_param; | ||
1351 | if (low_band_component_type_param != -1) | ||
1352 | priv->conf.phy.low_band_component_type = | ||
1353 | low_band_component_type_param; | ||
1354 | if (high_band_component_param != -1) | ||
1355 | priv->conf.phy.high_band_component = high_band_component_param; | ||
1356 | if (high_band_component_type_param != -1) | ||
1357 | priv->conf.phy.high_band_component_type = | ||
1358 | high_band_component_type_param; | ||
1359 | if (pwr_limit_reference_11_abg_param != -1) | ||
1360 | priv->conf.phy.pwr_limit_reference_11_abg = | ||
1361 | pwr_limit_reference_11_abg_param; | ||
1362 | if (n_antennas_2_param != -1) | ||
1363 | priv->conf.phy.number_of_assembled_ant2_4 = n_antennas_2_param; | ||
1364 | if (n_antennas_5_param != -1) | ||
1365 | priv->conf.phy.number_of_assembled_ant5 = n_antennas_5_param; | ||
1366 | if (dc2dc_param != -1) | ||
1367 | priv->conf.phy.external_pa_dc2dc = dc2dc_param; | ||
1368 | |||
1369 | if (!checksum_param) { | ||
1370 | wl18xx_ops.set_rx_csum = NULL; | ||
1371 | wl18xx_ops.init_vif = NULL; | ||
1372 | } | ||
1373 | |||
1374 | wl->enable_11a = enable_11a_param; | ||
1375 | |||
1376 | return wlcore_probe(wl, pdev); | ||
1377 | |||
1378 | out_free: | ||
1379 | wlcore_free_hw(wl); | ||
1380 | out: | ||
1381 | return ret; | ||
1382 | } | ||
1383 | |||
1384 | static const struct platform_device_id wl18xx_id_table[] __devinitconst = { | ||
1385 | { "wl18xx", 0 }, | ||
1386 | { } /* Terminating Entry */ | ||
1387 | }; | ||
1388 | MODULE_DEVICE_TABLE(platform, wl18xx_id_table); | ||
1389 | |||
1390 | static struct platform_driver wl18xx_driver = { | ||
1391 | .probe = wl18xx_probe, | ||
1392 | .remove = __devexit_p(wlcore_remove), | ||
1393 | .id_table = wl18xx_id_table, | ||
1394 | .driver = { | ||
1395 | .name = "wl18xx_driver", | ||
1396 | .owner = THIS_MODULE, | ||
1397 | } | ||
1398 | }; | ||
1399 | |||
1400 | static int __init wl18xx_init(void) | ||
1401 | { | ||
1402 | return platform_driver_register(&wl18xx_driver); | ||
1403 | } | ||
1404 | module_init(wl18xx_init); | ||
1405 | |||
1406 | static void __exit wl18xx_exit(void) | ||
1407 | { | ||
1408 | platform_driver_unregister(&wl18xx_driver); | ||
1409 | } | ||
1410 | module_exit(wl18xx_exit); | ||
1411 | |||
1412 | module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); | ||
1413 | MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20"); | ||
1414 | |||
1415 | module_param_named(board_type, board_type_param, charp, S_IRUSR); | ||
1416 | MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " | ||
1417 | "dvp"); | ||
1418 | |||
1419 | module_param_named(checksum, checksum_param, bool, S_IRUSR); | ||
1420 | MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)"); | ||
1421 | |||
1422 | module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR); | ||
1423 | MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)"); | ||
1424 | |||
1425 | module_param_named(dc2dc, dc2dc_param, int, S_IRUSR); | ||
1426 | MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)"); | ||
1427 | |||
1428 | module_param_named(n_antennas_2, n_antennas_2_param, int, S_IRUSR); | ||
1429 | MODULE_PARM_DESC(n_antennas_2, | ||
1430 | "Number of installed 2.4GHz antennas: 1 (default) or 2"); | ||
1431 | |||
1432 | module_param_named(n_antennas_5, n_antennas_5_param, int, S_IRUSR); | ||
1433 | MODULE_PARM_DESC(n_antennas_5, | ||
1434 | "Number of installed 5GHz antennas: 1 (default) or 2"); | ||
1435 | |||
1436 | module_param_named(low_band_component, low_band_component_param, int, | ||
1437 | S_IRUSR); | ||
1438 | MODULE_PARM_DESC(low_band_component, "Low band component: u8 " | ||
1439 | "(default is 0x01)"); | ||
1440 | |||
1441 | module_param_named(low_band_component_type, low_band_component_type_param, | ||
1442 | int, S_IRUSR); | ||
1443 | MODULE_PARM_DESC(low_band_component_type, "Low band component type: u8 " | ||
1444 | "(default is 0x05 or 0x06 depending on the board_type)"); | ||
1445 | |||
1446 | module_param_named(high_band_component, high_band_component_param, int, | ||
1447 | S_IRUSR); | ||
1448 | MODULE_PARM_DESC(high_band_component, "High band component: u8, " | ||
1449 | "(default is 0x01)"); | ||
1450 | |||
1451 | module_param_named(high_band_component_type, high_band_component_type_param, | ||
1452 | int, S_IRUSR); | ||
1453 | MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 " | ||
1454 | "(default is 0x09)"); | ||
1455 | |||
1456 | module_param_named(pwr_limit_reference_11_abg, | ||
1457 | pwr_limit_reference_11_abg_param, int, S_IRUSR); | ||
1458 | MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " | ||
1459 | "(default is 0xc8)"); | ||
1460 | |||
1461 | MODULE_LICENSE("GPL v2"); | ||
1462 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | ||
1463 | MODULE_FIRMWARE(WL18XX_FW_NAME); | ||
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h new file mode 100644 index 000000000000..937b71d8783f --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/reg.h | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * This file is part of wlcore | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __REG_H__ | ||
23 | #define __REG_H__ | ||
24 | |||
25 | #define WL18XX_REGISTERS_BASE 0x00800000 | ||
26 | #define WL18XX_CODE_BASE 0x00000000 | ||
27 | #define WL18XX_DATA_BASE 0x00400000 | ||
28 | #define WL18XX_DOUBLE_BUFFER_BASE 0x00600000 | ||
29 | #define WL18XX_MCU_KEY_SEARCH_BASE 0x00700000 | ||
30 | #define WL18XX_PHY_BASE 0x00900000 | ||
31 | #define WL18XX_TOP_OCP_BASE 0x00A00000 | ||
32 | #define WL18XX_PACKET_RAM_BASE 0x00B00000 | ||
33 | #define WL18XX_HOST_BASE 0x00C00000 | ||
34 | |||
35 | #define WL18XX_REGISTERS_DOWN_SIZE 0x0000B000 | ||
36 | |||
37 | #define WL18XX_REG_BOOT_PART_START 0x00802000 | ||
38 | #define WL18XX_REG_BOOT_PART_SIZE 0x00014578 | ||
39 | |||
40 | #define WL18XX_PHY_INIT_MEM_ADDR 0x80926000 | ||
41 | |||
42 | #define WL18XX_SDIO_WSPI_BASE (WL18XX_REGISTERS_BASE) | ||
43 | #define WL18XX_REG_CONFIG_BASE (WL18XX_REGISTERS_BASE + 0x02000) | ||
44 | #define WL18XX_WGCM_REGS_BASE (WL18XX_REGISTERS_BASE + 0x03000) | ||
45 | #define WL18XX_ENC_BASE (WL18XX_REGISTERS_BASE + 0x04000) | ||
46 | #define WL18XX_INTERRUPT_BASE (WL18XX_REGISTERS_BASE + 0x05000) | ||
47 | #define WL18XX_UART_BASE (WL18XX_REGISTERS_BASE + 0x06000) | ||
48 | #define WL18XX_WELP_BASE (WL18XX_REGISTERS_BASE + 0x07000) | ||
49 | #define WL18XX_TCP_CKSM_BASE (WL18XX_REGISTERS_BASE + 0x08000) | ||
50 | #define WL18XX_FIFO_BASE (WL18XX_REGISTERS_BASE + 0x09000) | ||
51 | #define WL18XX_OCP_BRIDGE_BASE (WL18XX_REGISTERS_BASE + 0x0A000) | ||
52 | #define WL18XX_PMAC_RX_BASE (WL18XX_REGISTERS_BASE + 0x14800) | ||
53 | #define WL18XX_PMAC_ACM_BASE (WL18XX_REGISTERS_BASE + 0x14C00) | ||
54 | #define WL18XX_PMAC_TX_BASE (WL18XX_REGISTERS_BASE + 0x15000) | ||
55 | #define WL18XX_PMAC_CSR_BASE (WL18XX_REGISTERS_BASE + 0x15400) | ||
56 | |||
57 | #define WL18XX_REG_ECPU_CONTROL (WL18XX_REGISTERS_BASE + 0x02004) | ||
58 | #define WL18XX_REG_INTERRUPT_NO_CLEAR (WL18XX_REGISTERS_BASE + 0x050E8) | ||
59 | #define WL18XX_REG_INTERRUPT_ACK (WL18XX_REGISTERS_BASE + 0x050F0) | ||
60 | #define WL18XX_REG_INTERRUPT_TRIG (WL18XX_REGISTERS_BASE + 0x5074) | ||
61 | #define WL18XX_REG_INTERRUPT_TRIG_H (WL18XX_REGISTERS_BASE + 0x5078) | ||
62 | #define WL18XX_REG_INTERRUPT_MASK (WL18XX_REGISTERS_BASE + 0x0050DC) | ||
63 | |||
64 | #define WL18XX_REG_CHIP_ID_B (WL18XX_REGISTERS_BASE + 0x01542C) | ||
65 | |||
66 | #define WL18XX_SLV_MEM_DATA (WL18XX_HOST_BASE + 0x0018) | ||
67 | #define WL18XX_SLV_REG_DATA (WL18XX_HOST_BASE + 0x0008) | ||
68 | |||
69 | /* Scratch Pad registers*/ | ||
70 | #define WL18XX_SCR_PAD0 (WL18XX_REGISTERS_BASE + 0x0154EC) | ||
71 | #define WL18XX_SCR_PAD1 (WL18XX_REGISTERS_BASE + 0x0154F0) | ||
72 | #define WL18XX_SCR_PAD2 (WL18XX_REGISTERS_BASE + 0x0154F4) | ||
73 | #define WL18XX_SCR_PAD3 (WL18XX_REGISTERS_BASE + 0x0154F8) | ||
74 | #define WL18XX_SCR_PAD4 (WL18XX_REGISTERS_BASE + 0x0154FC) | ||
75 | #define WL18XX_SCR_PAD4_SET (WL18XX_REGISTERS_BASE + 0x015504) | ||
76 | #define WL18XX_SCR_PAD4_CLR (WL18XX_REGISTERS_BASE + 0x015500) | ||
77 | #define WL18XX_SCR_PAD5 (WL18XX_REGISTERS_BASE + 0x015508) | ||
78 | #define WL18XX_SCR_PAD5_SET (WL18XX_REGISTERS_BASE + 0x015510) | ||
79 | #define WL18XX_SCR_PAD5_CLR (WL18XX_REGISTERS_BASE + 0x01550C) | ||
80 | #define WL18XX_SCR_PAD6 (WL18XX_REGISTERS_BASE + 0x015514) | ||
81 | #define WL18XX_SCR_PAD7 (WL18XX_REGISTERS_BASE + 0x015518) | ||
82 | #define WL18XX_SCR_PAD8 (WL18XX_REGISTERS_BASE + 0x01551C) | ||
83 | #define WL18XX_SCR_PAD9 (WL18XX_REGISTERS_BASE + 0x015520) | ||
84 | |||
85 | /* Spare registers*/ | ||
86 | #define WL18XX_SPARE_A1 (WL18XX_REGISTERS_BASE + 0x002194) | ||
87 | #define WL18XX_SPARE_A2 (WL18XX_REGISTERS_BASE + 0x002198) | ||
88 | #define WL18XX_SPARE_A3 (WL18XX_REGISTERS_BASE + 0x00219C) | ||
89 | #define WL18XX_SPARE_A4 (WL18XX_REGISTERS_BASE + 0x0021A0) | ||
90 | #define WL18XX_SPARE_A5 (WL18XX_REGISTERS_BASE + 0x0021A4) | ||
91 | #define WL18XX_SPARE_A6 (WL18XX_REGISTERS_BASE + 0x0021A8) | ||
92 | #define WL18XX_SPARE_A7 (WL18XX_REGISTERS_BASE + 0x0021AC) | ||
93 | #define WL18XX_SPARE_A8 (WL18XX_REGISTERS_BASE + 0x0021B0) | ||
94 | #define WL18XX_SPARE_B1 (WL18XX_REGISTERS_BASE + 0x015524) | ||
95 | #define WL18XX_SPARE_B2 (WL18XX_REGISTERS_BASE + 0x015528) | ||
96 | #define WL18XX_SPARE_B3 (WL18XX_REGISTERS_BASE + 0x01552C) | ||
97 | #define WL18XX_SPARE_B4 (WL18XX_REGISTERS_BASE + 0x015530) | ||
98 | #define WL18XX_SPARE_B5 (WL18XX_REGISTERS_BASE + 0x015534) | ||
99 | #define WL18XX_SPARE_B6 (WL18XX_REGISTERS_BASE + 0x015538) | ||
100 | #define WL18XX_SPARE_B7 (WL18XX_REGISTERS_BASE + 0x01553C) | ||
101 | #define WL18XX_SPARE_B8 (WL18XX_REGISTERS_BASE + 0x015540) | ||
102 | |||
103 | #define WL18XX_REG_COMMAND_MAILBOX_PTR (WL18XX_SCR_PAD0) | ||
104 | #define WL18XX_REG_EVENT_MAILBOX_PTR (WL18XX_SCR_PAD1) | ||
105 | #define WL18XX_EEPROMLESS_IND (WL18XX_SCR_PAD4) | ||
106 | |||
107 | #define WL18XX_WELP_ARM_COMMAND (WL18XX_REGISTERS_BASE + 0x7100) | ||
108 | #define WL18XX_ENABLE (WL18XX_REGISTERS_BASE + 0x01543C) | ||
109 | |||
110 | /* PRCM registers */ | ||
111 | #define PLATFORM_DETECTION 0xA0E3E0 | ||
112 | #define OCS_EN 0xA02080 | ||
113 | #define PRIMARY_CLK_DETECT 0xA020A6 | ||
114 | #define PLLSH_WCS_PLL_N 0xA02362 | ||
115 | #define PLLSH_WCS_PLL_M 0xA02360 | ||
116 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_1 0xA02364 | ||
117 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_2 0xA02366 | ||
118 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_1 0xA02368 | ||
119 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_2 0xA0236A | ||
120 | #define PLLSH_WCS_PLL_SWALLOW_EN 0xA0236C | ||
121 | #define PLLSH_WL_PLL_EN 0xA02392 | ||
122 | |||
123 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK 0xFFFF | ||
124 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK 0x007F | ||
125 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK 0xFFFF | ||
126 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK 0x000F | ||
127 | |||
128 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1 | ||
129 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12 | ||
130 | |||
131 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C | ||
132 | #define WL18XX_PG_VER_MASK 0x70 | ||
133 | #define WL18XX_PG_VER_OFFSET 4 | ||
134 | |||
135 | #define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 | ||
136 | #define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 | ||
137 | |||
138 | #define WL18XX_CMD_MBOX_ADDRESS 0xB007B4 | ||
139 | |||
140 | #define WL18XX_FW_STATUS_ADDR 0x50F8 | ||
141 | |||
142 | #define CHIP_ID_185x_PG10 (0x06030101) | ||
143 | #define CHIP_ID_185x_PG20 (0x06030111) | ||
144 | |||
145 | /* | ||
146 | * Host Command Interrupt. Setting this bit masks | ||
147 | * the interrupt that the host issues to inform | ||
148 | * the FW that it has sent a command | ||
149 | * to the Wlan hardware Command Mailbox. | ||
150 | */ | ||
151 | #define WL18XX_INTR_TRIG_CMD BIT(28) | ||
152 | |||
153 | /* | ||
154 | * Host Event Acknowlegde Interrupt. The host | ||
155 | * sets this bit to acknowledge that it received | ||
156 | * the unsolicited information from the event | ||
157 | * mailbox. | ||
158 | */ | ||
159 | #define WL18XX_INTR_TRIG_EVENT_ACK BIT(29) | ||
160 | |||
161 | /* | ||
162 | * To boot the firmware in PLT mode we need to write this value in | ||
163 | * SCR_PAD8 before starting. | ||
164 | */ | ||
165 | #define WL18XX_SCR_PAD8_PLT 0xBABABEBE | ||
166 | |||
167 | enum { | ||
168 | COMPONENT_NO_SWITCH = 0x0, | ||
169 | COMPONENT_2_WAY_SWITCH = 0x1, | ||
170 | COMPONENT_3_WAY_SWITCH = 0x2, | ||
171 | COMPONENT_MATCHING = 0x3, | ||
172 | }; | ||
173 | |||
174 | enum { | ||
175 | FEM_NONE = 0x0, | ||
176 | FEM_VENDOR_1 = 0x1, | ||
177 | FEM_VENDOR_2 = 0x2, | ||
178 | FEM_VENDOR_3 = 0x3, | ||
179 | }; | ||
180 | |||
181 | enum { | ||
182 | BOARD_TYPE_EVB_18XX = 0, | ||
183 | BOARD_TYPE_DVP_18XX = 1, | ||
184 | BOARD_TYPE_HDK_18XX = 2, | ||
185 | BOARD_TYPE_FPGA_18XX = 3, | ||
186 | BOARD_TYPE_COM8_18XX = 4, | ||
187 | |||
188 | NUM_BOARD_TYPES, | ||
189 | }; | ||
190 | |||
191 | #endif /* __REG_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c new file mode 100644 index 000000000000..5b1fb10d9fd7 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/tx.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "../wlcore/wlcore.h" | ||
23 | #include "../wlcore/cmd.h" | ||
24 | #include "../wlcore/debug.h" | ||
25 | #include "../wlcore/acx.h" | ||
26 | #include "../wlcore/tx.h" | ||
27 | |||
28 | #include "wl18xx.h" | ||
29 | #include "tx.h" | ||
30 | |||
31 | static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) | ||
32 | { | ||
33 | struct ieee80211_tx_info *info; | ||
34 | struct sk_buff *skb; | ||
35 | int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK; | ||
36 | bool tx_success; | ||
37 | |||
38 | /* check for id legality */ | ||
39 | if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) { | ||
40 | wl1271_warning("illegal id in tx completion: %d", id); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | /* a zero bit indicates Tx success */ | ||
45 | tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); | ||
46 | |||
47 | |||
48 | skb = wl->tx_frames[id]; | ||
49 | info = IEEE80211_SKB_CB(skb); | ||
50 | |||
51 | if (wl12xx_is_dummy_packet(wl, skb)) { | ||
52 | wl1271_free_tx_id(wl, id); | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | /* update the TX status info */ | ||
57 | if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) | ||
58 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
59 | |||
60 | /* no real data about Tx completion */ | ||
61 | info->status.rates[0].idx = -1; | ||
62 | info->status.rates[0].count = 0; | ||
63 | info->status.rates[0].flags = 0; | ||
64 | info->status.ack_signal = -1; | ||
65 | |||
66 | if (!tx_success) | ||
67 | wl->stats.retry_count++; | ||
68 | |||
69 | /* | ||
70 | * TODO: update sequence number for encryption? seems to be | ||
71 | * unsupported for now. needed for recovery with encryption. | ||
72 | */ | ||
73 | |||
74 | /* remove private header from packet */ | ||
75 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | ||
76 | |||
77 | /* remove TKIP header space if present */ | ||
78 | if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && | ||
79 | info->control.hw_key && | ||
80 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
81 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
82 | memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen); | ||
83 | skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); | ||
84 | } | ||
85 | |||
86 | wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d", | ||
87 | id, skb, tx_success); | ||
88 | |||
89 | /* return the packet to the stack */ | ||
90 | skb_queue_tail(&wl->deferred_tx_queue, skb); | ||
91 | queue_work(wl->freezable_wq, &wl->netstack_work); | ||
92 | wl1271_free_tx_id(wl, id); | ||
93 | } | ||
94 | |||
95 | void wl18xx_tx_immediate_complete(struct wl1271 *wl) | ||
96 | { | ||
97 | struct wl18xx_fw_status_priv *status_priv = | ||
98 | (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; | ||
99 | struct wl18xx_priv *priv = wl->priv; | ||
100 | u8 i; | ||
101 | |||
102 | /* nothing to do here */ | ||
103 | if (priv->last_fw_rls_idx == status_priv->fw_release_idx) | ||
104 | return; | ||
105 | |||
106 | /* freed Tx descriptors */ | ||
107 | wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d", | ||
108 | priv->last_fw_rls_idx, status_priv->fw_release_idx); | ||
109 | |||
110 | if (status_priv->fw_release_idx >= WL18XX_FW_MAX_TX_STATUS_DESC) { | ||
111 | wl1271_error("invalid desc release index %d", | ||
112 | status_priv->fw_release_idx); | ||
113 | WARN_ON(1); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | for (i = priv->last_fw_rls_idx; | ||
118 | i != status_priv->fw_release_idx; | ||
119 | i = (i + 1) % WL18XX_FW_MAX_TX_STATUS_DESC) { | ||
120 | wl18xx_tx_complete_packet(wl, | ||
121 | status_priv->released_tx_desc[i]); | ||
122 | |||
123 | wl->tx_results_count++; | ||
124 | } | ||
125 | |||
126 | priv->last_fw_rls_idx = status_priv->fw_release_idx; | ||
127 | } | ||
diff --git a/drivers/net/wireless/ti/wl18xx/tx.h b/drivers/net/wireless/ti/wl18xx/tx.h new file mode 100644 index 000000000000..ccddc548e44a --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/tx.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_TX_H__ | ||
23 | #define __WL18XX_TX_H__ | ||
24 | |||
25 | #include "../wlcore/wlcore.h" | ||
26 | |||
27 | #define WL18XX_TX_HW_BLOCK_SPARE 1 | ||
28 | /* for special cases - namely, TKIP and GEM */ | ||
29 | #define WL18XX_TX_HW_EXTRA_BLOCK_SPARE 2 | ||
30 | #define WL18XX_TX_HW_BLOCK_SIZE 268 | ||
31 | |||
32 | #define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F | ||
33 | #define WL18XX_TX_STATUS_STAT_BIT_IDX 7 | ||
34 | |||
35 | /* Indicates this TX HW frame is not padded to SDIO block size */ | ||
36 | #define WL18XX_TX_CTRL_NOT_PADDED BIT(7) | ||
37 | |||
38 | /* | ||
39 | * The FW uses a special bit to indicate a wide channel should be used in | ||
40 | * the rate policy. | ||
41 | */ | ||
42 | #define CONF_TX_RATE_USE_WIDE_CHAN BIT(31) | ||
43 | |||
44 | void wl18xx_tx_immediate_complete(struct wl1271 *wl); | ||
45 | |||
46 | #endif /* __WL12XX_TX_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h new file mode 100644 index 000000000000..bc67a4750615 --- /dev/null +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * This file is part of wl18xx | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __WL18XX_PRIV_H__ | ||
23 | #define __WL18XX_PRIV_H__ | ||
24 | |||
25 | #include "conf.h" | ||
26 | |||
27 | #define WL18XX_CMD_MAX_SIZE 740 | ||
28 | |||
29 | struct wl18xx_priv { | ||
30 | /* buffer for sending commands to FW */ | ||
31 | u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; | ||
32 | |||
33 | struct wl18xx_priv_conf conf; | ||
34 | |||
35 | /* Index of last released Tx desc in FW */ | ||
36 | u8 last_fw_rls_idx; | ||
37 | |||
38 | /* number of VIFs requiring extra spare mem-blocks */ | ||
39 | int extra_spare_vif_count; | ||
40 | }; | ||
41 | |||
42 | #define WL18XX_FW_MAX_TX_STATUS_DESC 33 | ||
43 | |||
44 | struct wl18xx_fw_status_priv { | ||
45 | /* | ||
46 | * Index in released_tx_desc for first byte that holds | ||
47 | * released tx host desc | ||
48 | */ | ||
49 | u8 fw_release_idx; | ||
50 | |||
51 | /* | ||
52 | * Array of host Tx descriptors, where fw_release_idx | ||
53 | * indicated the first released idx. | ||
54 | */ | ||
55 | u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC]; | ||
56 | |||
57 | u8 padding[2]; | ||
58 | }; | ||
59 | |||
60 | #define WL18XX_PHY_VERSION_MAX_LEN 20 | ||
61 | |||
62 | struct wl18xx_static_data_priv { | ||
63 | char phy_version[WL18XX_PHY_VERSION_MAX_LEN]; | ||
64 | }; | ||
65 | |||
66 | struct wl18xx_clk_cfg { | ||
67 | u32 n; | ||
68 | u32 m; | ||
69 | u32 p; | ||
70 | u32 q; | ||
71 | bool swallow; | ||
72 | }; | ||
73 | |||
74 | enum { | ||
75 | CLOCK_CONFIG_16_2_M = 1, | ||
76 | CLOCK_CONFIG_16_368_M, | ||
77 | CLOCK_CONFIG_16_8_M, | ||
78 | CLOCK_CONFIG_19_2_M, | ||
79 | CLOCK_CONFIG_26_M, | ||
80 | CLOCK_CONFIG_32_736_M, | ||
81 | CLOCK_CONFIG_33_6_M, | ||
82 | CLOCK_CONFIG_38_468_M, | ||
83 | CLOCK_CONFIG_52_M, | ||
84 | |||
85 | NUM_CLOCK_CONFIGS, | ||
86 | }; | ||
87 | |||
88 | #endif /* __WL18XX_PRIV_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index f3d6fa508269..b9ec42c83757 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -86,6 +86,7 @@ out: | |||
86 | kfree(auth); | 86 | kfree(auth); |
87 | return ret; | 87 | return ret; |
88 | } | 88 | } |
89 | EXPORT_SYMBOL_GPL(wl1271_acx_sleep_auth); | ||
89 | 90 | ||
90 | int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 91 | int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
91 | int power) | 92 | int power) |
@@ -708,14 +709,14 @@ out: | |||
708 | return ret; | 709 | return ret; |
709 | } | 710 | } |
710 | 711 | ||
711 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | 712 | int wl1271_acx_statistics(struct wl1271 *wl, void *stats) |
712 | { | 713 | { |
713 | int ret; | 714 | int ret; |
714 | 715 | ||
715 | wl1271_debug(DEBUG_ACX, "acx statistics"); | 716 | wl1271_debug(DEBUG_ACX, "acx statistics"); |
716 | 717 | ||
717 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, | 718 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, |
718 | sizeof(*stats)); | 719 | wl->stats.fw_stats_len); |
719 | if (ret < 0) { | 720 | if (ret < 0) { |
720 | wl1271_warning("acx statistics failed: %d", ret); | 721 | wl1271_warning("acx statistics failed: %d", ret); |
721 | return -ENOMEM; | 722 | return -ENOMEM; |
@@ -997,6 +998,7 @@ out: | |||
997 | kfree(mem_conf); | 998 | kfree(mem_conf); |
998 | return ret; | 999 | return ret; |
999 | } | 1000 | } |
1001 | EXPORT_SYMBOL_GPL(wl12xx_acx_mem_cfg); | ||
1000 | 1002 | ||
1001 | int wl1271_acx_init_mem_config(struct wl1271 *wl) | 1003 | int wl1271_acx_init_mem_config(struct wl1271 *wl) |
1002 | { | 1004 | { |
@@ -1027,6 +1029,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) | |||
1027 | 1029 | ||
1028 | return 0; | 1030 | return 0; |
1029 | } | 1031 | } |
1032 | EXPORT_SYMBOL_GPL(wl1271_acx_init_mem_config); | ||
1030 | 1033 | ||
1031 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) | 1034 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) |
1032 | { | 1035 | { |
@@ -1150,6 +1153,7 @@ out: | |||
1150 | kfree(acx); | 1153 | kfree(acx); |
1151 | return ret; | 1154 | return ret; |
1152 | } | 1155 | } |
1156 | EXPORT_SYMBOL_GPL(wl1271_acx_pm_config); | ||
1153 | 1157 | ||
1154 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1158 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1155 | bool enable) | 1159 | bool enable) |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index e6a74869a5ff..c0181258b722 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -51,21 +51,18 @@ | |||
51 | #define WL1271_ACX_INTR_TRACE_A BIT(7) | 51 | #define WL1271_ACX_INTR_TRACE_A BIT(7) |
52 | /* Trace message on MBOX #B */ | 52 | /* Trace message on MBOX #B */ |
53 | #define WL1271_ACX_INTR_TRACE_B BIT(8) | 53 | #define WL1271_ACX_INTR_TRACE_B BIT(8) |
54 | /* SW FW Initiated interrupt Watchdog timer expiration */ | ||
55 | #define WL1271_ACX_SW_INTR_WATCHDOG BIT(9) | ||
54 | 56 | ||
55 | #define WL1271_ACX_INTR_ALL 0xFFFFFFFF | 57 | #define WL1271_ACX_INTR_ALL 0xFFFFFFFF |
56 | #define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ | 58 | |
57 | WL1271_ACX_INTR_INIT_COMPLETE | \ | 59 | /* all possible interrupts - only appropriate ones will be masked in */ |
58 | WL1271_ACX_INTR_EVENT_A | \ | 60 | #define WLCORE_ALL_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ |
59 | WL1271_ACX_INTR_EVENT_B | \ | 61 | WL1271_ACX_INTR_EVENT_A | \ |
60 | WL1271_ACX_INTR_CMD_COMPLETE | \ | 62 | WL1271_ACX_INTR_EVENT_B | \ |
61 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 63 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
62 | WL1271_ACX_INTR_DATA) | 64 | WL1271_ACX_INTR_DATA | \ |
63 | 65 | WL1271_ACX_SW_INTR_WATCHDOG) | |
64 | #define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ | ||
65 | WL1271_ACX_INTR_EVENT_A | \ | ||
66 | WL1271_ACX_INTR_EVENT_B | \ | ||
67 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
68 | WL1271_ACX_INTR_DATA) | ||
69 | 66 | ||
70 | /* Target's information element */ | 67 | /* Target's information element */ |
71 | struct acx_header { | 68 | struct acx_header { |
@@ -417,228 +414,6 @@ struct acx_ctsprotect { | |||
417 | u8 padding[2]; | 414 | u8 padding[2]; |
418 | } __packed; | 415 | } __packed; |
419 | 416 | ||
420 | struct acx_tx_statistics { | ||
421 | __le32 internal_desc_overflow; | ||
422 | } __packed; | ||
423 | |||
424 | struct acx_rx_statistics { | ||
425 | __le32 out_of_mem; | ||
426 | __le32 hdr_overflow; | ||
427 | __le32 hw_stuck; | ||
428 | __le32 dropped; | ||
429 | __le32 fcs_err; | ||
430 | __le32 xfr_hint_trig; | ||
431 | __le32 path_reset; | ||
432 | __le32 reset_counter; | ||
433 | } __packed; | ||
434 | |||
435 | struct acx_dma_statistics { | ||
436 | __le32 rx_requested; | ||
437 | __le32 rx_errors; | ||
438 | __le32 tx_requested; | ||
439 | __le32 tx_errors; | ||
440 | } __packed; | ||
441 | |||
442 | struct acx_isr_statistics { | ||
443 | /* host command complete */ | ||
444 | __le32 cmd_cmplt; | ||
445 | |||
446 | /* fiqisr() */ | ||
447 | __le32 fiqs; | ||
448 | |||
449 | /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ | ||
450 | __le32 rx_headers; | ||
451 | |||
452 | /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ | ||
453 | __le32 rx_completes; | ||
454 | |||
455 | /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ | ||
456 | __le32 rx_mem_overflow; | ||
457 | |||
458 | /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ | ||
459 | __le32 rx_rdys; | ||
460 | |||
461 | /* irqisr() */ | ||
462 | __le32 irqs; | ||
463 | |||
464 | /* (INT_STS_ND & INT_TRIG_TX_PROC) */ | ||
465 | __le32 tx_procs; | ||
466 | |||
467 | /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ | ||
468 | __le32 decrypt_done; | ||
469 | |||
470 | /* (INT_STS_ND & INT_TRIG_DMA0) */ | ||
471 | __le32 dma0_done; | ||
472 | |||
473 | /* (INT_STS_ND & INT_TRIG_DMA1) */ | ||
474 | __le32 dma1_done; | ||
475 | |||
476 | /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ | ||
477 | __le32 tx_exch_complete; | ||
478 | |||
479 | /* (INT_STS_ND & INT_TRIG_COMMAND) */ | ||
480 | __le32 commands; | ||
481 | |||
482 | /* (INT_STS_ND & INT_TRIG_RX_PROC) */ | ||
483 | __le32 rx_procs; | ||
484 | |||
485 | /* (INT_STS_ND & INT_TRIG_PM_802) */ | ||
486 | __le32 hw_pm_mode_changes; | ||
487 | |||
488 | /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ | ||
489 | __le32 host_acknowledges; | ||
490 | |||
491 | /* (INT_STS_ND & INT_TRIG_PM_PCI) */ | ||
492 | __le32 pci_pm; | ||
493 | |||
494 | /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ | ||
495 | __le32 wakeups; | ||
496 | |||
497 | /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ | ||
498 | __le32 low_rssi; | ||
499 | } __packed; | ||
500 | |||
501 | struct acx_wep_statistics { | ||
502 | /* WEP address keys configured */ | ||
503 | __le32 addr_key_count; | ||
504 | |||
505 | /* default keys configured */ | ||
506 | __le32 default_key_count; | ||
507 | |||
508 | __le32 reserved; | ||
509 | |||
510 | /* number of times that WEP key not found on lookup */ | ||
511 | __le32 key_not_found; | ||
512 | |||
513 | /* number of times that WEP key decryption failed */ | ||
514 | __le32 decrypt_fail; | ||
515 | |||
516 | /* WEP packets decrypted */ | ||
517 | __le32 packets; | ||
518 | |||
519 | /* WEP decrypt interrupts */ | ||
520 | __le32 interrupt; | ||
521 | } __packed; | ||
522 | |||
523 | #define ACX_MISSED_BEACONS_SPREAD 10 | ||
524 | |||
525 | struct acx_pwr_statistics { | ||
526 | /* the amount of enters into power save mode (both PD & ELP) */ | ||
527 | __le32 ps_enter; | ||
528 | |||
529 | /* the amount of enters into ELP mode */ | ||
530 | __le32 elp_enter; | ||
531 | |||
532 | /* the amount of missing beacon interrupts to the host */ | ||
533 | __le32 missing_bcns; | ||
534 | |||
535 | /* the amount of wake on host-access times */ | ||
536 | __le32 wake_on_host; | ||
537 | |||
538 | /* the amount of wake on timer-expire */ | ||
539 | __le32 wake_on_timer_exp; | ||
540 | |||
541 | /* the number of packets that were transmitted with PS bit set */ | ||
542 | __le32 tx_with_ps; | ||
543 | |||
544 | /* the number of packets that were transmitted with PS bit clear */ | ||
545 | __le32 tx_without_ps; | ||
546 | |||
547 | /* the number of received beacons */ | ||
548 | __le32 rcvd_beacons; | ||
549 | |||
550 | /* the number of entering into PowerOn (power save off) */ | ||
551 | __le32 power_save_off; | ||
552 | |||
553 | /* the number of entries into power save mode */ | ||
554 | __le16 enable_ps; | ||
555 | |||
556 | /* | ||
557 | * the number of exits from power save, not including failed PS | ||
558 | * transitions | ||
559 | */ | ||
560 | __le16 disable_ps; | ||
561 | |||
562 | /* | ||
563 | * the number of times the TSF counter was adjusted because | ||
564 | * of drift | ||
565 | */ | ||
566 | __le32 fix_tsf_ps; | ||
567 | |||
568 | /* Gives statistics about the spread continuous missed beacons. | ||
569 | * The 16 LSB are dedicated for the PS mode. | ||
570 | * The 16 MSB are dedicated for the PS mode. | ||
571 | * cont_miss_bcns_spread[0] - single missed beacon. | ||
572 | * cont_miss_bcns_spread[1] - two continuous missed beacons. | ||
573 | * cont_miss_bcns_spread[2] - three continuous missed beacons. | ||
574 | * ... | ||
575 | * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. | ||
576 | */ | ||
577 | __le32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; | ||
578 | |||
579 | /* the number of beacons in awake mode */ | ||
580 | __le32 rcvd_awake_beacons; | ||
581 | } __packed; | ||
582 | |||
583 | struct acx_mic_statistics { | ||
584 | __le32 rx_pkts; | ||
585 | __le32 calc_failure; | ||
586 | } __packed; | ||
587 | |||
588 | struct acx_aes_statistics { | ||
589 | __le32 encrypt_fail; | ||
590 | __le32 decrypt_fail; | ||
591 | __le32 encrypt_packets; | ||
592 | __le32 decrypt_packets; | ||
593 | __le32 encrypt_interrupt; | ||
594 | __le32 decrypt_interrupt; | ||
595 | } __packed; | ||
596 | |||
597 | struct acx_event_statistics { | ||
598 | __le32 heart_beat; | ||
599 | __le32 calibration; | ||
600 | __le32 rx_mismatch; | ||
601 | __le32 rx_mem_empty; | ||
602 | __le32 rx_pool; | ||
603 | __le32 oom_late; | ||
604 | __le32 phy_transmit_error; | ||
605 | __le32 tx_stuck; | ||
606 | } __packed; | ||
607 | |||
608 | struct acx_ps_statistics { | ||
609 | __le32 pspoll_timeouts; | ||
610 | __le32 upsd_timeouts; | ||
611 | __le32 upsd_max_sptime; | ||
612 | __le32 upsd_max_apturn; | ||
613 | __le32 pspoll_max_apturn; | ||
614 | __le32 pspoll_utilization; | ||
615 | __le32 upsd_utilization; | ||
616 | } __packed; | ||
617 | |||
618 | struct acx_rxpipe_statistics { | ||
619 | __le32 rx_prep_beacon_drop; | ||
620 | __le32 descr_host_int_trig_rx_data; | ||
621 | __le32 beacon_buffer_thres_host_int_trig_rx_data; | ||
622 | __le32 missed_beacon_host_int_trig_rx_data; | ||
623 | __le32 tx_xfr_host_int_trig_rx_data; | ||
624 | } __packed; | ||
625 | |||
626 | struct acx_statistics { | ||
627 | struct acx_header header; | ||
628 | |||
629 | struct acx_tx_statistics tx; | ||
630 | struct acx_rx_statistics rx; | ||
631 | struct acx_dma_statistics dma; | ||
632 | struct acx_isr_statistics isr; | ||
633 | struct acx_wep_statistics wep; | ||
634 | struct acx_pwr_statistics pwr; | ||
635 | struct acx_aes_statistics aes; | ||
636 | struct acx_mic_statistics mic; | ||
637 | struct acx_event_statistics event; | ||
638 | struct acx_ps_statistics ps; | ||
639 | struct acx_rxpipe_statistics rxpipe; | ||
640 | } __packed; | ||
641 | |||
642 | struct acx_rate_class { | 417 | struct acx_rate_class { |
643 | __le32 enabled_rates; | 418 | __le32 enabled_rates; |
644 | u8 short_retry_limit; | 419 | u8 short_retry_limit; |
@@ -828,6 +603,8 @@ struct wl1271_acx_keep_alive_config { | |||
828 | #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) | 603 | #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) |
829 | #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) | 604 | #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) |
830 | #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) | 605 | #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) |
606 | #define HOST_IF_CFG_RX_PAD_TO_SDIO_BLK BIT(4) | ||
607 | #define HOST_IF_CFG_ADD_RX_ALIGNMENT BIT(6) | ||
831 | 608 | ||
832 | enum { | 609 | enum { |
833 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, | 610 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, |
@@ -946,7 +723,7 @@ struct wl1271_acx_ht_information { | |||
946 | u8 padding[2]; | 723 | u8 padding[2]; |
947 | } __packed; | 724 | } __packed; |
948 | 725 | ||
949 | #define RX_BA_MAX_SESSIONS 2 | 726 | #define RX_BA_MAX_SESSIONS 3 |
950 | 727 | ||
951 | struct wl1271_acx_ba_initiator_policy { | 728 | struct wl1271_acx_ba_initiator_policy { |
952 | struct acx_header header; | 729 | struct acx_header header; |
@@ -1243,6 +1020,7 @@ enum { | |||
1243 | ACX_CONFIG_HANGOVER = 0x0042, | 1020 | ACX_CONFIG_HANGOVER = 0x0042, |
1244 | ACX_FEATURE_CFG = 0x0043, | 1021 | ACX_FEATURE_CFG = 0x0043, |
1245 | ACX_PROTECTION_CFG = 0x0044, | 1022 | ACX_PROTECTION_CFG = 0x0044, |
1023 | ACX_CHECKSUM_CONFIG = 0x0045, | ||
1246 | }; | 1024 | }; |
1247 | 1025 | ||
1248 | 1026 | ||
@@ -1281,7 +1059,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1281 | enum acx_preamble_type preamble); | 1059 | enum acx_preamble_type preamble); |
1282 | int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1060 | int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1283 | enum acx_ctsprotect_type ctsprotect); | 1061 | enum acx_ctsprotect_type ctsprotect); |
1284 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1062 | int wl1271_acx_statistics(struct wl1271 *wl, void *stats); |
1285 | int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 1063 | int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
1286 | int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, | 1064 | int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, |
1287 | u8 idx); | 1065 | u8 idx); |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 9b98230f84ce..0fda500c01c9 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -45,10 +45,17 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); | 45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); |
46 | } | 46 | } |
47 | 47 | ||
48 | static int wlcore_parse_fw_ver(struct wl1271 *wl) | 48 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, |
49 | struct wl1271_static_data *static_data) | ||
49 | { | 50 | { |
50 | int ret; | 51 | int ret; |
51 | 52 | ||
53 | strncpy(wl->chip.fw_ver_str, static_data->fw_version, | ||
54 | sizeof(wl->chip.fw_ver_str)); | ||
55 | |||
56 | /* make sure the string is NULL-terminated */ | ||
57 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; | ||
58 | |||
52 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", | 59 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", |
53 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], | 60 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], |
54 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], | 61 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], |
@@ -57,43 +64,43 @@ static int wlcore_parse_fw_ver(struct wl1271 *wl) | |||
57 | if (ret != 5) { | 64 | if (ret != 5) { |
58 | wl1271_warning("fw version incorrect value"); | 65 | wl1271_warning("fw version incorrect value"); |
59 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); | 66 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); |
60 | return -EINVAL; | 67 | ret = -EINVAL; |
68 | goto out; | ||
61 | } | 69 | } |
62 | 70 | ||
63 | ret = wlcore_identify_fw(wl); | 71 | ret = wlcore_identify_fw(wl); |
64 | if (ret < 0) | 72 | if (ret < 0) |
65 | return ret; | 73 | goto out; |
66 | 74 | out: | |
67 | return 0; | 75 | return ret; |
68 | } | 76 | } |
69 | 77 | ||
70 | static int wlcore_boot_fw_version(struct wl1271 *wl) | 78 | static int wlcore_boot_static_data(struct wl1271 *wl) |
71 | { | 79 | { |
72 | struct wl1271_static_data *static_data; | 80 | struct wl1271_static_data *static_data; |
81 | size_t len = sizeof(*static_data) + wl->static_data_priv_len; | ||
73 | int ret; | 82 | int ret; |
74 | 83 | ||
75 | static_data = kmalloc(sizeof(*static_data), GFP_KERNEL | GFP_DMA); | 84 | static_data = kmalloc(len, GFP_KERNEL); |
76 | if (!static_data) { | 85 | if (!static_data) { |
77 | wl1271_error("Couldn't allocate memory for static data!"); | 86 | ret = -ENOMEM; |
78 | return -ENOMEM; | 87 | goto out; |
79 | } | 88 | } |
80 | 89 | ||
81 | wl1271_read(wl, wl->cmd_box_addr, static_data, sizeof(*static_data), | 90 | wl1271_read(wl, wl->cmd_box_addr, static_data, len, false); |
82 | false); | ||
83 | |||
84 | strncpy(wl->chip.fw_ver_str, static_data->fw_version, | ||
85 | sizeof(wl->chip.fw_ver_str)); | ||
86 | |||
87 | kfree(static_data); | ||
88 | 91 | ||
89 | /* make sure the string is NULL-terminated */ | 92 | ret = wlcore_boot_parse_fw_ver(wl, static_data); |
90 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; | 93 | if (ret < 0) |
94 | goto out_free; | ||
91 | 95 | ||
92 | ret = wlcore_parse_fw_ver(wl); | 96 | ret = wlcore_handle_static_data(wl, static_data); |
93 | if (ret < 0) | 97 | if (ret < 0) |
94 | return ret; | 98 | goto out_free; |
95 | 99 | ||
96 | return 0; | 100 | out_free: |
101 | kfree(static_data); | ||
102 | out: | ||
103 | return ret; | ||
97 | } | 104 | } |
98 | 105 | ||
99 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | 106 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, |
@@ -204,8 +211,10 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
204 | u32 dest_addr, val; | 211 | u32 dest_addr, val; |
205 | u8 *nvs_ptr, *nvs_aligned; | 212 | u8 *nvs_ptr, *nvs_aligned; |
206 | 213 | ||
207 | if (wl->nvs == NULL) | 214 | if (wl->nvs == NULL) { |
215 | wl1271_error("NVS file is needed during boot"); | ||
208 | return -ENODEV; | 216 | return -ENODEV; |
217 | } | ||
209 | 218 | ||
210 | if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) { | 219 | if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) { |
211 | struct wl1271_nvs_file *nvs = | 220 | struct wl1271_nvs_file *nvs = |
@@ -400,9 +409,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
400 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | 409 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", |
401 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 410 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
402 | 411 | ||
403 | ret = wlcore_boot_fw_version(wl); | 412 | ret = wlcore_boot_static_data(wl); |
404 | if (ret < 0) { | 413 | if (ret < 0) { |
405 | wl1271_error("couldn't boot firmware"); | 414 | wl1271_error("error getting static data"); |
406 | return ret; | 415 | return ret; |
407 | } | 416 | } |
408 | 417 | ||
diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h index 094981dd2227..a525225f990c 100644 --- a/drivers/net/wireless/ti/wlcore/boot.h +++ b/drivers/net/wireless/ti/wlcore/boot.h | |||
@@ -40,6 +40,7 @@ struct wl1271_static_data { | |||
40 | u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; | 40 | u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; |
41 | u32 hw_version; | 41 | u32 hw_version; |
42 | u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; | 42 | u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; |
43 | u8 priv[0]; | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | /* number of times we try to read the INIT interrupt */ | 46 | /* number of times we try to read the INIT interrupt */ |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 5b128a971449..885364ca4344 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "cmd.h" | 36 | #include "cmd.h" |
37 | #include "event.h" | 37 | #include "event.h" |
38 | #include "tx.h" | 38 | #include "tx.h" |
39 | #include "hw_ops.h" | ||
39 | 40 | ||
40 | #define WL1271_CMD_FAST_POLL_COUNT 50 | 41 | #define WL1271_CMD_FAST_POLL_COUNT 50 |
41 | 42 | ||
@@ -291,6 +292,23 @@ static int wl12xx_get_new_session_id(struct wl1271 *wl, | |||
291 | return wlvif->session_counter; | 292 | return wlvif->session_counter; |
292 | } | 293 | } |
293 | 294 | ||
295 | static u8 wlcore_get_native_channel_type(u8 nl_channel_type) | ||
296 | { | ||
297 | switch (nl_channel_type) { | ||
298 | case NL80211_CHAN_NO_HT: | ||
299 | return WLCORE_CHAN_NO_HT; | ||
300 | case NL80211_CHAN_HT20: | ||
301 | return WLCORE_CHAN_HT20; | ||
302 | case NL80211_CHAN_HT40MINUS: | ||
303 | return WLCORE_CHAN_HT40MINUS; | ||
304 | case NL80211_CHAN_HT40PLUS: | ||
305 | return WLCORE_CHAN_HT40PLUS; | ||
306 | default: | ||
307 | WARN_ON(1); | ||
308 | return WLCORE_CHAN_NO_HT; | ||
309 | } | ||
310 | } | ||
311 | |||
294 | static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, | 312 | static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, |
295 | struct wl12xx_vif *wlvif) | 313 | struct wl12xx_vif *wlvif) |
296 | { | 314 | { |
@@ -407,6 +425,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
407 | memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); | 425 | memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); |
408 | memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); | 426 | memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); |
409 | cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); | 427 | cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); |
428 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); | ||
410 | 429 | ||
411 | if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { | 430 | if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { |
412 | ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); | 431 | ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); |
@@ -482,6 +501,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
482 | struct wl12xx_cmd_role_start *cmd; | 501 | struct wl12xx_cmd_role_start *cmd; |
483 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 502 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
484 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 503 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
504 | u32 supported_rates; | ||
485 | int ret; | 505 | int ret; |
486 | 506 | ||
487 | wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); | 507 | wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); |
@@ -519,6 +539,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
519 | /* FIXME: Change when adding DFS */ | 539 | /* FIXME: Change when adding DFS */ |
520 | cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ | 540 | cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ |
521 | cmd->channel = wlvif->channel; | 541 | cmd->channel = wlvif->channel; |
542 | cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); | ||
522 | 543 | ||
523 | if (!bss_conf->hidden_ssid) { | 544 | if (!bss_conf->hidden_ssid) { |
524 | /* take the SSID from the beacon for backward compatibility */ | 545 | /* take the SSID from the beacon for backward compatibility */ |
@@ -531,7 +552,13 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
531 | memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); | 552 | memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); |
532 | } | 553 | } |
533 | 554 | ||
534 | cmd->ap.local_rates = cpu_to_le32(0xffffffff); | 555 | supported_rates = CONF_TX_AP_ENABLED_RATES | CONF_TX_MCS_RATES | |
556 | wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); | ||
557 | |||
558 | wl1271_debug(DEBUG_CMD, "cmd role start ap with supported_rates 0x%08x", | ||
559 | supported_rates); | ||
560 | |||
561 | cmd->ap.local_rates = cpu_to_le32(supported_rates); | ||
535 | 562 | ||
536 | switch (wlvif->band) { | 563 | switch (wlvif->band) { |
537 | case IEEE80211_BAND_2GHZ: | 564 | case IEEE80211_BAND_2GHZ: |
@@ -797,6 +824,7 @@ out: | |||
797 | kfree(cmd); | 824 | kfree(cmd); |
798 | return ret; | 825 | return ret; |
799 | } | 826 | } |
827 | EXPORT_SYMBOL_GPL(wl1271_cmd_data_path); | ||
800 | 828 | ||
801 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 829 | int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
802 | u8 ps_mode, u16 auto_ps_timeout) | 830 | u8 ps_mode, u16 auto_ps_timeout) |
@@ -1018,7 +1046,7 @@ out: | |||
1018 | 1046 | ||
1019 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 1047 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
1020 | { | 1048 | { |
1021 | int ret, extra; | 1049 | int ret, extra = 0; |
1022 | u16 fc; | 1050 | u16 fc; |
1023 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | 1051 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
1024 | struct sk_buff *skb; | 1052 | struct sk_buff *skb; |
@@ -1057,7 +1085,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1057 | /* encryption space */ | 1085 | /* encryption space */ |
1058 | switch (wlvif->encryption_type) { | 1086 | switch (wlvif->encryption_type) { |
1059 | case KEY_TKIP: | 1087 | case KEY_TKIP: |
1060 | extra = WL1271_EXTRA_SPACE_TKIP; | 1088 | if (wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) |
1089 | extra = WL1271_EXTRA_SPACE_TKIP; | ||
1061 | break; | 1090 | break; |
1062 | case KEY_AES: | 1091 | case KEY_AES: |
1063 | extra = WL1271_EXTRA_SPACE_AES; | 1092 | extra = WL1271_EXTRA_SPACE_AES; |
@@ -1346,13 +1375,18 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1346 | 1375 | ||
1347 | for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) | 1376 | for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) |
1348 | if (sta->wme && (sta->uapsd_queues & BIT(i))) | 1377 | if (sta->wme && (sta->uapsd_queues & BIT(i))) |
1349 | cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER; | 1378 | cmd->psd_type[NUM_ACCESS_CATEGORIES_COPY-1-i] = |
1379 | WL1271_PSD_UPSD_TRIGGER; | ||
1350 | else | 1380 | else |
1351 | cmd->psd_type[i] = WL1271_PSD_LEGACY; | 1381 | cmd->psd_type[NUM_ACCESS_CATEGORIES_COPY-1-i] = |
1382 | WL1271_PSD_LEGACY; | ||
1383 | |||
1352 | 1384 | ||
1353 | sta_rates = sta->supp_rates[wlvif->band]; | 1385 | sta_rates = sta->supp_rates[wlvif->band]; |
1354 | if (sta->ht_cap.ht_supported) | 1386 | if (sta->ht_cap.ht_supported) |
1355 | sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; | 1387 | sta_rates |= |
1388 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET) | | ||
1389 | (sta->ht_cap.mcs.rx_mask[1] << HW_MIMO_RATES_OFFSET); | ||
1356 | 1390 | ||
1357 | cmd->supported_rates = | 1391 | cmd->supported_rates = |
1358 | cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, | 1392 | cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, |
@@ -1573,19 +1607,25 @@ out: | |||
1573 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) | 1607 | int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) |
1574 | { | 1608 | { |
1575 | int ret = 0; | 1609 | int ret = 0; |
1610 | bool is_first_roc; | ||
1576 | 1611 | ||
1577 | if (WARN_ON(test_bit(role_id, wl->roc_map))) | 1612 | if (WARN_ON(test_bit(role_id, wl->roc_map))) |
1578 | return 0; | 1613 | return 0; |
1579 | 1614 | ||
1615 | is_first_roc = (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= | ||
1616 | WL12XX_MAX_ROLES); | ||
1617 | |||
1580 | ret = wl12xx_cmd_roc(wl, wlvif, role_id); | 1618 | ret = wl12xx_cmd_roc(wl, wlvif, role_id); |
1581 | if (ret < 0) | 1619 | if (ret < 0) |
1582 | goto out; | 1620 | goto out; |
1583 | 1621 | ||
1584 | ret = wl1271_cmd_wait_for_event(wl, | 1622 | if (is_first_roc) { |
1585 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); | 1623 | ret = wl1271_cmd_wait_for_event(wl, |
1586 | if (ret < 0) { | 1624 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); |
1587 | wl1271_error("cmd roc event completion error"); | 1625 | if (ret < 0) { |
1588 | goto out; | 1626 | wl1271_error("cmd roc event completion error"); |
1627 | goto out; | ||
1628 | } | ||
1589 | } | 1629 | } |
1590 | 1630 | ||
1591 | __set_bit(role_id, wl->roc_map); | 1631 | __set_bit(role_id, wl->roc_map); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index a46ae07cb77e..85171f2bf68e 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -192,7 +192,7 @@ enum cmd_templ { | |||
192 | #define WL1271_COMMAND_TIMEOUT 2000 | 192 | #define WL1271_COMMAND_TIMEOUT 2000 |
193 | #define WL1271_CMD_TEMPL_DFLT_SIZE 252 | 193 | #define WL1271_CMD_TEMPL_DFLT_SIZE 252 |
194 | #define WL1271_CMD_TEMPL_MAX_SIZE 512 | 194 | #define WL1271_CMD_TEMPL_MAX_SIZE 512 |
195 | #define WL1271_EVENT_TIMEOUT 750 | 195 | #define WL1271_EVENT_TIMEOUT 1000 |
196 | 196 | ||
197 | struct wl1271_cmd_header { | 197 | struct wl1271_cmd_header { |
198 | __le16 id; | 198 | __le16 id; |
@@ -266,13 +266,22 @@ enum wlcore_band { | |||
266 | WLCORE_BAND_MAX_RADIO = 0x7F, | 266 | WLCORE_BAND_MAX_RADIO = 0x7F, |
267 | }; | 267 | }; |
268 | 268 | ||
269 | enum wlcore_channel_type { | ||
270 | WLCORE_CHAN_NO_HT, | ||
271 | WLCORE_CHAN_HT20, | ||
272 | WLCORE_CHAN_HT40MINUS, | ||
273 | WLCORE_CHAN_HT40PLUS | ||
274 | }; | ||
275 | |||
269 | struct wl12xx_cmd_role_start { | 276 | struct wl12xx_cmd_role_start { |
270 | struct wl1271_cmd_header header; | 277 | struct wl1271_cmd_header header; |
271 | 278 | ||
272 | u8 role_id; | 279 | u8 role_id; |
273 | u8 band; | 280 | u8 band; |
274 | u8 channel; | 281 | u8 channel; |
275 | u8 padding; | 282 | |
283 | /* enum wlcore_channel_type */ | ||
284 | u8 channel_type; | ||
276 | 285 | ||
277 | union { | 286 | union { |
278 | struct { | 287 | struct { |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index fef0db4213bc..03c635872335 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -45,7 +45,15 @@ enum { | |||
45 | CONF_HW_BIT_RATE_MCS_4 = BIT(17), | 45 | CONF_HW_BIT_RATE_MCS_4 = BIT(17), |
46 | CONF_HW_BIT_RATE_MCS_5 = BIT(18), | 46 | CONF_HW_BIT_RATE_MCS_5 = BIT(18), |
47 | CONF_HW_BIT_RATE_MCS_6 = BIT(19), | 47 | CONF_HW_BIT_RATE_MCS_6 = BIT(19), |
48 | CONF_HW_BIT_RATE_MCS_7 = BIT(20) | 48 | CONF_HW_BIT_RATE_MCS_7 = BIT(20), |
49 | CONF_HW_BIT_RATE_MCS_8 = BIT(21), | ||
50 | CONF_HW_BIT_RATE_MCS_9 = BIT(22), | ||
51 | CONF_HW_BIT_RATE_MCS_10 = BIT(23), | ||
52 | CONF_HW_BIT_RATE_MCS_11 = BIT(24), | ||
53 | CONF_HW_BIT_RATE_MCS_12 = BIT(25), | ||
54 | CONF_HW_BIT_RATE_MCS_13 = BIT(26), | ||
55 | CONF_HW_BIT_RATE_MCS_14 = BIT(27), | ||
56 | CONF_HW_BIT_RATE_MCS_15 = BIT(28), | ||
49 | }; | 57 | }; |
50 | 58 | ||
51 | enum { | 59 | enum { |
@@ -310,7 +318,7 @@ enum { | |||
310 | struct conf_sg_settings { | 318 | struct conf_sg_settings { |
311 | u32 params[CONF_SG_PARAMS_MAX]; | 319 | u32 params[CONF_SG_PARAMS_MAX]; |
312 | u8 state; | 320 | u8 state; |
313 | }; | 321 | } __packed; |
314 | 322 | ||
315 | enum conf_rx_queue_type { | 323 | enum conf_rx_queue_type { |
316 | CONF_RX_QUEUE_TYPE_LOW_PRIORITY, /* All except the high priority */ | 324 | CONF_RX_QUEUE_TYPE_LOW_PRIORITY, /* All except the high priority */ |
@@ -394,7 +402,7 @@ struct conf_rx_settings { | |||
394 | * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY, | 402 | * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY, |
395 | */ | 403 | */ |
396 | u8 queue_type; | 404 | u8 queue_type; |
397 | }; | 405 | } __packed; |
398 | 406 | ||
399 | #define CONF_TX_MAX_RATE_CLASSES 10 | 407 | #define CONF_TX_MAX_RATE_CLASSES 10 |
400 | 408 | ||
@@ -435,6 +443,12 @@ struct conf_rx_settings { | |||
435 | CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \ | 443 | CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \ |
436 | CONF_HW_BIT_RATE_MCS_7) | 444 | CONF_HW_BIT_RATE_MCS_7) |
437 | 445 | ||
446 | #define CONF_TX_MIMO_RATES (CONF_HW_BIT_RATE_MCS_8 | \ | ||
447 | CONF_HW_BIT_RATE_MCS_9 | CONF_HW_BIT_RATE_MCS_10 | \ | ||
448 | CONF_HW_BIT_RATE_MCS_11 | CONF_HW_BIT_RATE_MCS_12 | \ | ||
449 | CONF_HW_BIT_RATE_MCS_13 | CONF_HW_BIT_RATE_MCS_14 | \ | ||
450 | CONF_HW_BIT_RATE_MCS_15) | ||
451 | |||
438 | /* | 452 | /* |
439 | * Default rates for management traffic when operating in AP mode. This | 453 | * Default rates for management traffic when operating in AP mode. This |
440 | * should be configured according to the basic rate set of the AP | 454 | * should be configured according to the basic rate set of the AP |
@@ -487,7 +501,7 @@ struct conf_tx_rate_class { | |||
487 | * the policy (0 - long preamble, 1 - short preamble. | 501 | * the policy (0 - long preamble, 1 - short preamble. |
488 | */ | 502 | */ |
489 | u8 aflags; | 503 | u8 aflags; |
490 | }; | 504 | } __packed; |
491 | 505 | ||
492 | #define CONF_TX_MAX_AC_COUNT 4 | 506 | #define CONF_TX_MAX_AC_COUNT 4 |
493 | 507 | ||
@@ -504,7 +518,7 @@ enum conf_tx_ac { | |||
504 | CONF_TX_AC_VI = 2, /* video */ | 518 | CONF_TX_AC_VI = 2, /* video */ |
505 | CONF_TX_AC_VO = 3, /* voice */ | 519 | CONF_TX_AC_VO = 3, /* voice */ |
506 | CONF_TX_AC_CTS2SELF = 4, /* fictitious AC, follows AC_VO */ | 520 | CONF_TX_AC_CTS2SELF = 4, /* fictitious AC, follows AC_VO */ |
507 | CONF_TX_AC_ANY_TID = 0x1f | 521 | CONF_TX_AC_ANY_TID = 0xff |
508 | }; | 522 | }; |
509 | 523 | ||
510 | struct conf_tx_ac_category { | 524 | struct conf_tx_ac_category { |
@@ -544,7 +558,7 @@ struct conf_tx_ac_category { | |||
544 | * Range: u16 | 558 | * Range: u16 |
545 | */ | 559 | */ |
546 | u16 tx_op_limit; | 560 | u16 tx_op_limit; |
547 | }; | 561 | } __packed; |
548 | 562 | ||
549 | #define CONF_TX_MAX_TID_COUNT 8 | 563 | #define CONF_TX_MAX_TID_COUNT 8 |
550 | 564 | ||
@@ -578,7 +592,7 @@ struct conf_tx_tid { | |||
578 | u8 ps_scheme; | 592 | u8 ps_scheme; |
579 | u8 ack_policy; | 593 | u8 ack_policy; |
580 | u32 apsd_conf[2]; | 594 | u32 apsd_conf[2]; |
581 | }; | 595 | } __packed; |
582 | 596 | ||
583 | struct conf_tx_settings { | 597 | struct conf_tx_settings { |
584 | /* | 598 | /* |
@@ -664,7 +678,7 @@ struct conf_tx_settings { | |||
664 | 678 | ||
665 | /* Time in ms for Tx watchdog timer to expire */ | 679 | /* Time in ms for Tx watchdog timer to expire */ |
666 | u32 tx_watchdog_timeout; | 680 | u32 tx_watchdog_timeout; |
667 | }; | 681 | } __packed; |
668 | 682 | ||
669 | enum { | 683 | enum { |
670 | CONF_WAKE_UP_EVENT_BEACON = 0x01, /* Wake on every Beacon*/ | 684 | CONF_WAKE_UP_EVENT_BEACON = 0x01, /* Wake on every Beacon*/ |
@@ -711,7 +725,7 @@ struct conf_bcn_filt_rule { | |||
711 | * Version for the vendor specifie IE (221) | 725 | * Version for the vendor specifie IE (221) |
712 | */ | 726 | */ |
713 | u8 version[CONF_BCN_IE_VER_LEN]; | 727 | u8 version[CONF_BCN_IE_VER_LEN]; |
714 | }; | 728 | } __packed; |
715 | 729 | ||
716 | #define CONF_MAX_RSSI_SNR_TRIGGERS 8 | 730 | #define CONF_MAX_RSSI_SNR_TRIGGERS 8 |
717 | 731 | ||
@@ -762,7 +776,7 @@ struct conf_sig_weights { | |||
762 | * Range: u8 | 776 | * Range: u8 |
763 | */ | 777 | */ |
764 | u8 snr_pkt_avg_weight; | 778 | u8 snr_pkt_avg_weight; |
765 | }; | 779 | } __packed; |
766 | 780 | ||
767 | enum conf_bcn_filt_mode { | 781 | enum conf_bcn_filt_mode { |
768 | CONF_BCN_FILT_MODE_DISABLED = 0, | 782 | CONF_BCN_FILT_MODE_DISABLED = 0, |
@@ -810,7 +824,7 @@ struct conf_conn_settings { | |||
810 | * | 824 | * |
811 | * Range: CONF_BCN_FILT_MODE_* | 825 | * Range: CONF_BCN_FILT_MODE_* |
812 | */ | 826 | */ |
813 | enum conf_bcn_filt_mode bcn_filt_mode; | 827 | u8 bcn_filt_mode; |
814 | 828 | ||
815 | /* | 829 | /* |
816 | * Configure Beacon filter pass-thru rules. | 830 | * Configure Beacon filter pass-thru rules. |
@@ -937,7 +951,7 @@ struct conf_conn_settings { | |||
937 | * Range: u16 | 951 | * Range: u16 |
938 | */ | 952 | */ |
939 | u8 max_listen_interval; | 953 | u8 max_listen_interval; |
940 | }; | 954 | } __packed; |
941 | 955 | ||
942 | enum { | 956 | enum { |
943 | CONF_REF_CLK_19_2_E, | 957 | CONF_REF_CLK_19_2_E, |
@@ -965,6 +979,11 @@ struct conf_itrim_settings { | |||
965 | 979 | ||
966 | /* moderation timeout in microsecs from the last TX */ | 980 | /* moderation timeout in microsecs from the last TX */ |
967 | u32 timeout; | 981 | u32 timeout; |
982 | } __packed; | ||
983 | |||
984 | enum conf_fast_wakeup { | ||
985 | CONF_FAST_WAKEUP_ENABLE, | ||
986 | CONF_FAST_WAKEUP_DISABLE, | ||
968 | }; | 987 | }; |
969 | 988 | ||
970 | struct conf_pm_config_settings { | 989 | struct conf_pm_config_settings { |
@@ -978,10 +997,10 @@ struct conf_pm_config_settings { | |||
978 | /* | 997 | /* |
979 | * Host fast wakeup support | 998 | * Host fast wakeup support |
980 | * | 999 | * |
981 | * Range: true, false | 1000 | * Range: enum conf_fast_wakeup |
982 | */ | 1001 | */ |
983 | bool host_fast_wakeup_support; | 1002 | u8 host_fast_wakeup_support; |
984 | }; | 1003 | } __packed; |
985 | 1004 | ||
986 | struct conf_roam_trigger_settings { | 1005 | struct conf_roam_trigger_settings { |
987 | /* | 1006 | /* |
@@ -1018,7 +1037,7 @@ struct conf_roam_trigger_settings { | |||
1018 | * Range: 0 - 255 | 1037 | * Range: 0 - 255 |
1019 | */ | 1038 | */ |
1020 | u8 avg_weight_snr_data; | 1039 | u8 avg_weight_snr_data; |
1021 | }; | 1040 | } __packed; |
1022 | 1041 | ||
1023 | struct conf_scan_settings { | 1042 | struct conf_scan_settings { |
1024 | /* | 1043 | /* |
@@ -1064,7 +1083,7 @@ struct conf_scan_settings { | |||
1064 | * Range: u32 Microsecs | 1083 | * Range: u32 Microsecs |
1065 | */ | 1084 | */ |
1066 | u32 split_scan_timeout; | 1085 | u32 split_scan_timeout; |
1067 | }; | 1086 | } __packed; |
1068 | 1087 | ||
1069 | struct conf_sched_scan_settings { | 1088 | struct conf_sched_scan_settings { |
1070 | /* | 1089 | /* |
@@ -1102,7 +1121,7 @@ struct conf_sched_scan_settings { | |||
1102 | 1121 | ||
1103 | /* SNR threshold to be used for filtering */ | 1122 | /* SNR threshold to be used for filtering */ |
1104 | s8 snr_threshold; | 1123 | s8 snr_threshold; |
1105 | }; | 1124 | } __packed; |
1106 | 1125 | ||
1107 | struct conf_ht_setting { | 1126 | struct conf_ht_setting { |
1108 | u8 rx_ba_win_size; | 1127 | u8 rx_ba_win_size; |
@@ -1111,7 +1130,7 @@ struct conf_ht_setting { | |||
1111 | 1130 | ||
1112 | /* bitmap of enabled TIDs for TX BA sessions */ | 1131 | /* bitmap of enabled TIDs for TX BA sessions */ |
1113 | u8 tx_ba_tid_bitmap; | 1132 | u8 tx_ba_tid_bitmap; |
1114 | }; | 1133 | } __packed; |
1115 | 1134 | ||
1116 | struct conf_memory_settings { | 1135 | struct conf_memory_settings { |
1117 | /* Number of stations supported in IBSS mode */ | 1136 | /* Number of stations supported in IBSS mode */ |
@@ -1151,7 +1170,7 @@ struct conf_memory_settings { | |||
1151 | * Range: 0-120 | 1170 | * Range: 0-120 |
1152 | */ | 1171 | */ |
1153 | u8 tx_min; | 1172 | u8 tx_min; |
1154 | }; | 1173 | } __packed; |
1155 | 1174 | ||
1156 | struct conf_fm_coex { | 1175 | struct conf_fm_coex { |
1157 | u8 enable; | 1176 | u8 enable; |
@@ -1164,7 +1183,7 @@ struct conf_fm_coex { | |||
1164 | u16 ldo_stabilization_time; | 1183 | u16 ldo_stabilization_time; |
1165 | u8 fm_disturbed_band_margin; | 1184 | u8 fm_disturbed_band_margin; |
1166 | u8 swallow_clk_diff; | 1185 | u8 swallow_clk_diff; |
1167 | }; | 1186 | } __packed; |
1168 | 1187 | ||
1169 | struct conf_rx_streaming_settings { | 1188 | struct conf_rx_streaming_settings { |
1170 | /* | 1189 | /* |
@@ -1193,7 +1212,7 @@ struct conf_rx_streaming_settings { | |||
1193 | * enable rx streaming also when there is no coex activity | 1212 | * enable rx streaming also when there is no coex activity |
1194 | */ | 1213 | */ |
1195 | u8 always; | 1214 | u8 always; |
1196 | }; | 1215 | } __packed; |
1197 | 1216 | ||
1198 | struct conf_fwlog { | 1217 | struct conf_fwlog { |
1199 | /* Continuous or on-demand */ | 1218 | /* Continuous or on-demand */ |
@@ -1217,7 +1236,7 @@ struct conf_fwlog { | |||
1217 | 1236 | ||
1218 | /* Regulates the frequency of log messages */ | 1237 | /* Regulates the frequency of log messages */ |
1219 | u8 threshold; | 1238 | u8 threshold; |
1220 | }; | 1239 | } __packed; |
1221 | 1240 | ||
1222 | #define ACX_RATE_MGMT_NUM_OF_RATES 13 | 1241 | #define ACX_RATE_MGMT_NUM_OF_RATES 13 |
1223 | struct conf_rate_policy_settings { | 1242 | struct conf_rate_policy_settings { |
@@ -1236,7 +1255,7 @@ struct conf_rate_policy_settings { | |||
1236 | u8 rate_check_up; | 1255 | u8 rate_check_up; |
1237 | u8 rate_check_down; | 1256 | u8 rate_check_down; |
1238 | u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; | 1257 | u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; |
1239 | }; | 1258 | } __packed; |
1240 | 1259 | ||
1241 | struct conf_hangover_settings { | 1260 | struct conf_hangover_settings { |
1242 | u32 recover_time; | 1261 | u32 recover_time; |
@@ -1250,7 +1269,23 @@ struct conf_hangover_settings { | |||
1250 | u8 quiet_time; | 1269 | u8 quiet_time; |
1251 | u8 increase_time; | 1270 | u8 increase_time; |
1252 | u8 window_size; | 1271 | u8 window_size; |
1253 | }; | 1272 | } __packed; |
1273 | |||
1274 | /* | ||
1275 | * The conf version consists of 4 bytes. The two MSB are the wlcore | ||
1276 | * version, the two LSB are the lower driver's private conf | ||
1277 | * version. | ||
1278 | */ | ||
1279 | #define WLCORE_CONF_VERSION (0x0001 << 16) | ||
1280 | #define WLCORE_CONF_MASK 0xffff0000 | ||
1281 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ | ||
1282 | sizeof(struct wlcore_conf)) | ||
1283 | |||
1284 | struct wlcore_conf_header { | ||
1285 | __le32 magic; | ||
1286 | __le32 version; | ||
1287 | __le32 checksum; | ||
1288 | } __packed; | ||
1254 | 1289 | ||
1255 | struct wlcore_conf { | 1290 | struct wlcore_conf { |
1256 | struct conf_sg_settings sg; | 1291 | struct conf_sg_settings sg; |
@@ -1269,6 +1304,12 @@ struct wlcore_conf { | |||
1269 | struct conf_fwlog fwlog; | 1304 | struct conf_fwlog fwlog; |
1270 | struct conf_rate_policy_settings rate; | 1305 | struct conf_rate_policy_settings rate; |
1271 | struct conf_hangover_settings hangover; | 1306 | struct conf_hangover_settings hangover; |
1272 | }; | 1307 | } __packed; |
1308 | |||
1309 | struct wlcore_conf_file { | ||
1310 | struct wlcore_conf_header header; | ||
1311 | struct wlcore_conf core; | ||
1312 | u8 priv[0]; | ||
1313 | } __packed; | ||
1273 | 1314 | ||
1274 | #endif | 1315 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index d5aea1ff5ad1..689a847005c9 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/module.h> | ||
28 | 29 | ||
29 | #include "wlcore.h" | 30 | #include "wlcore.h" |
30 | #include "debug.h" | 31 | #include "debug.h" |
@@ -32,14 +33,14 @@ | |||
32 | #include "ps.h" | 33 | #include "ps.h" |
33 | #include "io.h" | 34 | #include "io.h" |
34 | #include "tx.h" | 35 | #include "tx.h" |
36 | #include "hw_ops.h" | ||
35 | 37 | ||
36 | /* ms */ | 38 | /* ms */ |
37 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
38 | 40 | ||
39 | /* debugfs macros idea from mac80211 */ | 41 | /* debugfs macros idea from mac80211 */ |
40 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 | 42 | int wl1271_format_buffer(char __user *userbuf, size_t count, |
41 | static int wl1271_format_buffer(char __user *userbuf, size_t count, | 43 | loff_t *ppos, char *fmt, ...) |
42 | loff_t *ppos, char *fmt, ...) | ||
43 | { | 44 | { |
44 | va_list args; | 45 | va_list args; |
45 | char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; | 46 | char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; |
@@ -51,59 +52,9 @@ static int wl1271_format_buffer(char __user *userbuf, size_t count, | |||
51 | 52 | ||
52 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 53 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
53 | } | 54 | } |
55 | EXPORT_SYMBOL_GPL(wl1271_format_buffer); | ||
54 | 56 | ||
55 | #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ | 57 | void wl1271_debugfs_update_stats(struct wl1271 *wl) |
56 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | ||
57 | size_t count, loff_t *ppos) \ | ||
58 | { \ | ||
59 | struct wl1271 *wl = file->private_data; \ | ||
60 | return wl1271_format_buffer(userbuf, count, ppos, \ | ||
61 | fmt "\n", ##value); \ | ||
62 | } \ | ||
63 | \ | ||
64 | static const struct file_operations name## _ops = { \ | ||
65 | .read = name## _read, \ | ||
66 | .open = simple_open, \ | ||
67 | .llseek = generic_file_llseek, \ | ||
68 | }; | ||
69 | |||
70 | #define DEBUGFS_ADD(name, parent) \ | ||
71 | entry = debugfs_create_file(#name, 0400, parent, \ | ||
72 | wl, &name## _ops); \ | ||
73 | if (!entry || IS_ERR(entry)) \ | ||
74 | goto err; \ | ||
75 | |||
76 | #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ | ||
77 | do { \ | ||
78 | entry = debugfs_create_file(#name, 0400, parent, \ | ||
79 | wl, &prefix## _## name## _ops); \ | ||
80 | if (!entry || IS_ERR(entry)) \ | ||
81 | goto err; \ | ||
82 | } while (0); | ||
83 | |||
84 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ | ||
85 | static ssize_t sub## _ ##name## _read(struct file *file, \ | ||
86 | char __user *userbuf, \ | ||
87 | size_t count, loff_t *ppos) \ | ||
88 | { \ | ||
89 | struct wl1271 *wl = file->private_data; \ | ||
90 | \ | ||
91 | wl1271_debugfs_update_stats(wl); \ | ||
92 | \ | ||
93 | return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ | ||
94 | wl->stats.fw_stats->sub.name); \ | ||
95 | } \ | ||
96 | \ | ||
97 | static const struct file_operations sub## _ ##name## _ops = { \ | ||
98 | .read = sub## _ ##name## _read, \ | ||
99 | .open = simple_open, \ | ||
100 | .llseek = generic_file_llseek, \ | ||
101 | }; | ||
102 | |||
103 | #define DEBUGFS_FWSTATS_ADD(sub, name) \ | ||
104 | DEBUGFS_ADD(sub## _ ##name, stats) | ||
105 | |||
106 | static void wl1271_debugfs_update_stats(struct wl1271 *wl) | ||
107 | { | 58 | { |
108 | int ret; | 59 | int ret; |
109 | 60 | ||
@@ -125,97 +76,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) | |||
125 | out: | 76 | out: |
126 | mutex_unlock(&wl->mutex); | 77 | mutex_unlock(&wl->mutex); |
127 | } | 78 | } |
128 | 79 | EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats); | |
129 | DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); | ||
130 | |||
131 | DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); | ||
132 | DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); | ||
133 | DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); | ||
134 | DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); | ||
135 | DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); | ||
136 | DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); | ||
137 | DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); | ||
138 | DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); | ||
139 | |||
140 | DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); | ||
141 | DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); | ||
142 | DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); | ||
143 | DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); | ||
144 | |||
145 | DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); | ||
146 | DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); | ||
147 | DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); | ||
148 | DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); | ||
149 | DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); | ||
150 | DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); | ||
151 | DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); | ||
152 | DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); | ||
153 | DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); | ||
154 | DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); | ||
155 | DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); | ||
156 | DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); | ||
157 | DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); | ||
158 | DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); | ||
159 | DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); | ||
160 | DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); | ||
161 | DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); | ||
162 | DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); | ||
163 | |||
164 | DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); | ||
165 | DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); | ||
166 | /* skipping wep.reserved */ | ||
167 | DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); | ||
168 | DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); | ||
169 | DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); | ||
170 | DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); | ||
171 | |||
172 | DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); | ||
173 | DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); | ||
174 | DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); | ||
175 | DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); | ||
176 | DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); | ||
177 | DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); | ||
178 | DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); | ||
179 | DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); | ||
180 | DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); | ||
181 | DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); | ||
182 | DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); | ||
183 | DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); | ||
184 | /* skipping cont_miss_bcns_spread for now */ | ||
185 | DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); | ||
186 | |||
187 | DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); | ||
188 | DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); | ||
189 | |||
190 | DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); | ||
191 | DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); | ||
192 | DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); | ||
193 | DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); | ||
194 | DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); | ||
195 | DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); | ||
196 | |||
197 | DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); | ||
198 | DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); | ||
199 | DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); | ||
200 | DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); | ||
201 | DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); | ||
202 | DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); | ||
203 | DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); | ||
204 | DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); | ||
205 | |||
206 | DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); | ||
207 | DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); | ||
208 | DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); | ||
209 | DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); | ||
210 | DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); | ||
211 | DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); | ||
212 | DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); | ||
213 | |||
214 | DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); | ||
215 | DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); | ||
216 | DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, "%u"); | ||
217 | DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); | ||
218 | DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); | ||
219 | 80 | ||
220 | DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); | 81 | DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); |
221 | DEBUGFS_READONLY_FILE(excessive_retries, "%u", | 82 | DEBUGFS_READONLY_FILE(excessive_retries, "%u", |
@@ -241,6 +102,89 @@ static const struct file_operations tx_queue_len_ops = { | |||
241 | .llseek = default_llseek, | 102 | .llseek = default_llseek, |
242 | }; | 103 | }; |
243 | 104 | ||
105 | static void chip_op_handler(struct wl1271 *wl, unsigned long value, | ||
106 | void *arg) | ||
107 | { | ||
108 | int ret; | ||
109 | int (*chip_op) (struct wl1271 *wl); | ||
110 | |||
111 | if (!arg) { | ||
112 | wl1271_warning("debugfs chip_op_handler with no callback"); | ||
113 | return; | ||
114 | } | ||
115 | |||
116 | ret = wl1271_ps_elp_wakeup(wl); | ||
117 | if (ret < 0) | ||
118 | return; | ||
119 | |||
120 | chip_op = arg; | ||
121 | chip_op(wl); | ||
122 | |||
123 | wl1271_ps_elp_sleep(wl); | ||
124 | } | ||
125 | |||
126 | |||
127 | static inline void no_write_handler(struct wl1271 *wl, | ||
128 | unsigned long value, | ||
129 | unsigned long param) | ||
130 | { | ||
131 | } | ||
132 | |||
133 | #define WL12XX_CONF_DEBUGFS(param, conf_sub_struct, \ | ||
134 | min_val, max_val, write_handler_locked, \ | ||
135 | write_handler_arg) \ | ||
136 | static ssize_t param##_read(struct file *file, \ | ||
137 | char __user *user_buf, \ | ||
138 | size_t count, loff_t *ppos) \ | ||
139 | { \ | ||
140 | struct wl1271 *wl = file->private_data; \ | ||
141 | return wl1271_format_buffer(user_buf, count, \ | ||
142 | ppos, "%d\n", \ | ||
143 | wl->conf.conf_sub_struct.param); \ | ||
144 | } \ | ||
145 | \ | ||
146 | static ssize_t param##_write(struct file *file, \ | ||
147 | const char __user *user_buf, \ | ||
148 | size_t count, loff_t *ppos) \ | ||
149 | { \ | ||
150 | struct wl1271 *wl = file->private_data; \ | ||
151 | unsigned long value; \ | ||
152 | int ret; \ | ||
153 | \ | ||
154 | ret = kstrtoul_from_user(user_buf, count, 10, &value); \ | ||
155 | if (ret < 0) { \ | ||
156 | wl1271_warning("illegal value for " #param); \ | ||
157 | return -EINVAL; \ | ||
158 | } \ | ||
159 | \ | ||
160 | if (value < min_val || value > max_val) { \ | ||
161 | wl1271_warning(#param " is not in valid range"); \ | ||
162 | return -ERANGE; \ | ||
163 | } \ | ||
164 | \ | ||
165 | mutex_lock(&wl->mutex); \ | ||
166 | wl->conf.conf_sub_struct.param = value; \ | ||
167 | \ | ||
168 | write_handler_locked(wl, value, write_handler_arg); \ | ||
169 | \ | ||
170 | mutex_unlock(&wl->mutex); \ | ||
171 | return count; \ | ||
172 | } \ | ||
173 | \ | ||
174 | static const struct file_operations param##_ops = { \ | ||
175 | .read = param##_read, \ | ||
176 | .write = param##_write, \ | ||
177 | .open = simple_open, \ | ||
178 | .llseek = default_llseek, \ | ||
179 | }; | ||
180 | |||
181 | WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535, | ||
182 | chip_op_handler, wl1271_acx_init_rx_interrupt) | ||
183 | WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535, | ||
184 | chip_op_handler, wl1271_acx_init_rx_interrupt) | ||
185 | WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100, | ||
186 | chip_op_handler, wl1271_acx_init_rx_interrupt) | ||
187 | |||
244 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, | 188 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, |
245 | size_t count, loff_t *ppos) | 189 | size_t count, loff_t *ppos) |
246 | { | 190 | { |
@@ -535,8 +479,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
535 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); | 479 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); |
536 | DRIVER_STATE_PRINT_HEX(quirks); | 480 | DRIVER_STATE_PRINT_HEX(quirks); |
537 | DRIVER_STATE_PRINT_HEX(irq); | 481 | DRIVER_STATE_PRINT_HEX(irq); |
538 | DRIVER_STATE_PRINT_HEX(ref_clock); | 482 | /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */ |
539 | DRIVER_STATE_PRINT_HEX(tcxo_clock); | ||
540 | DRIVER_STATE_PRINT_HEX(hw_pg_ver); | 483 | DRIVER_STATE_PRINT_HEX(hw_pg_ver); |
541 | DRIVER_STATE_PRINT_HEX(platform_quirks); | 484 | DRIVER_STATE_PRINT_HEX(platform_quirks); |
542 | DRIVER_STATE_PRINT_HEX(chip.id); | 485 | DRIVER_STATE_PRINT_HEX(chip.id); |
@@ -647,7 +590,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
647 | VIF_STATE_PRINT_INT(last_rssi_event); | 590 | VIF_STATE_PRINT_INT(last_rssi_event); |
648 | VIF_STATE_PRINT_INT(ba_support); | 591 | VIF_STATE_PRINT_INT(ba_support); |
649 | VIF_STATE_PRINT_INT(ba_allowed); | 592 | VIF_STATE_PRINT_INT(ba_allowed); |
650 | VIF_STATE_PRINT_INT(is_gem); | ||
651 | VIF_STATE_PRINT_LLHEX(tx_security_seq); | 593 | VIF_STATE_PRINT_LLHEX(tx_security_seq); |
652 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); | 594 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); |
653 | } | 595 | } |
@@ -1002,108 +944,30 @@ static const struct file_operations beacon_filtering_ops = { | |||
1002 | .llseek = default_llseek, | 944 | .llseek = default_llseek, |
1003 | }; | 945 | }; |
1004 | 946 | ||
1005 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 947 | static ssize_t fw_stats_raw_read(struct file *file, |
1006 | struct dentry *rootdir) | 948 | char __user *userbuf, |
949 | size_t count, loff_t *ppos) | ||
1007 | { | 950 | { |
1008 | int ret = 0; | 951 | struct wl1271 *wl = file->private_data; |
1009 | struct dentry *entry, *stats, *streaming; | ||
1010 | 952 | ||
1011 | stats = debugfs_create_dir("fw-statistics", rootdir); | 953 | wl1271_debugfs_update_stats(wl); |
1012 | if (!stats || IS_ERR(stats)) { | ||
1013 | entry = stats; | ||
1014 | goto err; | ||
1015 | } | ||
1016 | 954 | ||
1017 | DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); | 955 | return simple_read_from_buffer(userbuf, count, ppos, |
1018 | 956 | wl->stats.fw_stats, | |
1019 | DEBUGFS_FWSTATS_ADD(rx, out_of_mem); | 957 | wl->stats.fw_stats_len); |
1020 | DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); | 958 | } |
1021 | DEBUGFS_FWSTATS_ADD(rx, hw_stuck); | 959 | |
1022 | DEBUGFS_FWSTATS_ADD(rx, dropped); | 960 | static const struct file_operations fw_stats_raw_ops = { |
1023 | DEBUGFS_FWSTATS_ADD(rx, fcs_err); | 961 | .read = fw_stats_raw_read, |
1024 | DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); | 962 | .open = simple_open, |
1025 | DEBUGFS_FWSTATS_ADD(rx, path_reset); | 963 | .llseek = default_llseek, |
1026 | DEBUGFS_FWSTATS_ADD(rx, reset_counter); | 964 | }; |
1027 | 965 | ||
1028 | DEBUGFS_FWSTATS_ADD(dma, rx_requested); | 966 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
1029 | DEBUGFS_FWSTATS_ADD(dma, rx_errors); | 967 | struct dentry *rootdir) |
1030 | DEBUGFS_FWSTATS_ADD(dma, tx_requested); | 968 | { |
1031 | DEBUGFS_FWSTATS_ADD(dma, tx_errors); | 969 | int ret = 0; |
1032 | 970 | struct dentry *entry, *streaming; | |
1033 | DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); | ||
1034 | DEBUGFS_FWSTATS_ADD(isr, fiqs); | ||
1035 | DEBUGFS_FWSTATS_ADD(isr, rx_headers); | ||
1036 | DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); | ||
1037 | DEBUGFS_FWSTATS_ADD(isr, rx_rdys); | ||
1038 | DEBUGFS_FWSTATS_ADD(isr, irqs); | ||
1039 | DEBUGFS_FWSTATS_ADD(isr, tx_procs); | ||
1040 | DEBUGFS_FWSTATS_ADD(isr, decrypt_done); | ||
1041 | DEBUGFS_FWSTATS_ADD(isr, dma0_done); | ||
1042 | DEBUGFS_FWSTATS_ADD(isr, dma1_done); | ||
1043 | DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); | ||
1044 | DEBUGFS_FWSTATS_ADD(isr, commands); | ||
1045 | DEBUGFS_FWSTATS_ADD(isr, rx_procs); | ||
1046 | DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); | ||
1047 | DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); | ||
1048 | DEBUGFS_FWSTATS_ADD(isr, pci_pm); | ||
1049 | DEBUGFS_FWSTATS_ADD(isr, wakeups); | ||
1050 | DEBUGFS_FWSTATS_ADD(isr, low_rssi); | ||
1051 | |||
1052 | DEBUGFS_FWSTATS_ADD(wep, addr_key_count); | ||
1053 | DEBUGFS_FWSTATS_ADD(wep, default_key_count); | ||
1054 | /* skipping wep.reserved */ | ||
1055 | DEBUGFS_FWSTATS_ADD(wep, key_not_found); | ||
1056 | DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); | ||
1057 | DEBUGFS_FWSTATS_ADD(wep, packets); | ||
1058 | DEBUGFS_FWSTATS_ADD(wep, interrupt); | ||
1059 | |||
1060 | DEBUGFS_FWSTATS_ADD(pwr, ps_enter); | ||
1061 | DEBUGFS_FWSTATS_ADD(pwr, elp_enter); | ||
1062 | DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); | ||
1063 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); | ||
1064 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); | ||
1065 | DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); | ||
1066 | DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); | ||
1067 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); | ||
1068 | DEBUGFS_FWSTATS_ADD(pwr, power_save_off); | ||
1069 | DEBUGFS_FWSTATS_ADD(pwr, enable_ps); | ||
1070 | DEBUGFS_FWSTATS_ADD(pwr, disable_ps); | ||
1071 | DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); | ||
1072 | /* skipping cont_miss_bcns_spread for now */ | ||
1073 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); | ||
1074 | |||
1075 | DEBUGFS_FWSTATS_ADD(mic, rx_pkts); | ||
1076 | DEBUGFS_FWSTATS_ADD(mic, calc_failure); | ||
1077 | |||
1078 | DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); | ||
1079 | DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); | ||
1080 | DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); | ||
1081 | DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); | ||
1082 | DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); | ||
1083 | DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); | ||
1084 | |||
1085 | DEBUGFS_FWSTATS_ADD(event, heart_beat); | ||
1086 | DEBUGFS_FWSTATS_ADD(event, calibration); | ||
1087 | DEBUGFS_FWSTATS_ADD(event, rx_mismatch); | ||
1088 | DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); | ||
1089 | DEBUGFS_FWSTATS_ADD(event, rx_pool); | ||
1090 | DEBUGFS_FWSTATS_ADD(event, oom_late); | ||
1091 | DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); | ||
1092 | DEBUGFS_FWSTATS_ADD(event, tx_stuck); | ||
1093 | |||
1094 | DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); | ||
1095 | DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); | ||
1096 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); | ||
1097 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); | ||
1098 | DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); | ||
1099 | DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); | ||
1100 | DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); | ||
1101 | |||
1102 | DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); | ||
1103 | DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); | ||
1104 | DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); | ||
1105 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); | ||
1106 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | ||
1107 | 971 | ||
1108 | DEBUGFS_ADD(tx_queue_len, rootdir); | 972 | DEBUGFS_ADD(tx_queue_len, rootdir); |
1109 | DEBUGFS_ADD(retry_count, rootdir); | 973 | DEBUGFS_ADD(retry_count, rootdir); |
@@ -1120,6 +984,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
1120 | DEBUGFS_ADD(dynamic_ps_timeout, rootdir); | 984 | DEBUGFS_ADD(dynamic_ps_timeout, rootdir); |
1121 | DEBUGFS_ADD(forced_ps, rootdir); | 985 | DEBUGFS_ADD(forced_ps, rootdir); |
1122 | DEBUGFS_ADD(split_scan_timeout, rootdir); | 986 | DEBUGFS_ADD(split_scan_timeout, rootdir); |
987 | DEBUGFS_ADD(irq_pkt_threshold, rootdir); | ||
988 | DEBUGFS_ADD(irq_blk_threshold, rootdir); | ||
989 | DEBUGFS_ADD(irq_timeout, rootdir); | ||
990 | DEBUGFS_ADD(fw_stats_raw, rootdir); | ||
1123 | 991 | ||
1124 | streaming = debugfs_create_dir("rx_streaming", rootdir); | 992 | streaming = debugfs_create_dir("rx_streaming", rootdir); |
1125 | if (!streaming || IS_ERR(streaming)) | 993 | if (!streaming || IS_ERR(streaming)) |
@@ -1145,7 +1013,7 @@ void wl1271_debugfs_reset(struct wl1271 *wl) | |||
1145 | if (!wl->stats.fw_stats) | 1013 | if (!wl->stats.fw_stats) |
1146 | return; | 1014 | return; |
1147 | 1015 | ||
1148 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); | 1016 | memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len); |
1149 | wl->stats.retry_count = 0; | 1017 | wl->stats.retry_count = 0; |
1150 | wl->stats.excessive_retries = 0; | 1018 | wl->stats.excessive_retries = 0; |
1151 | } | 1019 | } |
@@ -1160,34 +1028,34 @@ int wl1271_debugfs_init(struct wl1271 *wl) | |||
1160 | 1028 | ||
1161 | if (IS_ERR(rootdir)) { | 1029 | if (IS_ERR(rootdir)) { |
1162 | ret = PTR_ERR(rootdir); | 1030 | ret = PTR_ERR(rootdir); |
1163 | goto err; | 1031 | goto out; |
1164 | } | 1032 | } |
1165 | 1033 | ||
1166 | wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), | 1034 | wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL); |
1167 | GFP_KERNEL); | ||
1168 | |||
1169 | if (!wl->stats.fw_stats) { | 1035 | if (!wl->stats.fw_stats) { |
1170 | ret = -ENOMEM; | 1036 | ret = -ENOMEM; |
1171 | goto err_fw; | 1037 | goto out_remove; |
1172 | } | 1038 | } |
1173 | 1039 | ||
1174 | wl->stats.fw_stats_update = jiffies; | 1040 | wl->stats.fw_stats_update = jiffies; |
1175 | 1041 | ||
1176 | ret = wl1271_debugfs_add_files(wl, rootdir); | 1042 | ret = wl1271_debugfs_add_files(wl, rootdir); |
1043 | if (ret < 0) | ||
1044 | goto out_exit; | ||
1177 | 1045 | ||
1046 | ret = wlcore_debugfs_init(wl, rootdir); | ||
1178 | if (ret < 0) | 1047 | if (ret < 0) |
1179 | goto err_file; | 1048 | goto out_exit; |
1180 | 1049 | ||
1181 | return 0; | 1050 | goto out; |
1182 | 1051 | ||
1183 | err_file: | 1052 | out_exit: |
1184 | kfree(wl->stats.fw_stats); | 1053 | wl1271_debugfs_exit(wl); |
1185 | wl->stats.fw_stats = NULL; | ||
1186 | 1054 | ||
1187 | err_fw: | 1055 | out_remove: |
1188 | debugfs_remove_recursive(rootdir); | 1056 | debugfs_remove_recursive(rootdir); |
1189 | 1057 | ||
1190 | err: | 1058 | out: |
1191 | return ret; | 1059 | return ret; |
1192 | } | 1060 | } |
1193 | 1061 | ||
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index a8d3aef011ff..f7381dd69009 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h | |||
@@ -26,8 +26,95 @@ | |||
26 | 26 | ||
27 | #include "wlcore.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_format_buffer(char __user *userbuf, size_t count, | ||
30 | loff_t *ppos, char *fmt, ...); | ||
31 | |||
29 | int wl1271_debugfs_init(struct wl1271 *wl); | 32 | int wl1271_debugfs_init(struct wl1271 *wl); |
30 | void wl1271_debugfs_exit(struct wl1271 *wl); | 33 | void wl1271_debugfs_exit(struct wl1271 *wl); |
31 | void wl1271_debugfs_reset(struct wl1271 *wl); | 34 | void wl1271_debugfs_reset(struct wl1271 *wl); |
35 | void wl1271_debugfs_update_stats(struct wl1271 *wl); | ||
36 | |||
37 | #define DEBUGFS_FORMAT_BUFFER_SIZE 256 | ||
38 | |||
39 | #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ | ||
40 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | ||
41 | size_t count, loff_t *ppos) \ | ||
42 | { \ | ||
43 | struct wl1271 *wl = file->private_data; \ | ||
44 | return wl1271_format_buffer(userbuf, count, ppos, \ | ||
45 | fmt "\n", ##value); \ | ||
46 | } \ | ||
47 | \ | ||
48 | static const struct file_operations name## _ops = { \ | ||
49 | .read = name## _read, \ | ||
50 | .open = simple_open, \ | ||
51 | .llseek = generic_file_llseek, \ | ||
52 | }; | ||
53 | |||
54 | #define DEBUGFS_ADD(name, parent) \ | ||
55 | do { \ | ||
56 | entry = debugfs_create_file(#name, 0400, parent, \ | ||
57 | wl, &name## _ops); \ | ||
58 | if (!entry || IS_ERR(entry)) \ | ||
59 | goto err; \ | ||
60 | } while (0); | ||
61 | |||
62 | |||
63 | #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ | ||
64 | do { \ | ||
65 | entry = debugfs_create_file(#name, 0400, parent, \ | ||
66 | wl, &prefix## _## name## _ops); \ | ||
67 | if (!entry || IS_ERR(entry)) \ | ||
68 | goto err; \ | ||
69 | } while (0); | ||
70 | |||
71 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \ | ||
72 | static ssize_t sub## _ ##name## _read(struct file *file, \ | ||
73 | char __user *userbuf, \ | ||
74 | size_t count, loff_t *ppos) \ | ||
75 | { \ | ||
76 | struct wl1271 *wl = file->private_data; \ | ||
77 | struct struct_type *stats = wl->stats.fw_stats; \ | ||
78 | \ | ||
79 | wl1271_debugfs_update_stats(wl); \ | ||
80 | \ | ||
81 | return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ | ||
82 | stats->sub.name); \ | ||
83 | } \ | ||
84 | \ | ||
85 | static const struct file_operations sub## _ ##name## _ops = { \ | ||
86 | .read = sub## _ ##name## _read, \ | ||
87 | .open = simple_open, \ | ||
88 | .llseek = generic_file_llseek, \ | ||
89 | }; | ||
90 | |||
91 | #define DEBUGFS_FWSTATS_FILE_ARRAY(sub, name, len, struct_type) \ | ||
92 | static ssize_t sub## _ ##name## _read(struct file *file, \ | ||
93 | char __user *userbuf, \ | ||
94 | size_t count, loff_t *ppos) \ | ||
95 | { \ | ||
96 | struct wl1271 *wl = file->private_data; \ | ||
97 | struct struct_type *stats = wl->stats.fw_stats; \ | ||
98 | char buf[DEBUGFS_FORMAT_BUFFER_SIZE] = ""; \ | ||
99 | int res, i; \ | ||
100 | \ | ||
101 | wl1271_debugfs_update_stats(wl); \ | ||
102 | \ | ||
103 | for (i = 0; i < len; i++) \ | ||
104 | res = snprintf(buf, sizeof(buf), "%s[%d] = %d\n", \ | ||
105 | buf, i, stats->sub.name[i]); \ | ||
106 | \ | ||
107 | return wl1271_format_buffer(userbuf, count, ppos, "%s", buf); \ | ||
108 | } \ | ||
109 | \ | ||
110 | static const struct file_operations sub## _ ##name## _ops = { \ | ||
111 | .read = sub## _ ##name## _read, \ | ||
112 | .open = simple_open, \ | ||
113 | .llseek = generic_file_llseek, \ | ||
114 | }; | ||
115 | |||
116 | #define DEBUGFS_FWSTATS_ADD(sub, name) \ | ||
117 | DEBUGFS_ADD(sub## _ ##name, stats) | ||
118 | |||
32 | 119 | ||
33 | #endif /* WL1271_DEBUGFS_H */ | 120 | #endif /* WL1271_DEBUGFS_H */ |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 28e2a633c3be..c976f0409865 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -148,15 +148,33 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
148 | int delay = wl->conf.conn.synch_fail_thold * | 148 | int delay = wl->conf.conn.synch_fail_thold * |
149 | wl->conf.conn.bss_lose_timeout; | 149 | wl->conf.conn.bss_lose_timeout; |
150 | wl1271_info("Beacon loss detected."); | 150 | wl1271_info("Beacon loss detected."); |
151 | cancel_delayed_work_sync(&wl->connection_loss_work); | 151 | |
152 | /* | ||
153 | * if the work is already queued, it should take place. We | ||
154 | * don't want to delay the connection loss indication | ||
155 | * any more. | ||
156 | */ | ||
152 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, | 157 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, |
153 | msecs_to_jiffies(delay)); | 158 | msecs_to_jiffies(delay)); |
159 | |||
160 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
161 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
162 | |||
163 | ieee80211_cqm_rssi_notify( | ||
164 | vif, | ||
165 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | ||
166 | GFP_KERNEL); | ||
167 | } | ||
154 | } | 168 | } |
155 | 169 | ||
156 | if (vector & REGAINED_BSS_EVENT_ID) { | 170 | if (vector & REGAINED_BSS_EVENT_ID) { |
157 | /* TODO: check for multi-role */ | 171 | /* TODO: check for multi-role */ |
158 | wl1271_info("Beacon regained."); | 172 | wl1271_info("Beacon regained."); |
159 | cancel_delayed_work_sync(&wl->connection_loss_work); | 173 | cancel_delayed_work(&wl->connection_loss_work); |
174 | |||
175 | /* sanity check - we can't lose and gain the beacon together */ | ||
176 | WARN(vector & BSS_LOSE_EVENT_ID, | ||
177 | "Concurrent beacon loss and gain from FW"); | ||
160 | } | 178 | } |
161 | 179 | ||
162 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 180 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 9384b4d56c24..9e7787ba9610 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -119,4 +119,82 @@ static inline int wlcore_identify_fw(struct wl1271 *wl) | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline void | ||
123 | wlcore_hw_set_tx_desc_csum(struct wl1271 *wl, | ||
124 | struct wl1271_tx_hw_descr *desc, | ||
125 | struct sk_buff *skb) | ||
126 | { | ||
127 | if (!wl->ops->set_tx_desc_csum) | ||
128 | BUG_ON(1); | ||
129 | |||
130 | wl->ops->set_tx_desc_csum(wl, desc, skb); | ||
131 | } | ||
132 | |||
133 | static inline void | ||
134 | wlcore_hw_set_rx_csum(struct wl1271 *wl, | ||
135 | struct wl1271_rx_descriptor *desc, | ||
136 | struct sk_buff *skb) | ||
137 | { | ||
138 | if (wl->ops->set_rx_csum) | ||
139 | wl->ops->set_rx_csum(wl, desc, skb); | ||
140 | } | ||
141 | |||
142 | static inline u32 | ||
143 | wlcore_hw_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | ||
144 | struct wl12xx_vif *wlvif) | ||
145 | { | ||
146 | if (wl->ops->ap_get_mimo_wide_rate_mask) | ||
147 | return wl->ops->ap_get_mimo_wide_rate_mask(wl, wlvif); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static inline int | ||
153 | wlcore_debugfs_init(struct wl1271 *wl, struct dentry *rootdir) | ||
154 | { | ||
155 | if (wl->ops->debugfs_init) | ||
156 | return wl->ops->debugfs_init(wl, rootdir); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static inline int | ||
162 | wlcore_handle_static_data(struct wl1271 *wl, void *static_data) | ||
163 | { | ||
164 | if (wl->ops->handle_static_data) | ||
165 | return wl->ops->handle_static_data(wl, static_data); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static inline int | ||
171 | wlcore_hw_get_spare_blocks(struct wl1271 *wl, bool is_gem) | ||
172 | { | ||
173 | if (!wl->ops->get_spare_blocks) | ||
174 | BUG_ON(1); | ||
175 | |||
176 | return wl->ops->get_spare_blocks(wl, is_gem); | ||
177 | } | ||
178 | |||
179 | static inline int | ||
180 | wlcore_hw_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | ||
181 | struct ieee80211_vif *vif, | ||
182 | struct ieee80211_sta *sta, | ||
183 | struct ieee80211_key_conf *key_conf) | ||
184 | { | ||
185 | if (!wl->ops->set_key) | ||
186 | BUG_ON(1); | ||
187 | |||
188 | return wl->ops->set_key(wl, cmd, vif, sta, key_conf); | ||
189 | } | ||
190 | |||
191 | static inline u32 | ||
192 | wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len) | ||
193 | { | ||
194 | if (wl->ops->pre_pkt_send) | ||
195 | return wl->ops->pre_pkt_send(wl, buf_offset, last_len); | ||
196 | |||
197 | return buf_offset; | ||
198 | } | ||
199 | |||
122 | #endif | 200 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 9f89255eb6e6..645abd4b660d 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -460,6 +460,9 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
460 | /* unconditionally enable HT rates */ | 460 | /* unconditionally enable HT rates */ |
461 | supported_rates |= CONF_TX_MCS_RATES; | 461 | supported_rates |= CONF_TX_MCS_RATES; |
462 | 462 | ||
463 | /* get extra MIMO or wide-chan rates where the HW supports it */ | ||
464 | supported_rates |= wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); | ||
465 | |||
463 | /* configure unicast TX rate classes */ | 466 | /* configure unicast TX rate classes */ |
464 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | 467 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { |
465 | rc.enabled_rates = supported_rates; | 468 | rc.enabled_rates = supported_rates; |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index acef93390d3d..1156e3f578c1 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -320,46 +320,6 @@ static void wlcore_adjust_conf(struct wl1271 *wl) | |||
320 | } | 320 | } |
321 | } | 321 | } |
322 | 322 | ||
323 | static int wl1271_plt_init(struct wl1271 *wl) | ||
324 | { | ||
325 | int ret; | ||
326 | |||
327 | ret = wl->ops->hw_init(wl); | ||
328 | if (ret < 0) | ||
329 | return ret; | ||
330 | |||
331 | ret = wl1271_acx_init_mem_config(wl); | ||
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | |||
335 | ret = wl12xx_acx_mem_cfg(wl); | ||
336 | if (ret < 0) | ||
337 | goto out_free_memmap; | ||
338 | |||
339 | /* Enable data path */ | ||
340 | ret = wl1271_cmd_data_path(wl, 1); | ||
341 | if (ret < 0) | ||
342 | goto out_free_memmap; | ||
343 | |||
344 | /* Configure for CAM power saving (ie. always active) */ | ||
345 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
346 | if (ret < 0) | ||
347 | goto out_free_memmap; | ||
348 | |||
349 | /* configure PM */ | ||
350 | ret = wl1271_acx_pm_config(wl); | ||
351 | if (ret < 0) | ||
352 | goto out_free_memmap; | ||
353 | |||
354 | return 0; | ||
355 | |||
356 | out_free_memmap: | ||
357 | kfree(wl->target_mem_map); | ||
358 | wl->target_mem_map = NULL; | ||
359 | |||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | 323 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, |
364 | struct wl12xx_vif *wlvif, | 324 | struct wl12xx_vif *wlvif, |
365 | u8 hlid, u8 tx_pkts) | 325 | u8 hlid, u8 tx_pkts) |
@@ -387,7 +347,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
387 | 347 | ||
388 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, | 348 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, |
389 | struct wl12xx_vif *wlvif, | 349 | struct wl12xx_vif *wlvif, |
390 | struct wl_fw_status *status) | 350 | struct wl_fw_status_2 *status) |
391 | { | 351 | { |
392 | struct wl1271_link *lnk; | 352 | struct wl1271_link *lnk; |
393 | u32 cur_fw_ps_map; | 353 | u32 cur_fw_ps_map; |
@@ -419,7 +379,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
419 | } | 379 | } |
420 | 380 | ||
421 | static void wl12xx_fw_status(struct wl1271 *wl, | 381 | static void wl12xx_fw_status(struct wl1271 *wl, |
422 | struct wl_fw_status *status) | 382 | struct wl_fw_status_1 *status_1, |
383 | struct wl_fw_status_2 *status_2) | ||
423 | { | 384 | { |
424 | struct wl12xx_vif *wlvif; | 385 | struct wl12xx_vif *wlvif; |
425 | struct timespec ts; | 386 | struct timespec ts; |
@@ -428,37 +389,38 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
428 | int i; | 389 | int i; |
429 | size_t status_len; | 390 | size_t status_len; |
430 | 391 | ||
431 | status_len = sizeof(*status) + wl->fw_status_priv_len; | 392 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
393 | sizeof(*status_2) + wl->fw_status_priv_len; | ||
432 | 394 | ||
433 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status, | 395 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, |
434 | status_len, false); | 396 | status_len, false); |
435 | 397 | ||
436 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 398 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
437 | "drv_rx_counter = %d, tx_results_counter = %d)", | 399 | "drv_rx_counter = %d, tx_results_counter = %d)", |
438 | status->intr, | 400 | status_1->intr, |
439 | status->fw_rx_counter, | 401 | status_1->fw_rx_counter, |
440 | status->drv_rx_counter, | 402 | status_1->drv_rx_counter, |
441 | status->tx_results_counter); | 403 | status_1->tx_results_counter); |
442 | 404 | ||
443 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 405 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
444 | /* prevent wrap-around in freed-packets counter */ | 406 | /* prevent wrap-around in freed-packets counter */ |
445 | wl->tx_allocated_pkts[i] -= | 407 | wl->tx_allocated_pkts[i] -= |
446 | (status->counters.tx_released_pkts[i] - | 408 | (status_2->counters.tx_released_pkts[i] - |
447 | wl->tx_pkts_freed[i]) & 0xff; | 409 | wl->tx_pkts_freed[i]) & 0xff; |
448 | 410 | ||
449 | wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i]; | 411 | wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; |
450 | } | 412 | } |
451 | 413 | ||
452 | /* prevent wrap-around in total blocks counter */ | 414 | /* prevent wrap-around in total blocks counter */ |
453 | if (likely(wl->tx_blocks_freed <= | 415 | if (likely(wl->tx_blocks_freed <= |
454 | le32_to_cpu(status->total_released_blks))) | 416 | le32_to_cpu(status_2->total_released_blks))) |
455 | freed_blocks = le32_to_cpu(status->total_released_blks) - | 417 | freed_blocks = le32_to_cpu(status_2->total_released_blks) - |
456 | wl->tx_blocks_freed; | 418 | wl->tx_blocks_freed; |
457 | else | 419 | else |
458 | freed_blocks = 0x100000000LL - wl->tx_blocks_freed + | 420 | freed_blocks = 0x100000000LL - wl->tx_blocks_freed + |
459 | le32_to_cpu(status->total_released_blks); | 421 | le32_to_cpu(status_2->total_released_blks); |
460 | 422 | ||
461 | wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); | 423 | wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks); |
462 | 424 | ||
463 | wl->tx_allocated_blocks -= freed_blocks; | 425 | wl->tx_allocated_blocks -= freed_blocks; |
464 | 426 | ||
@@ -474,7 +436,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
474 | cancel_delayed_work(&wl->tx_watchdog_work); | 436 | cancel_delayed_work(&wl->tx_watchdog_work); |
475 | } | 437 | } |
476 | 438 | ||
477 | avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; | 439 | avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks; |
478 | 440 | ||
479 | /* | 441 | /* |
480 | * The FW might change the total number of TX memblocks before | 442 | * The FW might change the total number of TX memblocks before |
@@ -493,13 +455,13 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
493 | 455 | ||
494 | /* for AP update num of allocated TX blocks per link and ps status */ | 456 | /* for AP update num of allocated TX blocks per link and ps status */ |
495 | wl12xx_for_each_wlvif_ap(wl, wlvif) { | 457 | wl12xx_for_each_wlvif_ap(wl, wlvif) { |
496 | wl12xx_irq_update_links_status(wl, wlvif, status); | 458 | wl12xx_irq_update_links_status(wl, wlvif, status_2); |
497 | } | 459 | } |
498 | 460 | ||
499 | /* update the host-chipset time offset */ | 461 | /* update the host-chipset time offset */ |
500 | getnstimeofday(&ts); | 462 | getnstimeofday(&ts); |
501 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 463 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
502 | (s64)le32_to_cpu(status->fw_localtime); | 464 | (s64)le32_to_cpu(status_2->fw_localtime); |
503 | } | 465 | } |
504 | 466 | ||
505 | static void wl1271_flush_deferred_work(struct wl1271 *wl) | 467 | static void wl1271_flush_deferred_work(struct wl1271 *wl) |
@@ -568,20 +530,30 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
568 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | 530 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); |
569 | smp_mb__after_clear_bit(); | 531 | smp_mb__after_clear_bit(); |
570 | 532 | ||
571 | wl12xx_fw_status(wl, wl->fw_status); | 533 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
572 | 534 | ||
573 | wlcore_hw_tx_immediate_compl(wl); | 535 | wlcore_hw_tx_immediate_compl(wl); |
574 | 536 | ||
575 | intr = le32_to_cpu(wl->fw_status->intr); | 537 | intr = le32_to_cpu(wl->fw_status_1->intr); |
576 | intr &= WL1271_INTR_MASK; | 538 | intr &= WLCORE_ALL_INTR_MASK; |
577 | if (!intr) { | 539 | if (!intr) { |
578 | done = true; | 540 | done = true; |
579 | continue; | 541 | continue; |
580 | } | 542 | } |
581 | 543 | ||
582 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { | 544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { |
583 | wl1271_error("watchdog interrupt received! " | 545 | wl1271_error("HW watchdog interrupt received! starting recovery."); |
546 | wl->watchdog_recovery = true; | ||
547 | wl12xx_queue_recovery_work(wl); | ||
548 | |||
549 | /* restarting the chip. ignore any other interrupt. */ | ||
550 | goto out; | ||
551 | } | ||
552 | |||
553 | if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) { | ||
554 | wl1271_error("SW watchdog interrupt received! " | ||
584 | "starting recovery."); | 555 | "starting recovery."); |
556 | wl->watchdog_recovery = true; | ||
585 | wl12xx_queue_recovery_work(wl); | 557 | wl12xx_queue_recovery_work(wl); |
586 | 558 | ||
587 | /* restarting the chip. ignore any other interrupt. */ | 559 | /* restarting the chip. ignore any other interrupt. */ |
@@ -591,7 +563,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
591 | if (likely(intr & WL1271_ACX_INTR_DATA)) { | 563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { |
592 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
593 | 565 | ||
594 | wl12xx_rx(wl, wl->fw_status); | 566 | wl12xx_rx(wl, wl->fw_status_1); |
595 | 567 | ||
596 | /* Check if any tx blocks were freed */ | 568 | /* Check if any tx blocks were freed */ |
597 | spin_lock_irqsave(&wl->wl_lock, flags); | 569 | spin_lock_irqsave(&wl->wl_lock, flags); |
@@ -743,7 +715,7 @@ out: | |||
743 | return ret; | 715 | return ret; |
744 | } | 716 | } |
745 | 717 | ||
746 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 718 | static void wl1271_fetch_nvs(struct wl1271 *wl) |
747 | { | 719 | { |
748 | const struct firmware *fw; | 720 | const struct firmware *fw; |
749 | int ret; | 721 | int ret; |
@@ -751,16 +723,15 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
751 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); | 723 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); |
752 | 724 | ||
753 | if (ret < 0) { | 725 | if (ret < 0) { |
754 | wl1271_error("could not get nvs file %s: %d", WL12XX_NVS_NAME, | 726 | wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d", |
755 | ret); | 727 | WL12XX_NVS_NAME, ret); |
756 | return ret; | 728 | return; |
757 | } | 729 | } |
758 | 730 | ||
759 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); | 731 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); |
760 | 732 | ||
761 | if (!wl->nvs) { | 733 | if (!wl->nvs) { |
762 | wl1271_error("could not allocate memory for the nvs file"); | 734 | wl1271_error("could not allocate memory for the nvs file"); |
763 | ret = -ENOMEM; | ||
764 | goto out; | 735 | goto out; |
765 | } | 736 | } |
766 | 737 | ||
@@ -768,8 +739,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
768 | 739 | ||
769 | out: | 740 | out: |
770 | release_firmware(fw); | 741 | release_firmware(fw); |
771 | |||
772 | return ret; | ||
773 | } | 742 | } |
774 | 743 | ||
775 | void wl12xx_queue_recovery_work(struct wl1271 *wl) | 744 | void wl12xx_queue_recovery_work(struct wl1271 *wl) |
@@ -820,14 +789,16 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
820 | 789 | ||
821 | /* | 790 | /* |
822 | * Make sure the chip is awake and the logger isn't active. | 791 | * Make sure the chip is awake and the logger isn't active. |
823 | * This might fail if the firmware hanged. | 792 | * Do not send a stop fwlog command if the fw is hanged. |
824 | */ | 793 | */ |
825 | if (!wl1271_ps_elp_wakeup(wl)) | 794 | if (!wl1271_ps_elp_wakeup(wl) && !wl->watchdog_recovery) |
826 | wl12xx_cmd_stop_fwlog(wl); | 795 | wl12xx_cmd_stop_fwlog(wl); |
796 | else | ||
797 | goto out; | ||
827 | 798 | ||
828 | /* Read the first memory block address */ | 799 | /* Read the first memory block address */ |
829 | wl12xx_fw_status(wl, wl->fw_status); | 800 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
830 | first_addr = le32_to_cpu(wl->fw_status->log_start_addr); | 801 | first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr); |
831 | if (!first_addr) | 802 | if (!first_addr) |
832 | goto out; | 803 | goto out; |
833 | 804 | ||
@@ -872,9 +843,14 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
872 | 843 | ||
873 | wl12xx_read_fwlog_panic(wl); | 844 | wl12xx_read_fwlog_panic(wl); |
874 | 845 | ||
875 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", | 846 | /* change partitions momentarily so we can read the FW pc */ |
847 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
848 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x " | ||
849 | "hint_sts: 0x%08x", | ||
876 | wl->chip.fw_ver_str, | 850 | wl->chip.fw_ver_str, |
877 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY)); | 851 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY), |
852 | wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR)); | ||
853 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
878 | 854 | ||
879 | BUG_ON(bug_on_recovery && | 855 | BUG_ON(bug_on_recovery && |
880 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 856 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
@@ -885,8 +861,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
885 | goto out_unlock; | 861 | goto out_unlock; |
886 | } | 862 | } |
887 | 863 | ||
888 | BUG_ON(bug_on_recovery); | ||
889 | |||
890 | /* | 864 | /* |
891 | * Advance security sequence number to overcome potential progress | 865 | * Advance security sequence number to overcome potential progress |
892 | * in the firmware during recovery. This doens't hurt if the network is | 866 | * in the firmware during recovery. This doens't hurt if the network is |
@@ -900,7 +874,7 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
900 | } | 874 | } |
901 | 875 | ||
902 | /* Prevent spurious TX during FW restart */ | 876 | /* Prevent spurious TX during FW restart */ |
903 | ieee80211_stop_queues(wl->hw); | 877 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); |
904 | 878 | ||
905 | if (wl->sched_scanning) { | 879 | if (wl->sched_scanning) { |
906 | ieee80211_sched_scan_stopped(wl->hw); | 880 | ieee80211_sched_scan_stopped(wl->hw); |
@@ -914,6 +888,7 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
914 | vif = wl12xx_wlvif_to_vif(wlvif); | 888 | vif = wl12xx_wlvif_to_vif(wlvif); |
915 | __wl1271_op_remove_interface(wl, vif, false); | 889 | __wl1271_op_remove_interface(wl, vif, false); |
916 | } | 890 | } |
891 | wl->watchdog_recovery = false; | ||
917 | mutex_unlock(&wl->mutex); | 892 | mutex_unlock(&wl->mutex); |
918 | wl1271_op_stop(wl->hw); | 893 | wl1271_op_stop(wl->hw); |
919 | 894 | ||
@@ -925,9 +900,10 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
925 | * Its safe to enable TX now - the queues are stopped after a request | 900 | * Its safe to enable TX now - the queues are stopped after a request |
926 | * to restart the HW. | 901 | * to restart the HW. |
927 | */ | 902 | */ |
928 | ieee80211_wake_queues(wl->hw); | 903 | wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); |
929 | return; | 904 | return; |
930 | out_unlock: | 905 | out_unlock: |
906 | wl->watchdog_recovery = false; | ||
931 | mutex_unlock(&wl->mutex); | 907 | mutex_unlock(&wl->mutex); |
932 | } | 908 | } |
933 | 909 | ||
@@ -938,13 +914,19 @@ static void wl1271_fw_wakeup(struct wl1271 *wl) | |||
938 | 914 | ||
939 | static int wl1271_setup(struct wl1271 *wl) | 915 | static int wl1271_setup(struct wl1271 *wl) |
940 | { | 916 | { |
941 | wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL); | 917 | wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
942 | if (!wl->fw_status) | 918 | sizeof(*wl->fw_status_2) + |
919 | wl->fw_status_priv_len, GFP_KERNEL); | ||
920 | if (!wl->fw_status_1) | ||
943 | return -ENOMEM; | 921 | return -ENOMEM; |
944 | 922 | ||
923 | wl->fw_status_2 = (struct wl_fw_status_2 *) | ||
924 | (((u8 *) wl->fw_status_1) + | ||
925 | WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); | ||
926 | |||
945 | wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); | 927 | wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); |
946 | if (!wl->tx_res_if) { | 928 | if (!wl->tx_res_if) { |
947 | kfree(wl->fw_status); | 929 | kfree(wl->fw_status_1); |
948 | return -ENOMEM; | 930 | return -ENOMEM; |
949 | } | 931 | } |
950 | 932 | ||
@@ -987,13 +969,12 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | |||
987 | * simplify the code and since the performance impact is | 969 | * simplify the code and since the performance impact is |
988 | * negligible, we use the same block size for all different | 970 | * negligible, we use the same block size for all different |
989 | * chip types. | 971 | * chip types. |
972 | * | ||
973 | * Check if the bus supports blocksize alignment and, if it | ||
974 | * doesn't, make sure we don't have the quirk. | ||
990 | */ | 975 | */ |
991 | if (wl1271_set_block_size(wl)) | 976 | if (!wl1271_set_block_size(wl)) |
992 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | 977 | wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; |
993 | |||
994 | ret = wl->ops->identify_chip(wl); | ||
995 | if (ret < 0) | ||
996 | goto out; | ||
997 | 978 | ||
998 | /* TODO: make sure the lower driver has set things up correctly */ | 979 | /* TODO: make sure the lower driver has set things up correctly */ |
999 | 980 | ||
@@ -1005,13 +986,6 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | |||
1005 | if (ret < 0) | 986 | if (ret < 0) |
1006 | goto out; | 987 | goto out; |
1007 | 988 | ||
1008 | /* No NVS from netlink, try to get it from the filesystem */ | ||
1009 | if (wl->nvs == NULL) { | ||
1010 | ret = wl1271_fetch_nvs(wl); | ||
1011 | if (ret < 0) | ||
1012 | goto out; | ||
1013 | } | ||
1014 | |||
1015 | out: | 989 | out: |
1016 | return ret; | 990 | return ret; |
1017 | } | 991 | } |
@@ -1039,14 +1013,10 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1039 | if (ret < 0) | 1013 | if (ret < 0) |
1040 | goto power_off; | 1014 | goto power_off; |
1041 | 1015 | ||
1042 | ret = wl->ops->boot(wl); | 1016 | ret = wl->ops->plt_init(wl); |
1043 | if (ret < 0) | 1017 | if (ret < 0) |
1044 | goto power_off; | 1018 | goto power_off; |
1045 | 1019 | ||
1046 | ret = wl1271_plt_init(wl); | ||
1047 | if (ret < 0) | ||
1048 | goto irq_disable; | ||
1049 | |||
1050 | wl->plt = true; | 1020 | wl->plt = true; |
1051 | wl->state = WL1271_STATE_ON; | 1021 | wl->state = WL1271_STATE_ON; |
1052 | wl1271_notice("firmware booted in PLT mode (%s)", | 1022 | wl1271_notice("firmware booted in PLT mode (%s)", |
@@ -1059,19 +1029,6 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1059 | 1029 | ||
1060 | goto out; | 1030 | goto out; |
1061 | 1031 | ||
1062 | irq_disable: | ||
1063 | mutex_unlock(&wl->mutex); | ||
1064 | /* Unlocking the mutex in the middle of handling is | ||
1065 | inherently unsafe. In this case we deem it safe to do, | ||
1066 | because we need to let any possibly pending IRQ out of | ||
1067 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
1068 | work function will not do anything.) Also, any other | ||
1069 | possible concurrent operations will fail due to the | ||
1070 | current state, hence the wl1271 struct should be safe. */ | ||
1071 | wlcore_disable_interrupts(wl); | ||
1072 | wl1271_flush_deferred_work(wl); | ||
1073 | cancel_work_sync(&wl->netstack_work); | ||
1074 | mutex_lock(&wl->mutex); | ||
1075 | power_off: | 1032 | power_off: |
1076 | wl1271_power_off(wl); | 1033 | wl1271_power_off(wl); |
1077 | } | 1034 | } |
@@ -1154,9 +1111,16 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1154 | 1111 | ||
1155 | spin_lock_irqsave(&wl->wl_lock, flags); | 1112 | spin_lock_irqsave(&wl->wl_lock, flags); |
1156 | 1113 | ||
1157 | /* queue the packet */ | 1114 | /* |
1115 | * drop the packet if the link is invalid or the queue is stopped | ||
1116 | * for any reason but watermark. Watermark is a "soft"-stop so we | ||
1117 | * allow these packets through. | ||
1118 | */ | ||
1158 | if (hlid == WL12XX_INVALID_LINK_ID || | 1119 | if (hlid == WL12XX_INVALID_LINK_ID || |
1159 | (wlvif && !test_bit(hlid, wlvif->links_map))) { | 1120 | (wlvif && !test_bit(hlid, wlvif->links_map)) || |
1121 | (wlcore_is_queue_stopped(wl, q) && | ||
1122 | !wlcore_is_queue_stopped_by_reason(wl, q, | ||
1123 | WLCORE_QUEUE_STOP_REASON_WATERMARK))) { | ||
1160 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); | 1124 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); |
1161 | ieee80211_free_txskb(hw, skb); | 1125 | ieee80211_free_txskb(hw, skb); |
1162 | goto out; | 1126 | goto out; |
@@ -1174,8 +1138,8 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1174 | */ | 1138 | */ |
1175 | if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | 1139 | if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
1176 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); | 1140 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); |
1177 | ieee80211_stop_queue(wl->hw, mapping); | 1141 | wlcore_stop_queue_locked(wl, q, |
1178 | set_bit(q, &wl->stopped_queues_map); | 1142 | WLCORE_QUEUE_STOP_REASON_WATERMARK); |
1179 | } | 1143 | } |
1180 | 1144 | ||
1181 | /* | 1145 | /* |
@@ -1758,7 +1722,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1758 | cancel_delayed_work_sync(&wl->connection_loss_work); | 1722 | cancel_delayed_work_sync(&wl->connection_loss_work); |
1759 | 1723 | ||
1760 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1724 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1761 | wl12xx_tx_reset(wl, true); | 1725 | wl12xx_tx_reset(wl); |
1762 | mutex_lock(&wl->mutex); | 1726 | mutex_lock(&wl->mutex); |
1763 | 1727 | ||
1764 | wl1271_power_off(wl); | 1728 | wl1271_power_off(wl); |
@@ -1767,6 +1731,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1767 | 1731 | ||
1768 | wl->rx_counter = 0; | 1732 | wl->rx_counter = 0; |
1769 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1733 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1734 | wl->channel_type = NL80211_CHAN_NO_HT; | ||
1770 | wl->tx_blocks_available = 0; | 1735 | wl->tx_blocks_available = 0; |
1771 | wl->tx_allocated_blocks = 0; | 1736 | wl->tx_allocated_blocks = 0; |
1772 | wl->tx_results_count = 0; | 1737 | wl->tx_results_count = 0; |
@@ -1799,8 +1764,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1799 | 1764 | ||
1800 | wl1271_debugfs_reset(wl); | 1765 | wl1271_debugfs_reset(wl); |
1801 | 1766 | ||
1802 | kfree(wl->fw_status); | 1767 | kfree(wl->fw_status_1); |
1803 | wl->fw_status = NULL; | 1768 | wl->fw_status_1 = NULL; |
1769 | wl->fw_status_2 = NULL; | ||
1804 | kfree(wl->tx_res_if); | 1770 | kfree(wl->tx_res_if); |
1805 | wl->tx_res_if = NULL; | 1771 | wl->tx_res_if = NULL; |
1806 | kfree(wl->target_mem_map); | 1772 | kfree(wl->target_mem_map); |
@@ -1894,6 +1860,9 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1894 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); | 1860 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); |
1895 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); | 1861 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); |
1896 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); | 1862 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); |
1863 | wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1864 | wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
1865 | wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1897 | } else { | 1866 | } else { |
1898 | /* init ap data */ | 1867 | /* init ap data */ |
1899 | wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; | 1868 | wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; |
@@ -1903,13 +1872,19 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1903 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) | 1872 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) |
1904 | wl12xx_allocate_rate_policy(wl, | 1873 | wl12xx_allocate_rate_policy(wl, |
1905 | &wlvif->ap.ucast_rate_idx[i]); | 1874 | &wlvif->ap.ucast_rate_idx[i]); |
1875 | wlvif->basic_rate_set = CONF_TX_AP_ENABLED_RATES; | ||
1876 | /* | ||
1877 | * TODO: check if basic_rate shouldn't be | ||
1878 | * wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
1879 | * instead (the same thing for STA above). | ||
1880 | */ | ||
1881 | wlvif->basic_rate = CONF_TX_AP_ENABLED_RATES; | ||
1882 | /* TODO: this seems to be used only for STA, check it */ | ||
1883 | wlvif->rate_set = CONF_TX_AP_ENABLED_RATES; | ||
1906 | } | 1884 | } |
1907 | 1885 | ||
1908 | wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | 1886 | wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; |
1909 | wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; | 1887 | wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; |
1910 | wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1911 | wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
1912 | wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1913 | wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; | 1888 | wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; |
1914 | 1889 | ||
1915 | /* | 1890 | /* |
@@ -1919,6 +1894,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1919 | wlvif->band = wl->band; | 1894 | wlvif->band = wl->band; |
1920 | wlvif->channel = wl->channel; | 1895 | wlvif->channel = wl->channel; |
1921 | wlvif->power_level = wl->power_level; | 1896 | wlvif->power_level = wl->power_level; |
1897 | wlvif->channel_type = wl->channel_type; | ||
1922 | 1898 | ||
1923 | INIT_WORK(&wlvif->rx_streaming_enable_work, | 1899 | INIT_WORK(&wlvif->rx_streaming_enable_work, |
1924 | wl1271_rx_streaming_enable_work); | 1900 | wl1271_rx_streaming_enable_work); |
@@ -2444,7 +2420,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2444 | } else { | 2420 | } else { |
2445 | /* The current firmware only supports sched_scan in idle */ | 2421 | /* The current firmware only supports sched_scan in idle */ |
2446 | if (wl->sched_scanning) { | 2422 | if (wl->sched_scanning) { |
2447 | wl1271_scan_sched_scan_stop(wl); | 2423 | wl1271_scan_sched_scan_stop(wl, wlvif); |
2448 | ieee80211_sched_scan_stopped(wl->hw); | 2424 | ieee80211_sched_scan_stopped(wl->hw); |
2449 | } | 2425 | } |
2450 | 2426 | ||
@@ -2469,13 +2445,20 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2469 | /* if the channel changes while joined, join again */ | 2445 | /* if the channel changes while joined, join again */ |
2470 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | 2446 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && |
2471 | ((wlvif->band != conf->channel->band) || | 2447 | ((wlvif->band != conf->channel->band) || |
2472 | (wlvif->channel != channel))) { | 2448 | (wlvif->channel != channel) || |
2449 | (wlvif->channel_type != conf->channel_type))) { | ||
2473 | /* send all pending packets */ | 2450 | /* send all pending packets */ |
2474 | wl1271_tx_work_locked(wl); | 2451 | wl1271_tx_work_locked(wl); |
2475 | wlvif->band = conf->channel->band; | 2452 | wlvif->band = conf->channel->band; |
2476 | wlvif->channel = channel; | 2453 | wlvif->channel = channel; |
2454 | wlvif->channel_type = conf->channel_type; | ||
2477 | 2455 | ||
2478 | if (!is_ap) { | 2456 | if (is_ap) { |
2457 | ret = wl1271_init_ap_rates(wl, wlvif); | ||
2458 | if (ret < 0) | ||
2459 | wl1271_error("AP rate policy change failed %d", | ||
2460 | ret); | ||
2461 | } else { | ||
2479 | /* | 2462 | /* |
2480 | * FIXME: the mac80211 should really provide a fixed | 2463 | * FIXME: the mac80211 should really provide a fixed |
2481 | * rate to use here. for now, just use the smallest | 2464 | * rate to use here. for now, just use the smallest |
@@ -2583,8 +2566,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2583 | * frames, such as the deauth. To make sure those frames reach the air, | 2566 | * frames, such as the deauth. To make sure those frames reach the air, |
2584 | * wait here until the TX queue is fully flushed. | 2567 | * wait here until the TX queue is fully flushed. |
2585 | */ | 2568 | */ |
2586 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && | 2569 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || |
2587 | (conf->flags & IEEE80211_CONF_IDLE)) | 2570 | ((changed & IEEE80211_CONF_CHANGE_IDLE) && |
2571 | (conf->flags & IEEE80211_CONF_IDLE))) | ||
2588 | wl1271_tx_flush(wl); | 2572 | wl1271_tx_flush(wl); |
2589 | 2573 | ||
2590 | mutex_lock(&wl->mutex); | 2574 | mutex_lock(&wl->mutex); |
@@ -2593,6 +2577,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2593 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 2577 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
2594 | wl->band = conf->channel->band; | 2578 | wl->band = conf->channel->band; |
2595 | wl->channel = channel; | 2579 | wl->channel = channel; |
2580 | wl->channel_type = conf->channel_type; | ||
2596 | } | 2581 | } |
2597 | 2582 | ||
2598 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2583 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
@@ -2825,17 +2810,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2825 | int ret; | 2810 | int ret; |
2826 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 2811 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
2827 | 2812 | ||
2828 | /* | ||
2829 | * A role set to GEM cipher requires different Tx settings (namely | ||
2830 | * spare blocks). Note when we are in this mode so the HW can adjust. | ||
2831 | */ | ||
2832 | if (key_type == KEY_GEM) { | ||
2833 | if (action == KEY_ADD_OR_REPLACE) | ||
2834 | wlvif->is_gem = true; | ||
2835 | else if (action == KEY_REMOVE) | ||
2836 | wlvif->is_gem = false; | ||
2837 | } | ||
2838 | |||
2839 | if (is_ap) { | 2813 | if (is_ap) { |
2840 | struct wl1271_station *wl_sta; | 2814 | struct wl1271_station *wl_sta; |
2841 | u8 hlid; | 2815 | u8 hlid; |
@@ -2913,12 +2887,21 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2913 | return 0; | 2887 | return 0; |
2914 | } | 2888 | } |
2915 | 2889 | ||
2916 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2890 | static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
2917 | struct ieee80211_vif *vif, | 2891 | struct ieee80211_vif *vif, |
2918 | struct ieee80211_sta *sta, | 2892 | struct ieee80211_sta *sta, |
2919 | struct ieee80211_key_conf *key_conf) | 2893 | struct ieee80211_key_conf *key_conf) |
2920 | { | 2894 | { |
2921 | struct wl1271 *wl = hw->priv; | 2895 | struct wl1271 *wl = hw->priv; |
2896 | |||
2897 | return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); | ||
2898 | } | ||
2899 | |||
2900 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | ||
2901 | struct ieee80211_vif *vif, | ||
2902 | struct ieee80211_sta *sta, | ||
2903 | struct ieee80211_key_conf *key_conf) | ||
2904 | { | ||
2922 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 2905 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2923 | int ret; | 2906 | int ret; |
2924 | u32 tx_seq_32 = 0; | 2907 | u32 tx_seq_32 = 0; |
@@ -3029,6 +3012,7 @@ out_unlock: | |||
3029 | 3012 | ||
3030 | return ret; | 3013 | return ret; |
3031 | } | 3014 | } |
3015 | EXPORT_SYMBOL_GPL(wlcore_set_key); | ||
3032 | 3016 | ||
3033 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | 3017 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, |
3034 | struct ieee80211_vif *vif, | 3018 | struct ieee80211_vif *vif, |
@@ -3167,6 +3151,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | |||
3167 | struct ieee80211_vif *vif) | 3151 | struct ieee80211_vif *vif) |
3168 | { | 3152 | { |
3169 | struct wl1271 *wl = hw->priv; | 3153 | struct wl1271 *wl = hw->priv; |
3154 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3170 | int ret; | 3155 | int ret; |
3171 | 3156 | ||
3172 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); | 3157 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); |
@@ -3180,7 +3165,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | |||
3180 | if (ret < 0) | 3165 | if (ret < 0) |
3181 | goto out; | 3166 | goto out; |
3182 | 3167 | ||
3183 | wl1271_scan_sched_scan_stop(wl); | 3168 | wl1271_scan_sched_scan_stop(wl, wlvif); |
3184 | 3169 | ||
3185 | wl1271_ps_elp_sleep(wl); | 3170 | wl1271_ps_elp_sleep(wl); |
3186 | out: | 3171 | out: |
@@ -3316,8 +3301,15 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, | |||
3316 | skb->data, | 3301 | skb->data, |
3317 | skb->len, 0, | 3302 | skb->len, 0, |
3318 | rates); | 3303 | rates); |
3319 | |||
3320 | dev_kfree_skb(skb); | 3304 | dev_kfree_skb(skb); |
3305 | |||
3306 | if (ret < 0) | ||
3307 | goto out; | ||
3308 | |||
3309 | wl1271_debug(DEBUG_AP, "probe response updated"); | ||
3310 | set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); | ||
3311 | |||
3312 | out: | ||
3321 | return ret; | 3313 | return ret; |
3322 | } | 3314 | } |
3323 | 3315 | ||
@@ -3422,6 +3414,87 @@ out: | |||
3422 | return ret; | 3414 | return ret; |
3423 | } | 3415 | } |
3424 | 3416 | ||
3417 | static int wlcore_set_beacon_template(struct wl1271 *wl, | ||
3418 | struct ieee80211_vif *vif, | ||
3419 | bool is_ap) | ||
3420 | { | ||
3421 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3422 | struct ieee80211_hdr *hdr; | ||
3423 | u32 min_rate; | ||
3424 | int ret; | ||
3425 | int ieoffset = offsetof(struct ieee80211_mgmt, | ||
3426 | u.beacon.variable); | ||
3427 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | ||
3428 | u16 tmpl_id; | ||
3429 | |||
3430 | if (!beacon) { | ||
3431 | ret = -EINVAL; | ||
3432 | goto out; | ||
3433 | } | ||
3434 | |||
3435 | wl1271_debug(DEBUG_MASTER, "beacon updated"); | ||
3436 | |||
3437 | ret = wl1271_ssid_set(vif, beacon, ieoffset); | ||
3438 | if (ret < 0) { | ||
3439 | dev_kfree_skb(beacon); | ||
3440 | goto out; | ||
3441 | } | ||
3442 | min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
3443 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | ||
3444 | CMD_TEMPL_BEACON; | ||
3445 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, | ||
3446 | beacon->data, | ||
3447 | beacon->len, 0, | ||
3448 | min_rate); | ||
3449 | if (ret < 0) { | ||
3450 | dev_kfree_skb(beacon); | ||
3451 | goto out; | ||
3452 | } | ||
3453 | |||
3454 | /* | ||
3455 | * In case we already have a probe-resp beacon set explicitly | ||
3456 | * by usermode, don't use the beacon data. | ||
3457 | */ | ||
3458 | if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) | ||
3459 | goto end_bcn; | ||
3460 | |||
3461 | /* remove TIM ie from probe response */ | ||
3462 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); | ||
3463 | |||
3464 | /* | ||
3465 | * remove p2p ie from probe response. | ||
3466 | * the fw reponds to probe requests that don't include | ||
3467 | * the p2p ie. probe requests with p2p ie will be passed, | ||
3468 | * and will be responded by the supplicant (the spec | ||
3469 | * forbids including the p2p ie when responding to probe | ||
3470 | * requests that didn't include it). | ||
3471 | */ | ||
3472 | wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, | ||
3473 | WLAN_OUI_TYPE_WFA_P2P, ieoffset); | ||
3474 | |||
3475 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
3476 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
3477 | IEEE80211_STYPE_PROBE_RESP); | ||
3478 | if (is_ap) | ||
3479 | ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, | ||
3480 | beacon->data, | ||
3481 | beacon->len, | ||
3482 | min_rate); | ||
3483 | else | ||
3484 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, | ||
3485 | CMD_TEMPL_PROBE_RESPONSE, | ||
3486 | beacon->data, | ||
3487 | beacon->len, 0, | ||
3488 | min_rate); | ||
3489 | end_bcn: | ||
3490 | dev_kfree_skb(beacon); | ||
3491 | if (ret < 0) | ||
3492 | goto out; | ||
3493 | |||
3494 | out: | ||
3495 | return ret; | ||
3496 | } | ||
3497 | |||
3425 | static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | 3498 | static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, |
3426 | struct ieee80211_vif *vif, | 3499 | struct ieee80211_vif *vif, |
3427 | struct ieee80211_bss_conf *bss_conf, | 3500 | struct ieee80211_bss_conf *bss_conf, |
@@ -3440,81 +3513,12 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3440 | 3513 | ||
3441 | if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { | 3514 | if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { |
3442 | u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | 3515 | u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
3443 | if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { | 3516 | |
3444 | wl1271_debug(DEBUG_AP, "probe response updated"); | 3517 | wl1271_ap_set_probe_resp_tmpl(wl, rate, vif); |
3445 | set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); | ||
3446 | } | ||
3447 | } | 3518 | } |
3448 | 3519 | ||
3449 | if ((changed & BSS_CHANGED_BEACON)) { | 3520 | if ((changed & BSS_CHANGED_BEACON)) { |
3450 | struct ieee80211_hdr *hdr; | 3521 | ret = wlcore_set_beacon_template(wl, vif, is_ap); |
3451 | u32 min_rate; | ||
3452 | int ieoffset = offsetof(struct ieee80211_mgmt, | ||
3453 | u.beacon.variable); | ||
3454 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | ||
3455 | u16 tmpl_id; | ||
3456 | |||
3457 | if (!beacon) { | ||
3458 | ret = -EINVAL; | ||
3459 | goto out; | ||
3460 | } | ||
3461 | |||
3462 | wl1271_debug(DEBUG_MASTER, "beacon updated"); | ||
3463 | |||
3464 | ret = wl1271_ssid_set(vif, beacon, ieoffset); | ||
3465 | if (ret < 0) { | ||
3466 | dev_kfree_skb(beacon); | ||
3467 | goto out; | ||
3468 | } | ||
3469 | min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
3470 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | ||
3471 | CMD_TEMPL_BEACON; | ||
3472 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, | ||
3473 | beacon->data, | ||
3474 | beacon->len, 0, | ||
3475 | min_rate); | ||
3476 | if (ret < 0) { | ||
3477 | dev_kfree_skb(beacon); | ||
3478 | goto out; | ||
3479 | } | ||
3480 | |||
3481 | /* | ||
3482 | * In case we already have a probe-resp beacon set explicitly | ||
3483 | * by usermode, don't use the beacon data. | ||
3484 | */ | ||
3485 | if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) | ||
3486 | goto end_bcn; | ||
3487 | |||
3488 | /* remove TIM ie from probe response */ | ||
3489 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); | ||
3490 | |||
3491 | /* | ||
3492 | * remove p2p ie from probe response. | ||
3493 | * the fw reponds to probe requests that don't include | ||
3494 | * the p2p ie. probe requests with p2p ie will be passed, | ||
3495 | * and will be responded by the supplicant (the spec | ||
3496 | * forbids including the p2p ie when responding to probe | ||
3497 | * requests that didn't include it). | ||
3498 | */ | ||
3499 | wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, | ||
3500 | WLAN_OUI_TYPE_WFA_P2P, ieoffset); | ||
3501 | |||
3502 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
3503 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
3504 | IEEE80211_STYPE_PROBE_RESP); | ||
3505 | if (is_ap) | ||
3506 | ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, | ||
3507 | beacon->data, | ||
3508 | beacon->len, | ||
3509 | min_rate); | ||
3510 | else | ||
3511 | ret = wl1271_cmd_template_set(wl, wlvif->role_id, | ||
3512 | CMD_TEMPL_PROBE_RESPONSE, | ||
3513 | beacon->data, | ||
3514 | beacon->len, 0, | ||
3515 | min_rate); | ||
3516 | end_bcn: | ||
3517 | dev_kfree_skb(beacon); | ||
3518 | if (ret < 0) | 3522 | if (ret < 0) |
3519 | goto out; | 3523 | goto out; |
3520 | } | 3524 | } |
@@ -3551,6 +3555,14 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3551 | ret = wl1271_ap_init_templates(wl, vif); | 3555 | ret = wl1271_ap_init_templates(wl, vif); |
3552 | if (ret < 0) | 3556 | if (ret < 0) |
3553 | goto out; | 3557 | goto out; |
3558 | |||
3559 | ret = wl1271_ap_set_probe_resp_tmpl(wl, wlvif->basic_rate, vif); | ||
3560 | if (ret < 0) | ||
3561 | goto out; | ||
3562 | |||
3563 | ret = wlcore_set_beacon_template(wl, vif, true); | ||
3564 | if (ret < 0) | ||
3565 | goto out; | ||
3554 | } | 3566 | } |
3555 | 3567 | ||
3556 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); | 3568 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
@@ -3691,7 +3703,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3691 | sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; | 3703 | sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; |
3692 | if (sta->ht_cap.ht_supported) | 3704 | if (sta->ht_cap.ht_supported) |
3693 | sta_rate_set |= | 3705 | sta_rate_set |= |
3694 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); | 3706 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET) | |
3707 | (sta->ht_cap.mcs.rx_mask[1] << HW_MIMO_RATES_OFFSET); | ||
3695 | sta_ht_cap = sta->ht_cap; | 3708 | sta_ht_cap = sta->ht_cap; |
3696 | sta_exists = true; | 3709 | sta_exists = true; |
3697 | 3710 | ||
@@ -3704,13 +3717,11 @@ sta_not_found: | |||
3704 | u32 rates; | 3717 | u32 rates; |
3705 | int ieoffset; | 3718 | int ieoffset; |
3706 | wlvif->aid = bss_conf->aid; | 3719 | wlvif->aid = bss_conf->aid; |
3720 | wlvif->channel_type = bss_conf->channel_type; | ||
3707 | wlvif->beacon_int = bss_conf->beacon_int; | 3721 | wlvif->beacon_int = bss_conf->beacon_int; |
3708 | do_join = true; | 3722 | do_join = true; |
3709 | set_assoc = true; | 3723 | set_assoc = true; |
3710 | 3724 | ||
3711 | /* Cancel connection_loss_work */ | ||
3712 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
3713 | |||
3714 | /* | 3725 | /* |
3715 | * use basic rates from AP, and determine lowest rate | 3726 | * use basic rates from AP, and determine lowest rate |
3716 | * to use with control frames. | 3727 | * to use with control frames. |
@@ -3960,6 +3971,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3960 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", | 3971 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", |
3961 | (int)changed); | 3972 | (int)changed); |
3962 | 3973 | ||
3974 | /* | ||
3975 | * make sure to cancel pending disconnections if our association | ||
3976 | * state changed | ||
3977 | */ | ||
3978 | if (!is_ap && (changed & BSS_CHANGED_ASSOC)) | ||
3979 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
3980 | |||
3981 | if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) && | ||
3982 | !bss_conf->enable_beacon) | ||
3983 | wl1271_tx_flush(wl); | ||
3984 | |||
3963 | mutex_lock(&wl->mutex); | 3985 | mutex_lock(&wl->mutex); |
3964 | 3986 | ||
3965 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 3987 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
@@ -4636,7 +4658,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
4636 | .prepare_multicast = wl1271_op_prepare_multicast, | 4658 | .prepare_multicast = wl1271_op_prepare_multicast, |
4637 | .configure_filter = wl1271_op_configure_filter, | 4659 | .configure_filter = wl1271_op_configure_filter, |
4638 | .tx = wl1271_op_tx, | 4660 | .tx = wl1271_op_tx, |
4639 | .set_key = wl1271_op_set_key, | 4661 | .set_key = wlcore_op_set_key, |
4640 | .hw_scan = wl1271_op_hw_scan, | 4662 | .hw_scan = wl1271_op_hw_scan, |
4641 | .cancel_hw_scan = wl1271_op_cancel_hw_scan, | 4663 | .cancel_hw_scan = wl1271_op_cancel_hw_scan, |
4642 | .sched_scan_start = wl1271_op_sched_scan_start, | 4664 | .sched_scan_start = wl1271_op_sched_scan_start, |
@@ -4905,14 +4927,8 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
4905 | if (wl->mac80211_registered) | 4927 | if (wl->mac80211_registered) |
4906 | return 0; | 4928 | return 0; |
4907 | 4929 | ||
4908 | ret = wl12xx_get_hw_info(wl); | 4930 | wl1271_fetch_nvs(wl); |
4909 | if (ret < 0) { | 4931 | if (wl->nvs != NULL) { |
4910 | wl1271_error("couldn't get hw info"); | ||
4911 | goto out; | ||
4912 | } | ||
4913 | |||
4914 | ret = wl1271_fetch_nvs(wl); | ||
4915 | if (ret == 0) { | ||
4916 | /* NOTE: The wl->nvs->nvs element must be first, in | 4932 | /* NOTE: The wl->nvs->nvs element must be first, in |
4917 | * order to simplify the casting, we assume it is at | 4933 | * order to simplify the casting, we assume it is at |
4918 | * the beginning of the wl->nvs structure. | 4934 | * the beginning of the wl->nvs structure. |
@@ -4970,9 +4986,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4970 | WL1271_CIPHER_SUITE_GEM, | 4986 | WL1271_CIPHER_SUITE_GEM, |
4971 | }; | 4987 | }; |
4972 | 4988 | ||
4973 | /* The tx descriptor buffer and the TKIP space. */ | 4989 | /* The tx descriptor buffer */ |
4974 | wl->hw->extra_tx_headroom = WL1271_EXTRA_SPACE_TKIP + | 4990 | wl->hw->extra_tx_headroom = sizeof(struct wl1271_tx_hw_descr); |
4975 | sizeof(struct wl1271_tx_hw_descr); | 4991 | |
4992 | if (wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) | ||
4993 | wl->hw->extra_tx_headroom += WL1271_EXTRA_SPACE_TKIP; | ||
4976 | 4994 | ||
4977 | /* unit us */ | 4995 | /* unit us */ |
4978 | /* FIXME: find a proper value */ | 4996 | /* FIXME: find a proper value */ |
@@ -5025,12 +5043,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5025 | */ | 5043 | */ |
5026 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, | 5044 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, |
5027 | sizeof(wl1271_band_2ghz)); | 5045 | sizeof(wl1271_band_2ghz)); |
5028 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, &wl->ht_cap, | 5046 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, |
5029 | sizeof(wl->ht_cap)); | 5047 | &wl->ht_cap[IEEE80211_BAND_2GHZ], |
5048 | sizeof(*wl->ht_cap)); | ||
5030 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, | 5049 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, |
5031 | sizeof(wl1271_band_5ghz)); | 5050 | sizeof(wl1271_band_5ghz)); |
5032 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, &wl->ht_cap, | 5051 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, |
5033 | sizeof(wl->ht_cap)); | 5052 | &wl->ht_cap[IEEE80211_BAND_5GHZ], |
5053 | sizeof(*wl->ht_cap)); | ||
5034 | 5054 | ||
5035 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 5055 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
5036 | &wl->bands[IEEE80211_BAND_2GHZ]; | 5056 | &wl->bands[IEEE80211_BAND_2GHZ]; |
@@ -5117,6 +5137,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
5117 | wl->rx_counter = 0; | 5137 | wl->rx_counter = 0; |
5118 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 5138 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
5119 | wl->band = IEEE80211_BAND_2GHZ; | 5139 | wl->band = IEEE80211_BAND_2GHZ; |
5140 | wl->channel_type = NL80211_CHAN_NO_HT; | ||
5120 | wl->flags = 0; | 5141 | wl->flags = 0; |
5121 | wl->sg_enabled = true; | 5142 | wl->sg_enabled = true; |
5122 | wl->hw_pg_ver = -1; | 5143 | wl->hw_pg_ver = -1; |
@@ -5142,6 +5163,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
5142 | wl->state = WL1271_STATE_OFF; | 5163 | wl->state = WL1271_STATE_OFF; |
5143 | wl->fw_type = WL12XX_FW_TYPE_NONE; | 5164 | wl->fw_type = WL12XX_FW_TYPE_NONE; |
5144 | mutex_init(&wl->mutex); | 5165 | mutex_init(&wl->mutex); |
5166 | mutex_init(&wl->flush_mutex); | ||
5145 | 5167 | ||
5146 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | 5168 | order = get_order(WL1271_AGGR_BUFFER_SIZE); |
5147 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | 5169 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); |
@@ -5222,7 +5244,7 @@ int wlcore_free_hw(struct wl1271 *wl) | |||
5222 | kfree(wl->nvs); | 5244 | kfree(wl->nvs); |
5223 | wl->nvs = NULL; | 5245 | wl->nvs = NULL; |
5224 | 5246 | ||
5225 | kfree(wl->fw_status); | 5247 | kfree(wl->fw_status_1); |
5226 | kfree(wl->tx_res_if); | 5248 | kfree(wl->tx_res_if); |
5227 | destroy_workqueue(wl->freezable_wq); | 5249 | destroy_workqueue(wl->freezable_wq); |
5228 | 5250 | ||
@@ -5279,8 +5301,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5279 | wlcore_adjust_conf(wl); | 5301 | wlcore_adjust_conf(wl); |
5280 | 5302 | ||
5281 | wl->irq = platform_get_irq(pdev, 0); | 5303 | wl->irq = platform_get_irq(pdev, 0); |
5282 | wl->ref_clock = pdata->board_ref_clock; | ||
5283 | wl->tcxo_clock = pdata->board_tcxo_clock; | ||
5284 | wl->platform_quirks = pdata->platform_quirks; | 5304 | wl->platform_quirks = pdata->platform_quirks; |
5285 | wl->set_power = pdata->set_power; | 5305 | wl->set_power = pdata->set_power; |
5286 | wl->dev = &pdev->dev; | 5306 | wl->dev = &pdev->dev; |
@@ -5316,6 +5336,16 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5316 | } | 5336 | } |
5317 | disable_irq(wl->irq); | 5337 | disable_irq(wl->irq); |
5318 | 5338 | ||
5339 | ret = wl12xx_get_hw_info(wl); | ||
5340 | if (ret < 0) { | ||
5341 | wl1271_error("couldn't get hw info"); | ||
5342 | goto out; | ||
5343 | } | ||
5344 | |||
5345 | ret = wl->ops->identify_chip(wl); | ||
5346 | if (ret < 0) | ||
5347 | goto out; | ||
5348 | |||
5319 | ret = wl1271_init_ieee80211(wl); | 5349 | ret = wl1271_init_ieee80211(wl); |
5320 | if (ret) | 5350 | if (ret) |
5321 | goto out_irq; | 5351 | goto out_irq; |
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 756eee2257b4..47e81b32f7da 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #define WL1271_WAKEUP_TIMEOUT 500 | 29 | #define WL1271_WAKEUP_TIMEOUT 500 |
30 | 30 | ||
31 | #define ELP_ENTRY_DELAY 5 | ||
32 | |||
31 | void wl1271_elp_work(struct work_struct *work) | 33 | void wl1271_elp_work(struct work_struct *work) |
32 | { | 34 | { |
33 | struct delayed_work *dwork; | 35 | struct delayed_work *dwork; |
@@ -72,6 +74,7 @@ out: | |||
72 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 74 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
73 | { | 75 | { |
74 | struct wl12xx_vif *wlvif; | 76 | struct wl12xx_vif *wlvif; |
77 | u32 timeout; | ||
75 | 78 | ||
76 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) | 79 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) |
77 | return; | 80 | return; |
@@ -89,8 +92,13 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
89 | return; | 92 | return; |
90 | } | 93 | } |
91 | 94 | ||
95 | if (wl->conf.conn.forced_ps) | ||
96 | timeout = ELP_ENTRY_DELAY; | ||
97 | else | ||
98 | timeout = wl->conf.conn.dynamic_ps_timeout; | ||
99 | |||
92 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 100 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
93 | msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout)); | 101 | msecs_to_jiffies(timeout)); |
94 | } | 102 | } |
95 | 103 | ||
96 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) | 104 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) |
@@ -185,8 +193,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
185 | 193 | ||
186 | set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); | 194 | set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); |
187 | 195 | ||
188 | /* enable beacon early termination. Not relevant for 5GHz */ | 196 | /* |
189 | if (wlvif->band == IEEE80211_BAND_2GHZ) { | 197 | * enable beacon early termination. |
198 | * Not relevant for 5GHz and for high rates. | ||
199 | */ | ||
200 | if ((wlvif->band == IEEE80211_BAND_2GHZ) && | ||
201 | (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { | ||
190 | ret = wl1271_acx_bet_enable(wl, wlvif, true); | 202 | ret = wl1271_acx_bet_enable(wl, wlvif, true); |
191 | if (ret < 0) | 203 | if (ret < 0) |
192 | return ret; | 204 | return ret; |
@@ -196,7 +208,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
196 | wl1271_debug(DEBUG_PSM, "leaving psm"); | 208 | wl1271_debug(DEBUG_PSM, "leaving psm"); |
197 | 209 | ||
198 | /* disable beacon early termination */ | 210 | /* disable beacon early termination */ |
199 | if (wlvif->band == IEEE80211_BAND_2GHZ) { | 211 | if ((wlvif->band == IEEE80211_BAND_2GHZ) && |
212 | (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { | ||
200 | ret = wl1271_acx_bet_enable(wl, wlvif, false); | 213 | ret = wl1271_acx_bet_enable(wl, wlvif, false); |
201 | if (ret < 0) | 214 | if (ret < 0) |
202 | return ret; | 215 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index d6a3c6b07827..78200dcacfca 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -186,6 +186,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
186 | is_data = 1; | 186 | is_data = 1; |
187 | 187 | ||
188 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 188 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
189 | wlcore_hw_set_rx_csum(wl, desc, skb); | ||
189 | 190 | ||
190 | seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | 191 | seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; |
191 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, | 192 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, |
@@ -199,12 +200,12 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
199 | return is_data; | 200 | return is_data; |
200 | } | 201 | } |
201 | 202 | ||
202 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) | 203 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) |
203 | { | 204 | { |
204 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
205 | u32 buf_size; | 206 | u32 buf_size; |
206 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 207 | u32 fw_rx_counter = status->fw_rx_counter % wl->num_rx_desc; |
207 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 208 | u32 drv_rx_counter = wl->rx_counter % wl->num_rx_desc; |
208 | u32 rx_counter; | 209 | u32 rx_counter; |
209 | u32 pkt_len, align_pkt_len; | 210 | u32 pkt_len, align_pkt_len; |
210 | u32 pkt_offset, des; | 211 | u32 pkt_offset, des; |
@@ -223,7 +224,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) | |||
223 | break; | 224 | break; |
224 | buf_size += align_pkt_len; | 225 | buf_size += align_pkt_len; |
225 | rx_counter++; | 226 | rx_counter++; |
226 | rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | 227 | rx_counter %= wl->num_rx_desc; |
227 | } | 228 | } |
228 | 229 | ||
229 | if (buf_size == 0) { | 230 | if (buf_size == 0) { |
@@ -263,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) | |||
263 | 264 | ||
264 | wl->rx_counter++; | 265 | wl->rx_counter++; |
265 | drv_rx_counter++; | 266 | drv_rx_counter++; |
266 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | 267 | drv_rx_counter %= wl->num_rx_desc; |
267 | pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len); | 268 | pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len); |
268 | } | 269 | } |
269 | } | 270 | } |
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index e9a162a864ca..9be780179456 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -38,8 +38,6 @@ | |||
38 | #define RX_DESC_PACKETID_SHIFT 11 | 38 | #define RX_DESC_PACKETID_SHIFT 11 |
39 | #define RX_MAX_PACKET_ID 3 | 39 | #define RX_MAX_PACKET_ID 3 |
40 | 40 | ||
41 | #define NUM_RX_PKT_DESC_MOD_MASK 7 | ||
42 | |||
43 | #define RX_DESC_VALID_FCS 0x0001 | 41 | #define RX_DESC_VALID_FCS 0x0001 |
44 | #define RX_DESC_MATCH_RXADDR1 0x0002 | 42 | #define RX_DESC_MATCH_RXADDR1 0x0002 |
45 | #define RX_DESC_MCAST 0x0004 | 43 | #define RX_DESC_MCAST 0x0004 |
@@ -102,6 +100,9 @@ | |||
102 | /* If set, the start of IP payload is not 4 bytes aligned */ | 100 | /* If set, the start of IP payload is not 4 bytes aligned */ |
103 | #define RX_BUF_UNALIGNED_PAYLOAD BIT(20) | 101 | #define RX_BUF_UNALIGNED_PAYLOAD BIT(20) |
104 | 102 | ||
103 | /* If set, the buffer was padded by the FW to be 4 bytes aligned */ | ||
104 | #define RX_BUF_PADDED_PAYLOAD BIT(30) | ||
105 | |||
105 | /* Describes the alignment state of a Rx buffer */ | 106 | /* Describes the alignment state of a Rx buffer */ |
106 | enum wl_rx_buf_align { | 107 | enum wl_rx_buf_align { |
107 | WLCORE_RX_BUF_ALIGNED, | 108 | WLCORE_RX_BUF_ALIGNED, |
@@ -136,7 +137,7 @@ struct wl1271_rx_descriptor { | |||
136 | u8 reserved; | 137 | u8 reserved; |
137 | } __packed; | 138 | } __packed; |
138 | 139 | ||
139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); | 140 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); |
140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 141 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
141 | int wl1271_rx_filter_enable(struct wl1271 *wl, | 142 | int wl1271_rx_filter_enable(struct wl1271 *wl, |
142 | int index, bool enable, | 143 | int index, bool enable, |
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index ade21a011c45..d9daed53ceb7 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
@@ -411,7 +411,8 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
411 | struct cfg80211_sched_scan_request *req, | 411 | struct cfg80211_sched_scan_request *req, |
412 | struct conn_scan_ch_params *channels, | 412 | struct conn_scan_ch_params *channels, |
413 | u32 band, bool radar, bool passive, | 413 | u32 band, bool radar, bool passive, |
414 | int start, int max_channels) | 414 | int start, int max_channels, |
415 | u8 *n_pactive_ch) | ||
415 | { | 416 | { |
416 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | 417 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; |
417 | int i, j; | 418 | int i, j; |
@@ -479,6 +480,23 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
479 | channels[j].tx_power_att = req->channels[i]->max_power; | 480 | channels[j].tx_power_att = req->channels[i]->max_power; |
480 | channels[j].channel = req->channels[i]->hw_value; | 481 | channels[j].channel = req->channels[i]->hw_value; |
481 | 482 | ||
483 | if ((band == IEEE80211_BAND_2GHZ) && | ||
484 | (channels[j].channel >= 12) && | ||
485 | (channels[j].channel <= 14) && | ||
486 | (flags & IEEE80211_CHAN_PASSIVE_SCAN) && | ||
487 | !force_passive) { | ||
488 | /* pactive channels treated as DFS */ | ||
489 | channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; | ||
490 | |||
491 | /* | ||
492 | * n_pactive_ch is counted down from the end of | ||
493 | * the passive channel list | ||
494 | */ | ||
495 | (*n_pactive_ch)++; | ||
496 | wl1271_debug(DEBUG_SCAN, "n_pactive_ch = %d", | ||
497 | *n_pactive_ch); | ||
498 | } | ||
499 | |||
482 | j++; | 500 | j++; |
483 | } | 501 | } |
484 | } | 502 | } |
@@ -491,38 +509,47 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, | |||
491 | struct cfg80211_sched_scan_request *req, | 509 | struct cfg80211_sched_scan_request *req, |
492 | struct wl1271_cmd_sched_scan_config *cfg) | 510 | struct wl1271_cmd_sched_scan_config *cfg) |
493 | { | 511 | { |
512 | u8 n_pactive_ch = 0; | ||
513 | |||
494 | cfg->passive[0] = | 514 | cfg->passive[0] = |
495 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, | 515 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, |
496 | IEEE80211_BAND_2GHZ, | 516 | IEEE80211_BAND_2GHZ, |
497 | false, true, 0, | 517 | false, true, 0, |
498 | MAX_CHANNELS_2GHZ); | 518 | MAX_CHANNELS_2GHZ, |
519 | &n_pactive_ch); | ||
499 | cfg->active[0] = | 520 | cfg->active[0] = |
500 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, | 521 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, |
501 | IEEE80211_BAND_2GHZ, | 522 | IEEE80211_BAND_2GHZ, |
502 | false, false, | 523 | false, false, |
503 | cfg->passive[0], | 524 | cfg->passive[0], |
504 | MAX_CHANNELS_2GHZ); | 525 | MAX_CHANNELS_2GHZ, |
526 | &n_pactive_ch); | ||
505 | cfg->passive[1] = | 527 | cfg->passive[1] = |
506 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 528 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, |
507 | IEEE80211_BAND_5GHZ, | 529 | IEEE80211_BAND_5GHZ, |
508 | false, true, 0, | 530 | false, true, 0, |
509 | MAX_CHANNELS_5GHZ); | 531 | MAX_CHANNELS_5GHZ, |
532 | &n_pactive_ch); | ||
510 | cfg->dfs = | 533 | cfg->dfs = |
511 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 534 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, |
512 | IEEE80211_BAND_5GHZ, | 535 | IEEE80211_BAND_5GHZ, |
513 | true, true, | 536 | true, true, |
514 | cfg->passive[1], | 537 | cfg->passive[1], |
515 | MAX_CHANNELS_5GHZ); | 538 | MAX_CHANNELS_5GHZ, |
539 | &n_pactive_ch); | ||
516 | cfg->active[1] = | 540 | cfg->active[1] = |
517 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, | 541 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, |
518 | IEEE80211_BAND_5GHZ, | 542 | IEEE80211_BAND_5GHZ, |
519 | false, false, | 543 | false, false, |
520 | cfg->passive[1] + cfg->dfs, | 544 | cfg->passive[1] + cfg->dfs, |
521 | MAX_CHANNELS_5GHZ); | 545 | MAX_CHANNELS_5GHZ, |
546 | &n_pactive_ch); | ||
522 | /* 802.11j channels are not supported yet */ | 547 | /* 802.11j channels are not supported yet */ |
523 | cfg->passive[2] = 0; | 548 | cfg->passive[2] = 0; |
524 | cfg->active[2] = 0; | 549 | cfg->active[2] = 0; |
525 | 550 | ||
551 | cfg->n_pactive_ch = n_pactive_ch; | ||
552 | |||
526 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", | 553 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", |
527 | cfg->active[0], cfg->passive[0]); | 554 | cfg->active[0], cfg->passive[0]); |
528 | wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", | 555 | wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", |
@@ -537,6 +564,7 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, | |||
537 | /* Returns the scan type to be used or a negative value on error */ | 564 | /* Returns the scan type to be used or a negative value on error */ |
538 | static int | 565 | static int |
539 | wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | 566 | wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, |
567 | struct wl12xx_vif *wlvif, | ||
540 | struct cfg80211_sched_scan_request *req) | 568 | struct cfg80211_sched_scan_request *req) |
541 | { | 569 | { |
542 | struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; | 570 | struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; |
@@ -565,6 +593,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | |||
565 | goto out; | 593 | goto out; |
566 | } | 594 | } |
567 | 595 | ||
596 | cmd->role_id = wlvif->dev_role_id; | ||
568 | if (!n_match_ssids) { | 597 | if (!n_match_ssids) { |
569 | /* No filter, with ssids */ | 598 | /* No filter, with ssids */ |
570 | type = SCAN_SSID_FILTER_DISABLED; | 599 | type = SCAN_SSID_FILTER_DISABLED; |
@@ -603,7 +632,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | |||
603 | continue; | 632 | continue; |
604 | 633 | ||
605 | for (j = 0; j < cmd->n_ssids; j++) | 634 | for (j = 0; j < cmd->n_ssids; j++) |
606 | if (!memcmp(req->ssids[i].ssid, | 635 | if ((req->ssids[i].ssid_len == |
636 | req->ssids[j].ssid_len) && | ||
637 | !memcmp(req->ssids[i].ssid, | ||
607 | cmd->ssids[j].ssid, | 638 | cmd->ssids[j].ssid, |
608 | req->ssids[i].ssid_len)) { | 639 | req->ssids[i].ssid_len)) { |
609 | cmd->ssids[j].type = | 640 | cmd->ssids[j].type = |
@@ -652,6 +683,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
652 | if (!cfg) | 683 | if (!cfg) |
653 | return -ENOMEM; | 684 | return -ENOMEM; |
654 | 685 | ||
686 | cfg->role_id = wlvif->dev_role_id; | ||
655 | cfg->rssi_threshold = c->rssi_threshold; | 687 | cfg->rssi_threshold = c->rssi_threshold; |
656 | cfg->snr_threshold = c->snr_threshold; | 688 | cfg->snr_threshold = c->snr_threshold; |
657 | cfg->n_probe_reqs = c->num_probe_reqs; | 689 | cfg->n_probe_reqs = c->num_probe_reqs; |
@@ -669,7 +701,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
669 | cfg->intervals[i] = cpu_to_le32(req->interval); | 701 | cfg->intervals[i] = cpu_to_le32(req->interval); |
670 | 702 | ||
671 | cfg->ssid_len = 0; | 703 | cfg->ssid_len = 0; |
672 | ret = wl12xx_scan_sched_scan_ssid_list(wl, req); | 704 | ret = wl12xx_scan_sched_scan_ssid_list(wl, wlvif, req); |
673 | if (ret < 0) | 705 | if (ret < 0) |
674 | goto out; | 706 | goto out; |
675 | 707 | ||
@@ -741,6 +773,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
741 | if (!start) | 773 | if (!start) |
742 | return -ENOMEM; | 774 | return -ENOMEM; |
743 | 775 | ||
776 | start->role_id = wlvif->dev_role_id; | ||
744 | start->tag = WL1271_SCAN_DEFAULT_TAG; | 777 | start->tag = WL1271_SCAN_DEFAULT_TAG; |
745 | 778 | ||
746 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, | 779 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, |
@@ -762,7 +795,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl) | |||
762 | ieee80211_sched_scan_results(wl->hw); | 795 | ieee80211_sched_scan_results(wl->hw); |
763 | } | 796 | } |
764 | 797 | ||
765 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl) | 798 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
766 | { | 799 | { |
767 | struct wl1271_cmd_sched_scan_stop *stop; | 800 | struct wl1271_cmd_sched_scan_stop *stop; |
768 | int ret = 0; | 801 | int ret = 0; |
@@ -776,6 +809,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl) | |||
776 | return; | 809 | return; |
777 | } | 810 | } |
778 | 811 | ||
812 | stop->role_id = wlvif->dev_role_id; | ||
779 | stop->tag = WL1271_SCAN_DEFAULT_TAG; | 813 | stop->tag = WL1271_SCAN_DEFAULT_TAG; |
780 | 814 | ||
781 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | 815 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, |
diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h index 81ee36ac2078..29f3c8d6b046 100644 --- a/drivers/net/wireless/ti/wlcore/scan.h +++ b/drivers/net/wireless/ti/wlcore/scan.h | |||
@@ -40,7 +40,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
40 | struct cfg80211_sched_scan_request *req, | 40 | struct cfg80211_sched_scan_request *req, |
41 | struct ieee80211_sched_scan_ies *ies); | 41 | struct ieee80211_sched_scan_ies *ies); |
42 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 42 | int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
43 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl); | 43 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
44 | void wl1271_scan_sched_scan_results(struct wl1271 *wl); | 44 | void wl1271_scan_sched_scan_results(struct wl1271 *wl); |
45 | 45 | ||
46 | #define WL1271_SCAN_MAX_CHANNELS 24 | 46 | #define WL1271_SCAN_MAX_CHANNELS 24 |
@@ -142,7 +142,8 @@ enum { | |||
142 | SCAN_BSS_TYPE_ANY, | 142 | SCAN_BSS_TYPE_ANY, |
143 | }; | 143 | }; |
144 | 144 | ||
145 | #define SCAN_CHANNEL_FLAGS_DFS BIT(0) | 145 | #define SCAN_CHANNEL_FLAGS_DFS BIT(0) /* channel is passive until an |
146 | activity is detected on it */ | ||
146 | #define SCAN_CHANNEL_FLAGS_DFS_ENABLED BIT(1) | 147 | #define SCAN_CHANNEL_FLAGS_DFS_ENABLED BIT(1) |
147 | 148 | ||
148 | struct conn_scan_ch_params { | 149 | struct conn_scan_ch_params { |
@@ -185,7 +186,10 @@ struct wl1271_cmd_sched_scan_config { | |||
185 | 186 | ||
186 | u8 dfs; | 187 | u8 dfs; |
187 | 188 | ||
188 | u8 padding[3]; | 189 | u8 n_pactive_ch; /* number of pactive (passive until fw detects energy) |
190 | channels in BG band */ | ||
191 | u8 role_id; | ||
192 | u8 padding[1]; | ||
189 | 193 | ||
190 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; | 194 | struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; |
191 | struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; | 195 | struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; |
@@ -212,21 +216,24 @@ struct wl1271_cmd_sched_scan_ssid_list { | |||
212 | 216 | ||
213 | u8 n_ssids; | 217 | u8 n_ssids; |
214 | struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; | 218 | struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; |
215 | u8 padding[3]; | 219 | u8 role_id; |
220 | u8 padding[2]; | ||
216 | } __packed; | 221 | } __packed; |
217 | 222 | ||
218 | struct wl1271_cmd_sched_scan_start { | 223 | struct wl1271_cmd_sched_scan_start { |
219 | struct wl1271_cmd_header header; | 224 | struct wl1271_cmd_header header; |
220 | 225 | ||
221 | u8 tag; | 226 | u8 tag; |
222 | u8 padding[3]; | 227 | u8 role_id; |
228 | u8 padding[2]; | ||
223 | } __packed; | 229 | } __packed; |
224 | 230 | ||
225 | struct wl1271_cmd_sched_scan_stop { | 231 | struct wl1271_cmd_sched_scan_stop { |
226 | struct wl1271_cmd_header header; | 232 | struct wl1271_cmd_header header; |
227 | 233 | ||
228 | u8 tag; | 234 | u8 tag; |
229 | u8 padding[3]; | 235 | u8 role_id; |
236 | u8 padding[2]; | ||
230 | } __packed; | 237 | } __packed; |
231 | 238 | ||
232 | 239 | ||
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 0a72347cfc4c..c67ec482e445 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/mmc/sdio.h> | ||
28 | #include <linux/mmc/sdio_func.h> | 29 | #include <linux/mmc/sdio_func.h> |
29 | #include <linux/mmc/sdio_ids.h> | 30 | #include <linux/mmc/sdio_ids.h> |
30 | #include <linux/mmc/card.h> | 31 | #include <linux/mmc/card.h> |
@@ -32,6 +33,7 @@ | |||
32 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
33 | #include <linux/wl12xx.h> | 34 | #include <linux/wl12xx.h> |
34 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
36 | #include <linux/printk.h> | ||
35 | 37 | ||
36 | #include "wlcore.h" | 38 | #include "wlcore.h" |
37 | #include "wl12xx_80211.h" | 39 | #include "wl12xx_80211.h" |
@@ -45,6 +47,8 @@ | |||
45 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | 47 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 |
46 | #endif | 48 | #endif |
47 | 49 | ||
50 | static bool dump = false; | ||
51 | |||
48 | struct wl12xx_sdio_glue { | 52 | struct wl12xx_sdio_glue { |
49 | struct device *dev; | 53 | struct device *dev; |
50 | struct platform_device *core; | 54 | struct platform_device *core; |
@@ -76,6 +80,13 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
76 | 80 | ||
77 | sdio_claim_host(func); | 81 | sdio_claim_host(func); |
78 | 82 | ||
83 | if (unlikely(dump)) { | ||
84 | printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr); | ||
85 | print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ", | ||
86 | DUMP_PREFIX_OFFSET, 16, 1, | ||
87 | buf, len, false); | ||
88 | } | ||
89 | |||
79 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { | 90 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { |
80 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 91 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
81 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", | 92 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", |
@@ -105,6 +116,13 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
105 | 116 | ||
106 | sdio_claim_host(func); | 117 | sdio_claim_host(func); |
107 | 118 | ||
119 | if (unlikely(dump)) { | ||
120 | printk(KERN_DEBUG "wlcore_sdio: WRITE to 0x%04x\n", addr); | ||
121 | print_hex_dump(KERN_DEBUG, "wlcore_sdio: WRITE ", | ||
122 | DUMP_PREFIX_OFFSET, 16, 1, | ||
123 | buf, len, false); | ||
124 | } | ||
125 | |||
108 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { | 126 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { |
109 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 127 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
110 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", | 128 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", |
@@ -196,6 +214,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
196 | struct resource res[1]; | 214 | struct resource res[1]; |
197 | mmc_pm_flag_t mmcflags; | 215 | mmc_pm_flag_t mmcflags; |
198 | int ret = -ENOMEM; | 216 | int ret = -ENOMEM; |
217 | const char *chip_family; | ||
199 | 218 | ||
200 | /* We are only able to handle the wlan function */ | 219 | /* We are only able to handle the wlan function */ |
201 | if (func->num != 0x02) | 220 | if (func->num != 0x02) |
@@ -236,7 +255,18 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
236 | /* Tell PM core that we don't need the card to be powered now */ | 255 | /* Tell PM core that we don't need the card to be powered now */ |
237 | pm_runtime_put_noidle(&func->dev); | 256 | pm_runtime_put_noidle(&func->dev); |
238 | 257 | ||
239 | glue->core = platform_device_alloc("wl12xx", -1); | 258 | /* |
259 | * Due to a hardware bug, we can't differentiate wl18xx from | ||
260 | * wl12xx, because both report the same device ID. The only | ||
261 | * way to differentiate is by checking the SDIO revision, | ||
262 | * which is 3.00 on the wl18xx chips. | ||
263 | */ | ||
264 | if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00) | ||
265 | chip_family = "wl18xx"; | ||
266 | else | ||
267 | chip_family = "wl12xx"; | ||
268 | |||
269 | glue->core = platform_device_alloc(chip_family, -1); | ||
240 | if (!glue->core) { | 270 | if (!glue->core) { |
241 | dev_err(glue->dev, "can't allocate platform_device"); | 271 | dev_err(glue->dev, "can't allocate platform_device"); |
242 | ret = -ENOMEM; | 272 | ret = -ENOMEM; |
@@ -367,6 +397,9 @@ static void __exit wl1271_exit(void) | |||
367 | module_init(wl1271_init); | 397 | module_init(wl1271_init); |
368 | module_exit(wl1271_exit); | 398 | module_exit(wl1271_exit); |
369 | 399 | ||
400 | module_param(dump, bool, S_IRUSR | S_IWUSR); | ||
401 | MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); | ||
402 | |||
370 | MODULE_LICENSE("GPL"); | 403 | MODULE_LICENSE("GPL"); |
371 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 404 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
372 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 405 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 3fb595546538..9273fdb3aaec 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -72,7 +72,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
72 | return id; | 72 | return id; |
73 | } | 73 | } |
74 | 74 | ||
75 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) | 75 | void wl1271_free_tx_id(struct wl1271 *wl, int id) |
76 | { | 76 | { |
77 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { | 77 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { |
78 | if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc)) | 78 | if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc)) |
@@ -82,6 +82,7 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) | |||
82 | wl->tx_frames_cnt--; | 82 | wl->tx_frames_cnt--; |
83 | } | 83 | } |
84 | } | 84 | } |
85 | EXPORT_SYMBOL(wl1271_free_tx_id); | ||
85 | 86 | ||
86 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, | 87 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, |
87 | struct sk_buff *skb) | 88 | struct sk_buff *skb) |
@@ -127,6 +128,7 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) | |||
127 | { | 128 | { |
128 | return wl->dummy_packet == skb; | 129 | return wl->dummy_packet == skb; |
129 | } | 130 | } |
131 | EXPORT_SYMBOL(wl12xx_is_dummy_packet); | ||
130 | 132 | ||
131 | u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 133 | u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
132 | struct sk_buff *skb) | 134 | struct sk_buff *skb) |
@@ -146,10 +148,10 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
146 | return wl->system_hlid; | 148 | return wl->system_hlid; |
147 | 149 | ||
148 | hdr = (struct ieee80211_hdr *)skb->data; | 150 | hdr = (struct ieee80211_hdr *)skb->data; |
149 | if (ieee80211_is_mgmt(hdr->frame_control)) | 151 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) |
150 | return wlvif->ap.global_hlid; | ||
151 | else | ||
152 | return wlvif->ap.bcast_hlid; | 152 | return wlvif->ap.bcast_hlid; |
153 | else | ||
154 | return wlvif->ap.global_hlid; | ||
153 | } | 155 | } |
154 | } | 156 | } |
155 | 157 | ||
@@ -176,37 +178,34 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
176 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, | 178 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
177 | unsigned int packet_length) | 179 | unsigned int packet_length) |
178 | { | 180 | { |
179 | if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) | 181 | if ((wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) || |
180 | return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); | 182 | !(wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)) |
181 | else | ||
182 | return ALIGN(packet_length, WL1271_TX_ALIGN_TO); | 183 | return ALIGN(packet_length, WL1271_TX_ALIGN_TO); |
184 | else | ||
185 | return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); | ||
183 | } | 186 | } |
184 | EXPORT_SYMBOL(wlcore_calc_packet_alignment); | 187 | EXPORT_SYMBOL(wlcore_calc_packet_alignment); |
185 | 188 | ||
186 | static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 189 | static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
187 | struct sk_buff *skb, u32 extra, u32 buf_offset, | 190 | struct sk_buff *skb, u32 extra, u32 buf_offset, |
188 | u8 hlid) | 191 | u8 hlid, bool is_gem) |
189 | { | 192 | { |
190 | struct wl1271_tx_hw_descr *desc; | 193 | struct wl1271_tx_hw_descr *desc; |
191 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 194 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
192 | u32 total_blocks; | 195 | u32 total_blocks; |
193 | int id, ret = -EBUSY, ac; | 196 | int id, ret = -EBUSY, ac; |
194 | u32 spare_blocks = wl->normal_tx_spare; | 197 | u32 spare_blocks; |
195 | bool is_dummy = false; | ||
196 | 198 | ||
197 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) | 199 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) |
198 | return -EAGAIN; | 200 | return -EAGAIN; |
199 | 201 | ||
202 | spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem); | ||
203 | |||
200 | /* allocate free identifier for the packet */ | 204 | /* allocate free identifier for the packet */ |
201 | id = wl1271_alloc_tx_id(wl, skb); | 205 | id = wl1271_alloc_tx_id(wl, skb); |
202 | if (id < 0) | 206 | if (id < 0) |
203 | return id; | 207 | return id; |
204 | 208 | ||
205 | if (unlikely(wl12xx_is_dummy_packet(wl, skb))) | ||
206 | is_dummy = true; | ||
207 | else if (wlvif->is_gem) | ||
208 | spare_blocks = wl->gem_tx_spare; | ||
209 | |||
210 | total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); | 209 | total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); |
211 | 210 | ||
212 | if (total_blocks <= wl->tx_blocks_available) { | 211 | if (total_blocks <= wl->tx_blocks_available) { |
@@ -228,7 +227,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
228 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 227 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
229 | wl->tx_allocated_pkts[ac]++; | 228 | wl->tx_allocated_pkts[ac]++; |
230 | 229 | ||
231 | if (!is_dummy && wlvif && | 230 | if (!wl12xx_is_dummy_packet(wl, skb) && wlvif && |
232 | wlvif->bss_type == BSS_TYPE_AP_BSS && | 231 | wlvif->bss_type == BSS_TYPE_AP_BSS && |
233 | test_bit(hlid, wlvif->ap.sta_hlid_map)) | 232 | test_bit(hlid, wlvif->ap.sta_hlid_map)) |
234 | wl->links[hlid].allocated_pkts++; | 233 | wl->links[hlid].allocated_pkts++; |
@@ -268,6 +267,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
268 | if (extra) { | 267 | if (extra) { |
269 | int hdrlen = ieee80211_hdrlen(frame_control); | 268 | int hdrlen = ieee80211_hdrlen(frame_control); |
270 | memmove(frame_start, hdr, hdrlen); | 269 | memmove(frame_start, hdr, hdrlen); |
270 | skb_set_network_header(skb, skb_network_offset(skb) + extra); | ||
271 | } | 271 | } |
272 | 272 | ||
273 | /* configure packet life time */ | 273 | /* configure packet life time */ |
@@ -330,9 +330,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
330 | ieee80211_has_protected(frame_control)) | 330 | ieee80211_has_protected(frame_control)) |
331 | tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; | 331 | tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; |
332 | 332 | ||
333 | desc->reserved = 0; | ||
334 | desc->tx_attr = cpu_to_le16(tx_attr); | 333 | desc->tx_attr = cpu_to_le16(tx_attr); |
335 | 334 | ||
335 | wlcore_hw_set_tx_desc_csum(wl, desc, skb); | ||
336 | wlcore_hw_set_tx_desc_data_len(wl, desc, skb); | 336 | wlcore_hw_set_tx_desc_data_len(wl, desc, skb); |
337 | } | 337 | } |
338 | 338 | ||
@@ -346,6 +346,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
346 | u32 total_len; | 346 | u32 total_len; |
347 | u8 hlid; | 347 | u8 hlid; |
348 | bool is_dummy; | 348 | bool is_dummy; |
349 | bool is_gem = false; | ||
349 | 350 | ||
350 | if (!skb) | 351 | if (!skb) |
351 | return -EINVAL; | 352 | return -EINVAL; |
@@ -355,7 +356,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
355 | /* TODO: handle dummy packets on multi-vifs */ | 356 | /* TODO: handle dummy packets on multi-vifs */ |
356 | is_dummy = wl12xx_is_dummy_packet(wl, skb); | 357 | is_dummy = wl12xx_is_dummy_packet(wl, skb); |
357 | 358 | ||
358 | if (info->control.hw_key && | 359 | if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && |
360 | info->control.hw_key && | ||
359 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) | 361 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) |
360 | extra = WL1271_EXTRA_SPACE_TKIP; | 362 | extra = WL1271_EXTRA_SPACE_TKIP; |
361 | 363 | ||
@@ -373,6 +375,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
373 | return ret; | 375 | return ret; |
374 | wlvif->default_key = idx; | 376 | wlvif->default_key = idx; |
375 | } | 377 | } |
378 | |||
379 | is_gem = (cipher == WL1271_CIPHER_SUITE_GEM); | ||
376 | } | 380 | } |
377 | hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); | 381 | hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); |
378 | if (hlid == WL12XX_INVALID_LINK_ID) { | 382 | if (hlid == WL12XX_INVALID_LINK_ID) { |
@@ -380,7 +384,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
380 | return -EINVAL; | 384 | return -EINVAL; |
381 | } | 385 | } |
382 | 386 | ||
383 | ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid); | 387 | ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid, |
388 | is_gem); | ||
384 | if (ret < 0) | 389 | if (ret < 0) |
385 | return ret; | 390 | return ret; |
386 | 391 | ||
@@ -425,10 +430,10 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, | |||
425 | rate_set >>= 1; | 430 | rate_set >>= 1; |
426 | } | 431 | } |
427 | 432 | ||
428 | /* MCS rates indication are on bits 16 - 23 */ | 433 | /* MCS rates indication are on bits 16 - 31 */ |
429 | rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; | 434 | rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; |
430 | 435 | ||
431 | for (bit = 0; bit < 8; bit++) { | 436 | for (bit = 0; bit < 16; bit++) { |
432 | if (rate_set & 0x1) | 437 | if (rate_set & 0x1) |
433 | enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); | 438 | enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); |
434 | rate_set >>= 1; | 439 | rate_set >>= 1; |
@@ -439,18 +444,15 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, | |||
439 | 444 | ||
440 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) | 445 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl) |
441 | { | 446 | { |
442 | unsigned long flags; | ||
443 | int i; | 447 | int i; |
444 | 448 | ||
445 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 449 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
446 | if (test_bit(i, &wl->stopped_queues_map) && | 450 | if (wlcore_is_queue_stopped_by_reason(wl, i, |
451 | WLCORE_QUEUE_STOP_REASON_WATERMARK) && | ||
447 | wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { | 452 | wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
448 | /* firmware buffer has space, restart queues */ | 453 | /* firmware buffer has space, restart queues */ |
449 | spin_lock_irqsave(&wl->wl_lock, flags); | 454 | wlcore_wake_queue(wl, i, |
450 | ieee80211_wake_queue(wl->hw, | 455 | WLCORE_QUEUE_STOP_REASON_WATERMARK); |
451 | wl1271_tx_get_mac80211_queue(i)); | ||
452 | clear_bit(i, &wl->stopped_queues_map); | ||
453 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
454 | } | 456 | } |
455 | } | 457 | } |
456 | } | 458 | } |
@@ -661,7 +663,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
661 | struct wl12xx_vif *wlvif; | 663 | struct wl12xx_vif *wlvif; |
662 | struct sk_buff *skb; | 664 | struct sk_buff *skb; |
663 | struct wl1271_tx_hw_descr *desc; | 665 | struct wl1271_tx_hw_descr *desc; |
664 | u32 buf_offset = 0; | 666 | u32 buf_offset = 0, last_len = 0; |
665 | bool sent_packets = false; | 667 | bool sent_packets = false; |
666 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 668 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
667 | int ret; | 669 | int ret; |
@@ -685,6 +687,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
685 | * Flush buffer and try again. | 687 | * Flush buffer and try again. |
686 | */ | 688 | */ |
687 | wl1271_skb_queue_head(wl, wlvif, skb); | 689 | wl1271_skb_queue_head(wl, wlvif, skb); |
690 | |||
691 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, | ||
692 | last_len); | ||
688 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 693 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
689 | buf_offset, true); | 694 | buf_offset, true); |
690 | sent_packets = true; | 695 | sent_packets = true; |
@@ -710,7 +715,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
710 | ieee80211_free_txskb(wl->hw, skb); | 715 | ieee80211_free_txskb(wl->hw, skb); |
711 | goto out_ack; | 716 | goto out_ack; |
712 | } | 717 | } |
713 | buf_offset += ret; | 718 | last_len = ret; |
719 | buf_offset += last_len; | ||
714 | wl->tx_packets_count++; | 720 | wl->tx_packets_count++; |
715 | if (has_data) { | 721 | if (has_data) { |
716 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 722 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
@@ -720,6 +726,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
720 | 726 | ||
721 | out_ack: | 727 | out_ack: |
722 | if (buf_offset) { | 728 | if (buf_offset) { |
729 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); | ||
723 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 730 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
724 | buf_offset, true); | 731 | buf_offset, true); |
725 | sent_packets = true; | 732 | sent_packets = true; |
@@ -849,7 +856,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
849 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 856 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
850 | 857 | ||
851 | /* remove TKIP header space if present */ | 858 | /* remove TKIP header space if present */ |
852 | if (info->control.hw_key && | 859 | if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && |
860 | info->control.hw_key && | ||
853 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { | 861 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
854 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 862 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
855 | memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, | 863 | memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, |
@@ -957,7 +965,7 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
957 | 965 | ||
958 | } | 966 | } |
959 | /* caller must hold wl->mutex and TX must be stopped */ | 967 | /* caller must hold wl->mutex and TX must be stopped */ |
960 | void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | 968 | void wl12xx_tx_reset(struct wl1271 *wl) |
961 | { | 969 | { |
962 | int i; | 970 | int i; |
963 | struct sk_buff *skb; | 971 | struct sk_buff *skb; |
@@ -972,15 +980,12 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
972 | wl->tx_queue_count[i] = 0; | 980 | wl->tx_queue_count[i] = 0; |
973 | } | 981 | } |
974 | 982 | ||
975 | wl->stopped_queues_map = 0; | ||
976 | |||
977 | /* | 983 | /* |
978 | * Make sure the driver is at a consistent state, in case this | 984 | * Make sure the driver is at a consistent state, in case this |
979 | * function is called from a context other than interface removal. | 985 | * function is called from a context other than interface removal. |
980 | * This call will always wake the TX queues. | 986 | * This call will always wake the TX queues. |
981 | */ | 987 | */ |
982 | if (reset_tx_queues) | 988 | wl1271_handle_tx_low_watermark(wl); |
983 | wl1271_handle_tx_low_watermark(wl); | ||
984 | 989 | ||
985 | for (i = 0; i < wl->num_tx_desc; i++) { | 990 | for (i = 0; i < wl->num_tx_desc; i++) { |
986 | if (wl->tx_frames[i] == NULL) | 991 | if (wl->tx_frames[i] == NULL) |
@@ -997,7 +1002,8 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
997 | */ | 1002 | */ |
998 | info = IEEE80211_SKB_CB(skb); | 1003 | info = IEEE80211_SKB_CB(skb); |
999 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 1004 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
1000 | if (info->control.hw_key && | 1005 | if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && |
1006 | info->control.hw_key && | ||
1001 | info->control.hw_key->cipher == | 1007 | info->control.hw_key->cipher == |
1002 | WLAN_CIPHER_SUITE_TKIP) { | 1008 | WLAN_CIPHER_SUITE_TKIP) { |
1003 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1009 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
@@ -1023,6 +1029,11 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
1023 | int i; | 1029 | int i; |
1024 | timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); | 1030 | timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); |
1025 | 1031 | ||
1032 | /* only one flush should be in progress, for consistent queue state */ | ||
1033 | mutex_lock(&wl->flush_mutex); | ||
1034 | |||
1035 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); | ||
1036 | |||
1026 | while (!time_after(jiffies, timeout)) { | 1037 | while (!time_after(jiffies, timeout)) { |
1027 | mutex_lock(&wl->mutex); | 1038 | mutex_lock(&wl->mutex); |
1028 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", | 1039 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", |
@@ -1031,7 +1042,7 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
1031 | if ((wl->tx_frames_cnt == 0) && | 1042 | if ((wl->tx_frames_cnt == 0) && |
1032 | (wl1271_tx_total_queue_count(wl) == 0)) { | 1043 | (wl1271_tx_total_queue_count(wl) == 0)) { |
1033 | mutex_unlock(&wl->mutex); | 1044 | mutex_unlock(&wl->mutex); |
1034 | return; | 1045 | goto out; |
1035 | } | 1046 | } |
1036 | mutex_unlock(&wl->mutex); | 1047 | mutex_unlock(&wl->mutex); |
1037 | msleep(1); | 1048 | msleep(1); |
@@ -1044,7 +1055,12 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
1044 | for (i = 0; i < WL12XX_MAX_LINKS; i++) | 1055 | for (i = 0; i < WL12XX_MAX_LINKS; i++) |
1045 | wl1271_tx_reset_link_queues(wl, i); | 1056 | wl1271_tx_reset_link_queues(wl, i); |
1046 | mutex_unlock(&wl->mutex); | 1057 | mutex_unlock(&wl->mutex); |
1058 | |||
1059 | out: | ||
1060 | wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); | ||
1061 | mutex_unlock(&wl->flush_mutex); | ||
1047 | } | 1062 | } |
1063 | EXPORT_SYMBOL_GPL(wl1271_tx_flush); | ||
1048 | 1064 | ||
1049 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) | 1065 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) |
1050 | { | 1066 | { |
@@ -1053,3 +1069,96 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) | |||
1053 | 1069 | ||
1054 | return BIT(__ffs(rate_set)); | 1070 | return BIT(__ffs(rate_set)); |
1055 | } | 1071 | } |
1072 | |||
1073 | void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, | ||
1074 | enum wlcore_queue_stop_reason reason) | ||
1075 | { | ||
1076 | bool stopped = !!wl->queue_stop_reasons[queue]; | ||
1077 | |||
1078 | /* queue should not be stopped for this reason */ | ||
1079 | WARN_ON(test_and_set_bit(reason, &wl->queue_stop_reasons[queue])); | ||
1080 | |||
1081 | if (stopped) | ||
1082 | return; | ||
1083 | |||
1084 | ieee80211_stop_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); | ||
1085 | } | ||
1086 | |||
1087 | void wlcore_stop_queue(struct wl1271 *wl, u8 queue, | ||
1088 | enum wlcore_queue_stop_reason reason) | ||
1089 | { | ||
1090 | unsigned long flags; | ||
1091 | |||
1092 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1093 | wlcore_stop_queue_locked(wl, queue, reason); | ||
1094 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1095 | } | ||
1096 | |||
1097 | void wlcore_wake_queue(struct wl1271 *wl, u8 queue, | ||
1098 | enum wlcore_queue_stop_reason reason) | ||
1099 | { | ||
1100 | unsigned long flags; | ||
1101 | |||
1102 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1103 | |||
1104 | /* queue should not be clear for this reason */ | ||
1105 | WARN_ON(!test_and_clear_bit(reason, &wl->queue_stop_reasons[queue])); | ||
1106 | |||
1107 | if (wl->queue_stop_reasons[queue]) | ||
1108 | goto out; | ||
1109 | |||
1110 | ieee80211_wake_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); | ||
1111 | |||
1112 | out: | ||
1113 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1114 | } | ||
1115 | |||
1116 | void wlcore_stop_queues(struct wl1271 *wl, | ||
1117 | enum wlcore_queue_stop_reason reason) | ||
1118 | { | ||
1119 | int i; | ||
1120 | |||
1121 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
1122 | wlcore_stop_queue(wl, i, reason); | ||
1123 | } | ||
1124 | EXPORT_SYMBOL_GPL(wlcore_stop_queues); | ||
1125 | |||
1126 | void wlcore_wake_queues(struct wl1271 *wl, | ||
1127 | enum wlcore_queue_stop_reason reason) | ||
1128 | { | ||
1129 | int i; | ||
1130 | |||
1131 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
1132 | wlcore_wake_queue(wl, i, reason); | ||
1133 | } | ||
1134 | EXPORT_SYMBOL_GPL(wlcore_wake_queues); | ||
1135 | |||
1136 | void wlcore_reset_stopped_queues(struct wl1271 *wl) | ||
1137 | { | ||
1138 | int i; | ||
1139 | unsigned long flags; | ||
1140 | |||
1141 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1142 | |||
1143 | for (i = 0; i < NUM_TX_QUEUES; i++) { | ||
1144 | if (!wl->queue_stop_reasons[i]) | ||
1145 | continue; | ||
1146 | |||
1147 | wl->queue_stop_reasons[i] = 0; | ||
1148 | ieee80211_wake_queue(wl->hw, | ||
1149 | wl1271_tx_get_mac80211_queue(i)); | ||
1150 | } | ||
1151 | |||
1152 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1153 | } | ||
1154 | |||
1155 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, | ||
1156 | enum wlcore_queue_stop_reason reason) | ||
1157 | { | ||
1158 | return test_bit(reason, &wl->queue_stop_reasons[queue]); | ||
1159 | } | ||
1160 | |||
1161 | bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue) | ||
1162 | { | ||
1163 | return !!wl->queue_stop_reasons[queue]; | ||
1164 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index 2fd6e5dc6f75..fa4be1b91135 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
@@ -85,6 +85,19 @@ struct wl128x_tx_mem { | |||
85 | u8 extra_bytes; | 85 | u8 extra_bytes; |
86 | } __packed; | 86 | } __packed; |
87 | 87 | ||
88 | struct wl18xx_tx_mem { | ||
89 | /* | ||
90 | * Total number of memory blocks allocated by the host for | ||
91 | * this packet. | ||
92 | */ | ||
93 | u8 total_mem_blocks; | ||
94 | |||
95 | /* | ||
96 | * control bits | ||
97 | */ | ||
98 | u8 ctrl; | ||
99 | } __packed; | ||
100 | |||
88 | /* | 101 | /* |
89 | * On wl128x based devices, when TX packets are aggregated, each packet | 102 | * On wl128x based devices, when TX packets are aggregated, each packet |
90 | * size must be aligned to the SDIO block size. The maximum block size | 103 | * size must be aligned to the SDIO block size. The maximum block size |
@@ -100,6 +113,7 @@ struct wl1271_tx_hw_descr { | |||
100 | union { | 113 | union { |
101 | struct wl127x_tx_mem wl127x_mem; | 114 | struct wl127x_tx_mem wl127x_mem; |
102 | struct wl128x_tx_mem wl128x_mem; | 115 | struct wl128x_tx_mem wl128x_mem; |
116 | struct wl18xx_tx_mem wl18xx_mem; | ||
103 | } __packed; | 117 | } __packed; |
104 | /* Device time (in us) when the packet arrived to the driver */ | 118 | /* Device time (in us) when the packet arrived to the driver */ |
105 | __le32 start_time; | 119 | __le32 start_time; |
@@ -116,7 +130,16 @@ struct wl1271_tx_hw_descr { | |||
116 | u8 tid; | 130 | u8 tid; |
117 | /* host link ID (HLID) */ | 131 | /* host link ID (HLID) */ |
118 | u8 hlid; | 132 | u8 hlid; |
119 | u8 reserved; | 133 | |
134 | union { | ||
135 | u8 wl12xx_reserved; | ||
136 | |||
137 | /* | ||
138 | * bit 0 -> 0 = udp, 1 = tcp | ||
139 | * bit 1:7 -> IP header offset | ||
140 | */ | ||
141 | u8 wl18xx_checksum_data; | ||
142 | } __packed; | ||
120 | } __packed; | 143 | } __packed; |
121 | 144 | ||
122 | enum wl1271_tx_hw_res_status { | 145 | enum wl1271_tx_hw_res_status { |
@@ -161,6 +184,13 @@ struct wl1271_tx_hw_res_if { | |||
161 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; | 184 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; |
162 | } __packed; | 185 | } __packed; |
163 | 186 | ||
187 | enum wlcore_queue_stop_reason { | ||
188 | WLCORE_QUEUE_STOP_REASON_WATERMARK, | ||
189 | WLCORE_QUEUE_STOP_REASON_FW_RESTART, | ||
190 | WLCORE_QUEUE_STOP_REASON_FLUSH, | ||
191 | WLCORE_QUEUE_STOP_REASON_SPARE_BLK, /* 18xx specific */ | ||
192 | }; | ||
193 | |||
164 | static inline int wl1271_tx_get_queue(int queue) | 194 | static inline int wl1271_tx_get_queue(int queue) |
165 | { | 195 | { |
166 | switch (queue) { | 196 | switch (queue) { |
@@ -207,7 +237,7 @@ void wl1271_tx_work(struct work_struct *work); | |||
207 | void wl1271_tx_work_locked(struct wl1271 *wl); | 237 | void wl1271_tx_work_locked(struct wl1271 *wl); |
208 | void wl1271_tx_complete(struct wl1271 *wl); | 238 | void wl1271_tx_complete(struct wl1271 *wl); |
209 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
210 | void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); | 240 | void wl12xx_tx_reset(struct wl1271 *wl); |
211 | void wl1271_tx_flush(struct wl1271 *wl); | 241 | void wl1271_tx_flush(struct wl1271 *wl); |
212 | u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band); | 242 | u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band); |
213 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, | 243 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, |
@@ -223,6 +253,21 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); | |||
223 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); | 253 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); |
224 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, | 254 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
225 | unsigned int packet_length); | 255 | unsigned int packet_length); |
256 | void wl1271_free_tx_id(struct wl1271 *wl, int id); | ||
257 | void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, | ||
258 | enum wlcore_queue_stop_reason reason); | ||
259 | void wlcore_stop_queue(struct wl1271 *wl, u8 queue, | ||
260 | enum wlcore_queue_stop_reason reason); | ||
261 | void wlcore_wake_queue(struct wl1271 *wl, u8 queue, | ||
262 | enum wlcore_queue_stop_reason reason); | ||
263 | void wlcore_stop_queues(struct wl1271 *wl, | ||
264 | enum wlcore_queue_stop_reason reason); | ||
265 | void wlcore_wake_queues(struct wl1271 *wl, | ||
266 | enum wlcore_queue_stop_reason reason); | ||
267 | void wlcore_reset_stopped_queues(struct wl1271 *wl); | ||
268 | bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, | ||
269 | enum wlcore_queue_stop_reason reason); | ||
270 | bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue); | ||
226 | 271 | ||
227 | /* from main.c */ | 272 | /* from main.c */ |
228 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); | 273 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 0b3f0b586f4b..761a72f4b8d1 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -24,8 +24,9 @@ | |||
24 | 24 | ||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore_i.h" |
28 | #include "event.h" | 28 | #include "event.h" |
29 | #include "boot.h" | ||
29 | 30 | ||
30 | /* The maximum number of Tx descriptors in all chip families */ | 31 | /* The maximum number of Tx descriptors in all chip families */ |
31 | #define WLCORE_MAX_TX_DESCRIPTORS 32 | 32 | #define WLCORE_MAX_TX_DESCRIPTORS 32 |
@@ -33,11 +34,13 @@ | |||
33 | /* forward declaration */ | 34 | /* forward declaration */ |
34 | struct wl1271_tx_hw_descr; | 35 | struct wl1271_tx_hw_descr; |
35 | enum wl_rx_buf_align; | 36 | enum wl_rx_buf_align; |
37 | struct wl1271_rx_descriptor; | ||
36 | 38 | ||
37 | struct wlcore_ops { | 39 | struct wlcore_ops { |
38 | int (*identify_chip)(struct wl1271 *wl); | 40 | int (*identify_chip)(struct wl1271 *wl); |
39 | int (*identify_fw)(struct wl1271 *wl); | 41 | int (*identify_fw)(struct wl1271 *wl); |
40 | int (*boot)(struct wl1271 *wl); | 42 | int (*boot)(struct wl1271 *wl); |
43 | int (*plt_init)(struct wl1271 *wl); | ||
41 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | 44 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, |
42 | void *buf, size_t len); | 45 | void *buf, size_t len); |
43 | void (*ack_event)(struct wl1271 *wl); | 46 | void (*ack_event)(struct wl1271 *wl); |
@@ -61,6 +64,23 @@ struct wlcore_ops { | |||
61 | struct wl12xx_vif *wlvif); | 64 | struct wl12xx_vif *wlvif); |
62 | s8 (*get_pg_ver)(struct wl1271 *wl); | 65 | s8 (*get_pg_ver)(struct wl1271 *wl); |
63 | void (*get_mac)(struct wl1271 *wl); | 66 | void (*get_mac)(struct wl1271 *wl); |
67 | void (*set_tx_desc_csum)(struct wl1271 *wl, | ||
68 | struct wl1271_tx_hw_descr *desc, | ||
69 | struct sk_buff *skb); | ||
70 | void (*set_rx_csum)(struct wl1271 *wl, | ||
71 | struct wl1271_rx_descriptor *desc, | ||
72 | struct sk_buff *skb); | ||
73 | u32 (*ap_get_mimo_wide_rate_mask)(struct wl1271 *wl, | ||
74 | struct wl12xx_vif *wlvif); | ||
75 | int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir); | ||
76 | int (*handle_static_data)(struct wl1271 *wl, | ||
77 | struct wl1271_static_data *static_data); | ||
78 | int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem); | ||
79 | int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd, | ||
80 | struct ieee80211_vif *vif, | ||
81 | struct ieee80211_sta *sta, | ||
82 | struct ieee80211_key_conf *key_conf); | ||
83 | u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); | ||
64 | }; | 84 | }; |
65 | 85 | ||
66 | enum wlcore_partitions { | 86 | enum wlcore_partitions { |
@@ -109,6 +129,15 @@ enum wlcore_registers { | |||
109 | REG_TABLE_LEN, | 129 | REG_TABLE_LEN, |
110 | }; | 130 | }; |
111 | 131 | ||
132 | struct wl1271_stats { | ||
133 | void *fw_stats; | ||
134 | unsigned long fw_stats_update; | ||
135 | size_t fw_stats_len; | ||
136 | |||
137 | unsigned int retry_count; | ||
138 | unsigned int excessive_retries; | ||
139 | }; | ||
140 | |||
112 | struct wl1271 { | 141 | struct wl1271 { |
113 | struct ieee80211_hw *hw; | 142 | struct ieee80211_hw *hw; |
114 | bool mac80211_registered; | 143 | bool mac80211_registered; |
@@ -121,7 +150,6 @@ struct wl1271 { | |||
121 | 150 | ||
122 | void (*set_power)(bool enable); | 151 | void (*set_power)(bool enable); |
123 | int irq; | 152 | int irq; |
124 | int ref_clock; | ||
125 | 153 | ||
126 | spinlock_t wl_lock; | 154 | spinlock_t wl_lock; |
127 | 155 | ||
@@ -186,7 +214,7 @@ struct wl1271 { | |||
186 | 214 | ||
187 | /* Frames scheduled for transmission, not handled yet */ | 215 | /* Frames scheduled for transmission, not handled yet */ |
188 | int tx_queue_count[NUM_TX_QUEUES]; | 216 | int tx_queue_count[NUM_TX_QUEUES]; |
189 | long stopped_queues_map; | 217 | unsigned long queue_stop_reasons[NUM_TX_QUEUES]; |
190 | 218 | ||
191 | /* Frames received, not handled yet by mac80211 */ | 219 | /* Frames received, not handled yet by mac80211 */ |
192 | struct sk_buff_head deferred_rx_queue; | 220 | struct sk_buff_head deferred_rx_queue; |
@@ -205,9 +233,6 @@ struct wl1271 { | |||
205 | /* FW Rx counter */ | 233 | /* FW Rx counter */ |
206 | u32 rx_counter; | 234 | u32 rx_counter; |
207 | 235 | ||
208 | /* Rx memory pool address */ | ||
209 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; | ||
210 | |||
211 | /* Intermediate buffer, used for packet aggregation */ | 236 | /* Intermediate buffer, used for packet aggregation */ |
212 | u8 *aggr_buf; | 237 | u8 *aggr_buf; |
213 | 238 | ||
@@ -228,6 +253,7 @@ struct wl1271 { | |||
228 | 253 | ||
229 | /* Hardware recovery work */ | 254 | /* Hardware recovery work */ |
230 | struct work_struct recovery_work; | 255 | struct work_struct recovery_work; |
256 | bool watchdog_recovery; | ||
231 | 257 | ||
232 | /* Pointer that holds DMA-friendly block for the mailbox */ | 258 | /* Pointer that holds DMA-friendly block for the mailbox */ |
233 | struct event_mailbox *mbox; | 259 | struct event_mailbox *mbox; |
@@ -263,7 +289,8 @@ struct wl1271 { | |||
263 | u32 buffer_cmd; | 289 | u32 buffer_cmd; |
264 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; | 290 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; |
265 | 291 | ||
266 | struct wl_fw_status *fw_status; | 292 | struct wl_fw_status_1 *fw_status_1; |
293 | struct wl_fw_status_2 *fw_status_2; | ||
267 | struct wl1271_tx_hw_res_if *tx_res_if; | 294 | struct wl1271_tx_hw_res_if *tx_res_if; |
268 | 295 | ||
269 | /* Current chipset configuration */ | 296 | /* Current chipset configuration */ |
@@ -279,8 +306,6 @@ struct wl1271 { | |||
279 | /* bands supported by this instance of wl12xx */ | 306 | /* bands supported by this instance of wl12xx */ |
280 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 307 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
281 | 308 | ||
282 | int tcxo_clock; | ||
283 | |||
284 | /* | 309 | /* |
285 | * wowlan trigger was configured during suspend. | 310 | * wowlan trigger was configured during suspend. |
286 | * (currently, only "ANY" trigger is supported) | 311 | * (currently, only "ANY" trigger is supported) |
@@ -333,10 +358,8 @@ struct wl1271 { | |||
333 | 358 | ||
334 | /* number of TX descriptors the HW supports. */ | 359 | /* number of TX descriptors the HW supports. */ |
335 | u32 num_tx_desc; | 360 | u32 num_tx_desc; |
336 | 361 | /* number of RX descriptors the HW supports. */ | |
337 | /* spare Tx blocks for normal/GEM operating modes */ | 362 | u32 num_rx_desc; |
338 | u32 normal_tx_spare; | ||
339 | u32 gem_tx_spare; | ||
340 | 363 | ||
341 | /* translate HW Tx rates to standard rate-indices */ | 364 | /* translate HW Tx rates to standard rate-indices */ |
342 | const u8 **band_rate_to_idx; | 365 | const u8 **band_rate_to_idx; |
@@ -348,19 +371,32 @@ struct wl1271 { | |||
348 | u8 hw_min_ht_rate; | 371 | u8 hw_min_ht_rate; |
349 | 372 | ||
350 | /* HW HT (11n) capabilities */ | 373 | /* HW HT (11n) capabilities */ |
351 | struct ieee80211_sta_ht_cap ht_cap; | 374 | struct ieee80211_sta_ht_cap ht_cap[IEEE80211_NUM_BANDS]; |
352 | 375 | ||
353 | /* size of the private FW status data */ | 376 | /* size of the private FW status data */ |
354 | size_t fw_status_priv_len; | 377 | size_t fw_status_priv_len; |
355 | 378 | ||
356 | /* RX Data filter rule state - enabled/disabled */ | 379 | /* RX Data filter rule state - enabled/disabled */ |
357 | bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; | 380 | bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; |
381 | |||
382 | /* size of the private static data */ | ||
383 | size_t static_data_priv_len; | ||
384 | |||
385 | /* the current channel type */ | ||
386 | enum nl80211_channel_type channel_type; | ||
387 | |||
388 | /* mutex for protecting the tx_flush function */ | ||
389 | struct mutex flush_mutex; | ||
358 | }; | 390 | }; |
359 | 391 | ||
360 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 392 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
361 | int __devexit wlcore_remove(struct platform_device *pdev); | 393 | int __devexit wlcore_remove(struct platform_device *pdev); |
362 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); | 394 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); |
363 | int wlcore_free_hw(struct wl1271 *wl); | 395 | int wlcore_free_hw(struct wl1271 *wl); |
396 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | ||
397 | struct ieee80211_vif *vif, | ||
398 | struct ieee80211_sta *sta, | ||
399 | struct ieee80211_key_conf *key_conf); | ||
364 | 400 | ||
365 | /* Firmware image load chunk size */ | 401 | /* Firmware image load chunk size */ |
366 | #define CHUNK_SIZE 16384 | 402 | #define CHUNK_SIZE 16384 |
@@ -385,6 +421,12 @@ int wlcore_free_hw(struct wl1271 *wl); | |||
385 | /* Some firmwares may not support ELP */ | 421 | /* Some firmwares may not support ELP */ |
386 | #define WLCORE_QUIRK_NO_ELP BIT(6) | 422 | #define WLCORE_QUIRK_NO_ELP BIT(6) |
387 | 423 | ||
424 | /* pad only the last frame in the aggregate buffer */ | ||
425 | #define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7) | ||
426 | |||
427 | /* extra header space is required for TKIP */ | ||
428 | #define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8) | ||
429 | |||
388 | /* TODO: move to the lower drivers when all usages are abstracted */ | 430 | /* TODO: move to the lower drivers when all usages are abstracted */ |
389 | #define CHIP_ID_1271_PG10 (0x4030101) | 431 | #define CHIP_ID_1271_PG10 (0x4030101) |
390 | #define CHIP_ID_1271_PG20 (0x4030111) | 432 | #define CHIP_ID_1271_PG20 (0x4030111) |
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index f12bdf745180..8260b1e9288a 100644 --- a/drivers/net/wireless/ti/wlcore/wl12xx.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -22,8 +22,8 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #ifndef __WL12XX_H__ | 25 | #ifndef __WLCORE_I_H__ |
26 | #define __WL12XX_H__ | 26 | #define __WLCORE_I_H__ |
27 | 27 | ||
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
@@ -89,7 +89,7 @@ | |||
89 | #define WL1271_AP_BSS_INDEX 0 | 89 | #define WL1271_AP_BSS_INDEX 0 |
90 | #define WL1271_AP_DEF_BEACON_EXP 20 | 90 | #define WL1271_AP_DEF_BEACON_EXP 20 |
91 | 91 | ||
92 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | 92 | #define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) |
93 | 93 | ||
94 | enum wl1271_state { | 94 | enum wl1271_state { |
95 | WL1271_STATE_OFF, | 95 | WL1271_STATE_OFF, |
@@ -132,16 +132,7 @@ struct wl1271_chip { | |||
132 | unsigned int fw_ver[NUM_FW_VER]; | 132 | unsigned int fw_ver[NUM_FW_VER]; |
133 | }; | 133 | }; |
134 | 134 | ||
135 | struct wl1271_stats { | ||
136 | struct acx_statistics *fw_stats; | ||
137 | unsigned long fw_stats_update; | ||
138 | |||
139 | unsigned int retry_count; | ||
140 | unsigned int excessive_retries; | ||
141 | }; | ||
142 | |||
143 | #define NUM_TX_QUEUES 4 | 135 | #define NUM_TX_QUEUES 4 |
144 | #define NUM_RX_PKT_DESC 8 | ||
145 | 136 | ||
146 | #define AP_MAX_STATIONS 8 | 137 | #define AP_MAX_STATIONS 8 |
147 | 138 | ||
@@ -159,13 +150,26 @@ struct wl_fw_packet_counters { | |||
159 | } __packed; | 150 | } __packed; |
160 | 151 | ||
161 | /* FW status registers */ | 152 | /* FW status registers */ |
162 | struct wl_fw_status { | 153 | struct wl_fw_status_1 { |
163 | __le32 intr; | 154 | __le32 intr; |
164 | u8 fw_rx_counter; | 155 | u8 fw_rx_counter; |
165 | u8 drv_rx_counter; | 156 | u8 drv_rx_counter; |
166 | u8 reserved; | 157 | u8 reserved; |
167 | u8 tx_results_counter; | 158 | u8 tx_results_counter; |
168 | __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; | 159 | __le32 rx_pkt_descs[0]; |
160 | } __packed; | ||
161 | |||
162 | /* | ||
163 | * Each HW arch has a different number of Rx descriptors. | ||
164 | * The length of the status depends on it, since it holds an array | ||
165 | * of descriptors. | ||
166 | */ | ||
167 | #define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \ | ||
168 | (sizeof(struct wl_fw_status_1) + \ | ||
169 | (sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \ | ||
170 | num_rx_desc) | ||
171 | |||
172 | struct wl_fw_status_2 { | ||
169 | __le32 fw_localtime; | 173 | __le32 fw_localtime; |
170 | 174 | ||
171 | /* | 175 | /* |
@@ -194,11 +198,6 @@ struct wl_fw_status { | |||
194 | u8 priv[0]; | 198 | u8 priv[0]; |
195 | } __packed; | 199 | } __packed; |
196 | 200 | ||
197 | struct wl1271_rx_mem_pool_addr { | ||
198 | u32 addr; | ||
199 | u32 addr_extra; | ||
200 | }; | ||
201 | |||
202 | #define WL1271_MAX_CHANNELS 64 | 201 | #define WL1271_MAX_CHANNELS 64 |
203 | struct wl1271_scan { | 202 | struct wl1271_scan { |
204 | struct cfg80211_scan_request *req; | 203 | struct cfg80211_scan_request *req; |
@@ -367,6 +366,7 @@ struct wl12xx_vif { | |||
367 | /* The current band */ | 366 | /* The current band */ |
368 | enum ieee80211_band band; | 367 | enum ieee80211_band band; |
369 | int channel; | 368 | int channel; |
369 | enum nl80211_channel_type channel_type; | ||
370 | 370 | ||
371 | u32 bitrate_masks[IEEE80211_NUM_BANDS]; | 371 | u32 bitrate_masks[IEEE80211_NUM_BANDS]; |
372 | u32 basic_rate_set; | 372 | u32 basic_rate_set; |
@@ -417,9 +417,6 @@ struct wl12xx_vif { | |||
417 | struct work_struct rx_streaming_disable_work; | 417 | struct work_struct rx_streaming_disable_work; |
418 | struct timer_list rx_streaming_timer; | 418 | struct timer_list rx_streaming_timer; |
419 | 419 | ||
420 | /* does the current role use GEM for encryption (AP or STA) */ | ||
421 | bool is_gem; | ||
422 | |||
423 | /* | 420 | /* |
424 | * This struct must be last! | 421 | * This struct must be last! |
425 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 422 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
@@ -501,7 +498,8 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | |||
501 | /* Macros to handle wl1271.sta_rate_set */ | 498 | /* Macros to handle wl1271.sta_rate_set */ |
502 | #define HW_BG_RATES_MASK 0xffff | 499 | #define HW_BG_RATES_MASK 0xffff |
503 | #define HW_HT_RATES_OFFSET 16 | 500 | #define HW_HT_RATES_OFFSET 16 |
501 | #define HW_MIMO_RATES_OFFSET 24 | ||
504 | 502 | ||
505 | #define WL12XX_HW_BLOCK_SIZE 256 | 503 | #define WL12XX_HW_BLOCK_SIZE 256 |
506 | 504 | ||
507 | #endif | 505 | #endif /* __WLCORE_I_H__ */ |
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 19110f0eb15f..9ac829e22e73 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = { | |||
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(usb, pn533_table); | 46 | MODULE_DEVICE_TABLE(usb, pn533_table); |
47 | 47 | ||
48 | /* How much time we spend listening for initiators */ | ||
49 | #define PN533_LISTEN_TIME 2 | ||
50 | |||
48 | /* frame definitions */ | 51 | /* frame definitions */ |
49 | #define PN533_FRAME_TAIL_SIZE 2 | 52 | #define PN533_FRAME_TAIL_SIZE 2 |
50 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ | 53 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ |
@@ -74,6 +77,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
74 | #define PN533_CMD_IN_RELEASE 0x52 | 77 | #define PN533_CMD_IN_RELEASE 0x52 |
75 | #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 | 78 | #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 |
76 | 79 | ||
80 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c | ||
81 | #define PN533_CMD_TG_GET_DATA 0x86 | ||
82 | #define PN533_CMD_TG_SET_DATA 0x8e | ||
83 | |||
77 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 84 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
78 | 85 | ||
79 | /* PN533 Return codes */ | 86 | /* PN533 Return codes */ |
@@ -81,6 +88,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
81 | #define PN533_CMD_MI_MASK 0x40 | 88 | #define PN533_CMD_MI_MASK 0x40 |
82 | #define PN533_CMD_RET_SUCCESS 0x00 | 89 | #define PN533_CMD_RET_SUCCESS 0x00 |
83 | 90 | ||
91 | /* PN533 status codes */ | ||
92 | #define PN533_STATUS_TARGET_RELEASED 0x29 | ||
93 | |||
84 | struct pn533; | 94 | struct pn533; |
85 | 95 | ||
86 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, | 96 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, |
@@ -97,8 +107,14 @@ struct pn533_fw_version { | |||
97 | }; | 107 | }; |
98 | 108 | ||
99 | /* PN533_CMD_RF_CONFIGURATION */ | 109 | /* PN533_CMD_RF_CONFIGURATION */ |
110 | #define PN533_CFGITEM_TIMING 0x02 | ||
100 | #define PN533_CFGITEM_MAX_RETRIES 0x05 | 111 | #define PN533_CFGITEM_MAX_RETRIES 0x05 |
101 | 112 | ||
113 | #define PN533_CONFIG_TIMING_102 0xb | ||
114 | #define PN533_CONFIG_TIMING_204 0xc | ||
115 | #define PN533_CONFIG_TIMING_409 0xd | ||
116 | #define PN533_CONFIG_TIMING_819 0xe | ||
117 | |||
102 | #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00 | 118 | #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00 |
103 | #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF | 119 | #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF |
104 | 120 | ||
@@ -108,6 +124,12 @@ struct pn533_config_max_retries { | |||
108 | u8 mx_rty_passive_act; | 124 | u8 mx_rty_passive_act; |
109 | } __packed; | 125 | } __packed; |
110 | 126 | ||
127 | struct pn533_config_timing { | ||
128 | u8 rfu; | ||
129 | u8 atr_res_timeout; | ||
130 | u8 dep_timeout; | ||
131 | } __packed; | ||
132 | |||
111 | /* PN533_CMD_IN_LIST_PASSIVE_TARGET */ | 133 | /* PN533_CMD_IN_LIST_PASSIVE_TARGET */ |
112 | 134 | ||
113 | /* felica commands opcode */ | 135 | /* felica commands opcode */ |
@@ -144,6 +166,7 @@ enum { | |||
144 | PN533_POLL_MOD_424KBPS_FELICA, | 166 | PN533_POLL_MOD_424KBPS_FELICA, |
145 | PN533_POLL_MOD_106KBPS_JEWEL, | 167 | PN533_POLL_MOD_106KBPS_JEWEL, |
146 | PN533_POLL_MOD_847KBPS_B, | 168 | PN533_POLL_MOD_847KBPS_B, |
169 | PN533_LISTEN_MOD, | ||
147 | 170 | ||
148 | __PN533_POLL_MOD_AFTER_LAST, | 171 | __PN533_POLL_MOD_AFTER_LAST, |
149 | }; | 172 | }; |
@@ -211,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = { | |||
211 | }, | 234 | }, |
212 | .len = 3, | 235 | .len = 3, |
213 | }, | 236 | }, |
237 | [PN533_LISTEN_MOD] = { | ||
238 | .len = 0, | ||
239 | }, | ||
214 | }; | 240 | }; |
215 | 241 | ||
216 | /* PN533_CMD_IN_ATR */ | 242 | /* PN533_CMD_IN_ATR */ |
@@ -237,7 +263,7 @@ struct pn533_cmd_jump_dep { | |||
237 | u8 active; | 263 | u8 active; |
238 | u8 baud; | 264 | u8 baud; |
239 | u8 next; | 265 | u8 next; |
240 | u8 gt[]; | 266 | u8 data[]; |
241 | } __packed; | 267 | } __packed; |
242 | 268 | ||
243 | struct pn533_cmd_jump_dep_response { | 269 | struct pn533_cmd_jump_dep_response { |
@@ -253,6 +279,29 @@ struct pn533_cmd_jump_dep_response { | |||
253 | u8 gt[]; | 279 | u8 gt[]; |
254 | } __packed; | 280 | } __packed; |
255 | 281 | ||
282 | |||
283 | /* PN533_TG_INIT_AS_TARGET */ | ||
284 | #define PN533_INIT_TARGET_PASSIVE 0x1 | ||
285 | #define PN533_INIT_TARGET_DEP 0x2 | ||
286 | |||
287 | #define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3 | ||
288 | #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 | ||
289 | #define PN533_INIT_TARGET_RESP_DEP 0x4 | ||
290 | |||
291 | struct pn533_cmd_init_target { | ||
292 | u8 mode; | ||
293 | u8 mifare[6]; | ||
294 | u8 felica[18]; | ||
295 | u8 nfcid3[10]; | ||
296 | u8 gb_len; | ||
297 | u8 gb[]; | ||
298 | } __packed; | ||
299 | |||
300 | struct pn533_cmd_init_target_response { | ||
301 | u8 mode; | ||
302 | u8 cmd[]; | ||
303 | } __packed; | ||
304 | |||
256 | struct pn533 { | 305 | struct pn533 { |
257 | struct usb_device *udev; | 306 | struct usb_device *udev; |
258 | struct usb_interface *interface; | 307 | struct usb_interface *interface; |
@@ -270,22 +319,31 @@ struct pn533 { | |||
270 | 319 | ||
271 | struct workqueue_struct *wq; | 320 | struct workqueue_struct *wq; |
272 | struct work_struct cmd_work; | 321 | struct work_struct cmd_work; |
322 | struct work_struct poll_work; | ||
273 | struct work_struct mi_work; | 323 | struct work_struct mi_work; |
324 | struct work_struct tg_work; | ||
325 | struct timer_list listen_timer; | ||
274 | struct pn533_frame *wq_in_frame; | 326 | struct pn533_frame *wq_in_frame; |
275 | int wq_in_error; | 327 | int wq_in_error; |
328 | int cancel_listen; | ||
276 | 329 | ||
277 | pn533_cmd_complete_t cmd_complete; | 330 | pn533_cmd_complete_t cmd_complete; |
278 | void *cmd_complete_arg; | 331 | void *cmd_complete_arg; |
279 | struct semaphore cmd_lock; | 332 | struct mutex cmd_lock; |
280 | u8 cmd; | 333 | u8 cmd; |
281 | 334 | ||
282 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; | 335 | struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; |
283 | u8 poll_mod_count; | 336 | u8 poll_mod_count; |
284 | u8 poll_mod_curr; | 337 | u8 poll_mod_curr; |
285 | u32 poll_protocols; | 338 | u32 poll_protocols; |
339 | u32 listen_protocols; | ||
340 | |||
341 | u8 *gb; | ||
342 | size_t gb_len; | ||
286 | 343 | ||
287 | u8 tgt_available_prots; | 344 | u8 tgt_available_prots; |
288 | u8 tgt_active_prot; | 345 | u8 tgt_active_prot; |
346 | u8 tgt_mode; | ||
289 | }; | 347 | }; |
290 | 348 | ||
291 | struct pn533_frame { | 349 | struct pn533_frame { |
@@ -405,7 +463,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work) | |||
405 | PN533_FRAME_CMD_PARAMS_LEN(in_frame)); | 463 | PN533_FRAME_CMD_PARAMS_LEN(in_frame)); |
406 | 464 | ||
407 | if (rc != -EINPROGRESS) | 465 | if (rc != -EINPROGRESS) |
408 | up(&dev->cmd_lock); | 466 | mutex_unlock(&dev->cmd_lock); |
409 | } | 467 | } |
410 | 468 | ||
411 | static void pn533_recv_response(struct urb *urb) | 469 | static void pn533_recv_response(struct urb *urb) |
@@ -583,7 +641,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, | |||
583 | 641 | ||
584 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 642 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
585 | 643 | ||
586 | if (down_trylock(&dev->cmd_lock)) | 644 | if (!mutex_trylock(&dev->cmd_lock)) |
587 | return -EBUSY; | 645 | return -EBUSY; |
588 | 646 | ||
589 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, | 647 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, |
@@ -593,7 +651,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, | |||
593 | 651 | ||
594 | return 0; | 652 | return 0; |
595 | error: | 653 | error: |
596 | up(&dev->cmd_lock); | 654 | mutex_unlock(&dev->cmd_lock); |
597 | return rc; | 655 | return rc; |
598 | } | 656 | } |
599 | 657 | ||
@@ -963,6 +1021,11 @@ static int pn533_target_found(struct pn533 *dev, | |||
963 | return 0; | 1021 | return 0; |
964 | } | 1022 | } |
965 | 1023 | ||
1024 | static inline void pn533_poll_next_mod(struct pn533 *dev) | ||
1025 | { | ||
1026 | dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; | ||
1027 | } | ||
1028 | |||
966 | static void pn533_poll_reset_mod_list(struct pn533 *dev) | 1029 | static void pn533_poll_reset_mod_list(struct pn533 *dev) |
967 | { | 1030 | { |
968 | dev->poll_mod_count = 0; | 1031 | dev->poll_mod_count = 0; |
@@ -975,102 +1038,283 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) | |||
975 | dev->poll_mod_count++; | 1038 | dev->poll_mod_count++; |
976 | } | 1039 | } |
977 | 1040 | ||
978 | static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols) | 1041 | static void pn533_poll_create_mod_list(struct pn533 *dev, |
1042 | u32 im_protocols, u32 tm_protocols) | ||
979 | { | 1043 | { |
980 | pn533_poll_reset_mod_list(dev); | 1044 | pn533_poll_reset_mod_list(dev); |
981 | 1045 | ||
982 | if (protocols & NFC_PROTO_MIFARE_MASK | 1046 | if (im_protocols & NFC_PROTO_MIFARE_MASK |
983 | || protocols & NFC_PROTO_ISO14443_MASK | 1047 | || im_protocols & NFC_PROTO_ISO14443_MASK |
984 | || protocols & NFC_PROTO_NFC_DEP_MASK) | 1048 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) |
985 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); | 1049 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); |
986 | 1050 | ||
987 | if (protocols & NFC_PROTO_FELICA_MASK | 1051 | if (im_protocols & NFC_PROTO_FELICA_MASK |
988 | || protocols & NFC_PROTO_NFC_DEP_MASK) { | 1052 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) { |
989 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); | 1053 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); |
990 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); | 1054 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); |
991 | } | 1055 | } |
992 | 1056 | ||
993 | if (protocols & NFC_PROTO_JEWEL_MASK) | 1057 | if (im_protocols & NFC_PROTO_JEWEL_MASK) |
994 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); | 1058 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); |
995 | 1059 | ||
996 | if (protocols & NFC_PROTO_ISO14443_MASK) | 1060 | if (im_protocols & NFC_PROTO_ISO14443_MASK) |
997 | pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); | 1061 | pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); |
1062 | |||
1063 | if (tm_protocols) | ||
1064 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); | ||
1065 | } | ||
1066 | |||
1067 | static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | ||
1068 | u8 *params, int params_len) | ||
1069 | { | ||
1070 | struct pn533_poll_response *resp; | ||
1071 | int rc; | ||
1072 | |||
1073 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1074 | |||
1075 | resp = (struct pn533_poll_response *) params; | ||
1076 | if (resp->nbtg) { | ||
1077 | rc = pn533_target_found(dev, resp, params_len); | ||
1078 | |||
1079 | /* We must stop the poll after a valid target found */ | ||
1080 | if (rc == 0) { | ||
1081 | pn533_poll_reset_mod_list(dev); | ||
1082 | return 0; | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | return -EAGAIN; | ||
998 | } | 1087 | } |
999 | 1088 | ||
1000 | static void pn533_start_poll_frame(struct pn533_frame *frame, | 1089 | static int pn533_init_target_frame(struct pn533_frame *frame, |
1001 | struct pn533_poll_modulations *mod) | 1090 | u8 *gb, size_t gb_len) |
1002 | { | 1091 | { |
1092 | struct pn533_cmd_init_target *cmd; | ||
1093 | size_t cmd_len; | ||
1094 | u8 felica_params[18] = {0x1, 0xfe, /* DEP */ | ||
1095 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ | ||
1096 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | ||
1097 | 0xff, 0xff}; /* System code */ | ||
1098 | u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */ | ||
1099 | 0x0, 0x0, 0x0, | ||
1100 | 0x40}; /* SEL_RES for DEP */ | ||
1101 | |||
1102 | cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1; | ||
1103 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
1104 | if (cmd == NULL) | ||
1105 | return -ENOMEM; | ||
1106 | |||
1107 | pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET); | ||
1108 | |||
1109 | /* DEP support only */ | ||
1110 | cmd->mode |= PN533_INIT_TARGET_DEP; | ||
1111 | |||
1112 | /* Felica params */ | ||
1113 | memcpy(cmd->felica, felica_params, 18); | ||
1114 | get_random_bytes(cmd->felica + 2, 6); | ||
1115 | |||
1116 | /* NFCID3 */ | ||
1117 | memset(cmd->nfcid3, 0, 10); | ||
1118 | memcpy(cmd->nfcid3, cmd->felica, 8); | ||
1003 | 1119 | ||
1004 | pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); | 1120 | /* MIFARE params */ |
1121 | memcpy(cmd->mifare, mifare_params, 6); | ||
1005 | 1122 | ||
1006 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); | 1123 | /* General bytes */ |
1007 | frame->datalen += mod->len; | 1124 | cmd->gb_len = gb_len; |
1125 | memcpy(cmd->gb, gb, gb_len); | ||
1126 | |||
1127 | /* Len Tk */ | ||
1128 | cmd->gb[gb_len] = 0; | ||
1129 | |||
1130 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len); | ||
1131 | |||
1132 | frame->datalen += cmd_len; | ||
1008 | 1133 | ||
1009 | pn533_tx_frame_finish(frame); | 1134 | pn533_tx_frame_finish(frame); |
1135 | |||
1136 | kfree(cmd); | ||
1137 | |||
1138 | return 0; | ||
1010 | } | 1139 | } |
1011 | 1140 | ||
1012 | static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | 1141 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) |
1013 | u8 *params, int params_len) | 1142 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 |
1143 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, | ||
1144 | u8 *params, int params_len) | ||
1014 | { | 1145 | { |
1015 | struct pn533_poll_response *resp; | 1146 | struct sk_buff *skb_resp = arg; |
1016 | struct pn533_poll_modulations *next_mod; | 1147 | struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; |
1017 | int rc; | ||
1018 | 1148 | ||
1019 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1149 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1020 | 1150 | ||
1021 | if (params_len == -ENOENT) { | 1151 | if (params_len < 0) { |
1022 | nfc_dev_dbg(&dev->interface->dev, "Polling operation has been" | 1152 | nfc_dev_err(&dev->interface->dev, |
1023 | " stopped"); | 1153 | "Error %d when starting as a target", |
1024 | goto stop_poll; | 1154 | params_len); |
1155 | |||
1156 | return params_len; | ||
1025 | } | 1157 | } |
1026 | 1158 | ||
1159 | if (params_len > 0 && params[0] != 0) { | ||
1160 | nfc_tm_deactivated(dev->nfc_dev); | ||
1161 | |||
1162 | dev->tgt_mode = 0; | ||
1163 | |||
1164 | kfree_skb(skb_resp); | ||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); | ||
1169 | skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1170 | skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); | ||
1171 | |||
1172 | return nfc_tm_data_received(dev->nfc_dev, skb_resp); | ||
1173 | } | ||
1174 | |||
1175 | static void pn533_wq_tg_get_data(struct work_struct *work) | ||
1176 | { | ||
1177 | struct pn533 *dev = container_of(work, struct pn533, tg_work); | ||
1178 | struct pn533_frame *in_frame; | ||
1179 | struct sk_buff *skb_resp; | ||
1180 | size_t skb_resp_len; | ||
1181 | |||
1182 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1183 | |||
1184 | skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + | ||
1185 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | ||
1186 | PN533_FRAME_TAIL_SIZE; | ||
1187 | |||
1188 | skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); | ||
1189 | if (!skb_resp) | ||
1190 | return; | ||
1191 | |||
1192 | in_frame = (struct pn533_frame *)skb_resp->data; | ||
1193 | |||
1194 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA); | ||
1195 | pn533_tx_frame_finish(dev->out_frame); | ||
1196 | |||
1197 | pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, | ||
1198 | skb_resp_len, | ||
1199 | pn533_tm_get_data_complete, | ||
1200 | skb_resp, GFP_KERNEL); | ||
1201 | |||
1202 | return; | ||
1203 | } | ||
1204 | |||
1205 | #define ATR_REQ_GB_OFFSET 17 | ||
1206 | static int pn533_init_target_complete(struct pn533 *dev, void *arg, | ||
1207 | u8 *params, int params_len) | ||
1208 | { | ||
1209 | struct pn533_cmd_init_target_response *resp; | ||
1210 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; | ||
1211 | size_t gb_len; | ||
1212 | int rc; | ||
1213 | |||
1214 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1215 | |||
1027 | if (params_len < 0) { | 1216 | if (params_len < 0) { |
1028 | nfc_dev_err(&dev->interface->dev, "Error %d when running poll", | 1217 | nfc_dev_err(&dev->interface->dev, |
1029 | params_len); | 1218 | "Error %d when starting as a target", |
1030 | goto stop_poll; | 1219 | params_len); |
1220 | |||
1221 | return params_len; | ||
1031 | } | 1222 | } |
1032 | 1223 | ||
1033 | resp = (struct pn533_poll_response *) params; | 1224 | if (params_len < ATR_REQ_GB_OFFSET + 1) |
1034 | if (resp->nbtg) { | 1225 | return -EINVAL; |
1035 | rc = pn533_target_found(dev, resp, params_len); | ||
1036 | 1226 | ||
1037 | /* We must stop the poll after a valid target found */ | 1227 | resp = (struct pn533_cmd_init_target_response *) params; |
1038 | if (rc == 0) | 1228 | |
1039 | goto stop_poll; | 1229 | nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n", |
1230 | resp->mode, params_len); | ||
1231 | |||
1232 | frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK; | ||
1233 | if (frame == PN533_INIT_TARGET_RESP_ACTIVE) | ||
1234 | comm_mode = NFC_COMM_ACTIVE; | ||
1040 | 1235 | ||
1041 | if (rc != -EAGAIN) | 1236 | /* Again, only DEP */ |
1042 | nfc_dev_err(&dev->interface->dev, "The target found is" | 1237 | if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0) |
1043 | " not valid - continuing to poll"); | 1238 | return -EOPNOTSUPP; |
1239 | |||
1240 | gb = resp->cmd + ATR_REQ_GB_OFFSET; | ||
1241 | gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); | ||
1242 | |||
1243 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | ||
1244 | comm_mode, gb, gb_len); | ||
1245 | if (rc < 0) { | ||
1246 | nfc_dev_err(&dev->interface->dev, | ||
1247 | "Error when signaling target activation"); | ||
1248 | return rc; | ||
1044 | } | 1249 | } |
1045 | 1250 | ||
1046 | dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; | 1251 | dev->tgt_mode = 1; |
1047 | 1252 | ||
1048 | next_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1253 | queue_work(dev->wq, &dev->tg_work); |
1049 | 1254 | ||
1050 | nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)", | 1255 | return 0; |
1051 | dev->poll_mod_curr); | 1256 | } |
1257 | |||
1258 | static void pn533_listen_mode_timer(unsigned long data) | ||
1259 | { | ||
1260 | struct pn533 *dev = (struct pn533 *) data; | ||
1261 | |||
1262 | nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); | ||
1263 | |||
1264 | /* An ack will cancel the last issued command (poll) */ | ||
1265 | pn533_send_ack(dev, GFP_ATOMIC); | ||
1266 | |||
1267 | dev->cancel_listen = 1; | ||
1268 | |||
1269 | mutex_unlock(&dev->cmd_lock); | ||
1270 | |||
1271 | pn533_poll_next_mod(dev); | ||
1272 | |||
1273 | queue_work(dev->wq, &dev->poll_work); | ||
1274 | } | ||
1052 | 1275 | ||
1053 | pn533_start_poll_frame(dev->out_frame, next_mod); | 1276 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
1277 | u8 *params, int params_len) | ||
1278 | { | ||
1279 | struct pn533_poll_modulations *cur_mod; | ||
1280 | int rc; | ||
1054 | 1281 | ||
1055 | /* Don't need to down the semaphore again */ | 1282 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1056 | rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1283 | |
1057 | dev->in_maxlen, pn533_start_poll_complete, | 1284 | if (params_len == -ENOENT) { |
1058 | NULL, GFP_ATOMIC); | 1285 | if (dev->poll_mod_count != 0) |
1286 | return 0; | ||
1287 | |||
1288 | nfc_dev_err(&dev->interface->dev, | ||
1289 | "Polling operation has been stopped"); | ||
1059 | 1290 | ||
1060 | if (rc == -EPERM) { | ||
1061 | nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation" | ||
1062 | " because poll has been stopped"); | ||
1063 | goto stop_poll; | 1291 | goto stop_poll; |
1064 | } | 1292 | } |
1065 | 1293 | ||
1066 | if (rc) { | 1294 | if (params_len < 0) { |
1067 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll" | 1295 | nfc_dev_err(&dev->interface->dev, |
1068 | " next modulation", rc); | 1296 | "Error %d when running poll", params_len); |
1297 | |||
1069 | goto stop_poll; | 1298 | goto stop_poll; |
1070 | } | 1299 | } |
1071 | 1300 | ||
1072 | /* Inform caller function to do not up the semaphore */ | 1301 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1073 | return -EINPROGRESS; | 1302 | |
1303 | if (cur_mod->len == 0) { | ||
1304 | del_timer(&dev->listen_timer); | ||
1305 | |||
1306 | return pn533_init_target_complete(dev, arg, params, params_len); | ||
1307 | } else { | ||
1308 | rc = pn533_start_poll_complete(dev, arg, params, params_len); | ||
1309 | if (!rc) | ||
1310 | return rc; | ||
1311 | } | ||
1312 | |||
1313 | pn533_poll_next_mod(dev); | ||
1314 | |||
1315 | queue_work(dev->wq, &dev->poll_work); | ||
1316 | |||
1317 | return 0; | ||
1074 | 1318 | ||
1075 | stop_poll: | 1319 | stop_poll: |
1076 | pn533_poll_reset_mod_list(dev); | 1320 | pn533_poll_reset_mod_list(dev); |
@@ -1078,61 +1322,104 @@ stop_poll: | |||
1078 | return 0; | 1322 | return 0; |
1079 | } | 1323 | } |
1080 | 1324 | ||
1081 | static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 1325 | static void pn533_build_poll_frame(struct pn533 *dev, |
1326 | struct pn533_frame *frame, | ||
1327 | struct pn533_poll_modulations *mod) | ||
1082 | { | 1328 | { |
1083 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1329 | nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len); |
1084 | struct pn533_poll_modulations *start_mod; | ||
1085 | int rc; | ||
1086 | 1330 | ||
1087 | nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__, | 1331 | if (mod->len == 0) { |
1088 | protocols); | 1332 | /* Listen mode */ |
1333 | pn533_init_target_frame(frame, dev->gb, dev->gb_len); | ||
1334 | } else { | ||
1335 | /* Polling mode */ | ||
1336 | pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); | ||
1089 | 1337 | ||
1090 | if (dev->poll_mod_count) { | 1338 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); |
1091 | nfc_dev_err(&dev->interface->dev, "Polling operation already" | 1339 | frame->datalen += mod->len; |
1092 | " active"); | ||
1093 | return -EBUSY; | ||
1094 | } | ||
1095 | 1340 | ||
1096 | if (dev->tgt_active_prot) { | 1341 | pn533_tx_frame_finish(frame); |
1097 | nfc_dev_err(&dev->interface->dev, "Cannot poll with a target" | ||
1098 | " already activated"); | ||
1099 | return -EBUSY; | ||
1100 | } | 1342 | } |
1343 | } | ||
1101 | 1344 | ||
1102 | pn533_poll_create_mod_list(dev, protocols); | 1345 | static int pn533_send_poll_frame(struct pn533 *dev) |
1346 | { | ||
1347 | struct pn533_poll_modulations *cur_mod; | ||
1348 | int rc; | ||
1103 | 1349 | ||
1104 | if (!dev->poll_mod_count) { | 1350 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1105 | nfc_dev_err(&dev->interface->dev, "No valid protocols" | 1351 | |
1106 | " specified"); | 1352 | pn533_build_poll_frame(dev, dev->out_frame, cur_mod); |
1107 | rc = -EINVAL; | 1353 | |
1108 | goto error; | 1354 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, |
1355 | dev->in_maxlen, pn533_poll_complete, | ||
1356 | NULL, GFP_KERNEL); | ||
1357 | if (rc) | ||
1358 | nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); | ||
1359 | |||
1360 | return rc; | ||
1361 | } | ||
1362 | |||
1363 | static void pn533_wq_poll(struct work_struct *work) | ||
1364 | { | ||
1365 | struct pn533 *dev = container_of(work, struct pn533, poll_work); | ||
1366 | struct pn533_poll_modulations *cur_mod; | ||
1367 | int rc; | ||
1368 | |||
1369 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; | ||
1370 | |||
1371 | nfc_dev_dbg(&dev->interface->dev, | ||
1372 | "%s cancel_listen %d modulation len %d", | ||
1373 | __func__, dev->cancel_listen, cur_mod->len); | ||
1374 | |||
1375 | if (dev->cancel_listen == 1) { | ||
1376 | dev->cancel_listen = 0; | ||
1377 | usb_kill_urb(dev->in_urb); | ||
1109 | } | 1378 | } |
1110 | 1379 | ||
1111 | nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types", | 1380 | rc = pn533_send_poll_frame(dev); |
1112 | dev->poll_mod_count); | 1381 | if (rc) |
1382 | return; | ||
1113 | 1383 | ||
1114 | dev->poll_mod_curr = 0; | 1384 | if (cur_mod->len == 0 && dev->poll_mod_count > 1) |
1115 | start_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1385 | mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); |
1116 | 1386 | ||
1117 | pn533_start_poll_frame(dev->out_frame, start_mod); | 1387 | return; |
1388 | } | ||
1118 | 1389 | ||
1119 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1390 | static int pn533_start_poll(struct nfc_dev *nfc_dev, |
1120 | dev->in_maxlen, pn533_start_poll_complete, | 1391 | u32 im_protocols, u32 tm_protocols) |
1121 | NULL, GFP_KERNEL); | 1392 | { |
1393 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1122 | 1394 | ||
1123 | if (rc) { | 1395 | nfc_dev_dbg(&dev->interface->dev, |
1124 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to" | 1396 | "%s: im protocols 0x%x tm protocols 0x%x", |
1125 | " start poll", rc); | 1397 | __func__, im_protocols, tm_protocols); |
1126 | goto error; | 1398 | |
1399 | if (dev->tgt_active_prot) { | ||
1400 | nfc_dev_err(&dev->interface->dev, | ||
1401 | "Cannot poll with a target already activated"); | ||
1402 | return -EBUSY; | ||
1127 | } | 1403 | } |
1128 | 1404 | ||
1129 | dev->poll_protocols = protocols; | 1405 | if (dev->tgt_mode) { |
1406 | nfc_dev_err(&dev->interface->dev, | ||
1407 | "Cannot poll while already being activated"); | ||
1408 | return -EBUSY; | ||
1409 | } | ||
1130 | 1410 | ||
1131 | return 0; | 1411 | if (tm_protocols) { |
1412 | dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); | ||
1413 | if (dev->gb == NULL) | ||
1414 | tm_protocols = 0; | ||
1415 | } | ||
1132 | 1416 | ||
1133 | error: | 1417 | dev->poll_mod_curr = 0; |
1134 | pn533_poll_reset_mod_list(dev); | 1418 | pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); |
1135 | return rc; | 1419 | dev->poll_protocols = im_protocols; |
1420 | dev->listen_protocols = tm_protocols; | ||
1421 | |||
1422 | return pn533_send_poll_frame(dev); | ||
1136 | } | 1423 | } |
1137 | 1424 | ||
1138 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) | 1425 | static void pn533_stop_poll(struct nfc_dev *nfc_dev) |
@@ -1141,6 +1428,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1141 | 1428 | ||
1142 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1429 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1143 | 1430 | ||
1431 | del_timer(&dev->listen_timer); | ||
1432 | |||
1144 | if (!dev->poll_mod_count) { | 1433 | if (!dev->poll_mod_count) { |
1145 | nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" | 1434 | nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" |
1146 | " running"); | 1435 | " running"); |
@@ -1152,6 +1441,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1152 | 1441 | ||
1153 | /* prevent pn533_start_poll_complete to issue a new poll meanwhile */ | 1442 | /* prevent pn533_start_poll_complete to issue a new poll meanwhile */ |
1154 | usb_kill_urb(dev->in_urb); | 1443 | usb_kill_urb(dev->in_urb); |
1444 | |||
1445 | pn533_poll_reset_mod_list(dev); | ||
1155 | } | 1446 | } |
1156 | 1447 | ||
1157 | static int pn533_activate_target_nfcdep(struct pn533 *dev) | 1448 | static int pn533_activate_target_nfcdep(struct pn533 *dev) |
@@ -1349,13 +1640,29 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
1349 | return 0; | 1640 | return 0; |
1350 | } | 1641 | } |
1351 | 1642 | ||
1643 | static int pn533_mod_to_baud(struct pn533 *dev) | ||
1644 | { | ||
1645 | switch (dev->poll_mod_curr) { | ||
1646 | case PN533_POLL_MOD_106KBPS_A: | ||
1647 | return 0; | ||
1648 | case PN533_POLL_MOD_212KBPS_FELICA: | ||
1649 | return 1; | ||
1650 | case PN533_POLL_MOD_424KBPS_FELICA: | ||
1651 | return 2; | ||
1652 | default: | ||
1653 | return -EINVAL; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | #define PASSIVE_DATA_LEN 5 | ||
1352 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 1658 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
1353 | u8 comm_mode, u8* gb, size_t gb_len) | 1659 | u8 comm_mode, u8* gb, size_t gb_len) |
1354 | { | 1660 | { |
1355 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1661 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1356 | struct pn533_cmd_jump_dep *cmd; | 1662 | struct pn533_cmd_jump_dep *cmd; |
1357 | u8 cmd_len; | 1663 | u8 cmd_len, *data_ptr; |
1358 | int rc; | 1664 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; |
1665 | int rc, baud; | ||
1359 | 1666 | ||
1360 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1667 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1361 | 1668 | ||
@@ -1371,7 +1678,17 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
1371 | return -EBUSY; | 1678 | return -EBUSY; |
1372 | } | 1679 | } |
1373 | 1680 | ||
1681 | baud = pn533_mod_to_baud(dev); | ||
1682 | if (baud < 0) { | ||
1683 | nfc_dev_err(&dev->interface->dev, | ||
1684 | "Invalid curr modulation %d", dev->poll_mod_curr); | ||
1685 | return baud; | ||
1686 | } | ||
1687 | |||
1374 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; | 1688 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; |
1689 | if (comm_mode == NFC_COMM_PASSIVE) | ||
1690 | cmd_len += PASSIVE_DATA_LEN; | ||
1691 | |||
1375 | cmd = kzalloc(cmd_len, GFP_KERNEL); | 1692 | cmd = kzalloc(cmd_len, GFP_KERNEL); |
1376 | if (cmd == NULL) | 1693 | if (cmd == NULL) |
1377 | return -ENOMEM; | 1694 | return -ENOMEM; |
@@ -1379,10 +1696,18 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
1379 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); | 1696 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); |
1380 | 1697 | ||
1381 | cmd->active = !comm_mode; | 1698 | cmd->active = !comm_mode; |
1382 | cmd->baud = 0; | 1699 | cmd->next = 0; |
1700 | cmd->baud = baud; | ||
1701 | data_ptr = cmd->data; | ||
1702 | if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) { | ||
1703 | memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN); | ||
1704 | cmd->next |= 1; | ||
1705 | data_ptr += PASSIVE_DATA_LEN; | ||
1706 | } | ||
1707 | |||
1383 | if (gb != NULL && gb_len > 0) { | 1708 | if (gb != NULL && gb_len > 0) { |
1384 | cmd->next = 4; /* We have some Gi */ | 1709 | cmd->next |= 4; /* We have some Gi */ |
1385 | memcpy(cmd->gt, gb, gb_len); | 1710 | memcpy(data_ptr, gb, gb_len); |
1386 | } else { | 1711 | } else { |
1387 | cmd->next = 0; | 1712 | cmd->next = 0; |
1388 | } | 1713 | } |
@@ -1407,15 +1732,25 @@ out: | |||
1407 | 1732 | ||
1408 | static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | 1733 | static int pn533_dep_link_down(struct nfc_dev *nfc_dev) |
1409 | { | 1734 | { |
1410 | pn533_deactivate_target(nfc_dev, 0); | 1735 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1736 | |||
1737 | pn533_poll_reset_mod_list(dev); | ||
1738 | |||
1739 | if (dev->tgt_mode || dev->tgt_active_prot) { | ||
1740 | pn533_send_ack(dev, GFP_KERNEL); | ||
1741 | usb_kill_urb(dev->in_urb); | ||
1742 | } | ||
1743 | |||
1744 | dev->tgt_active_prot = 0; | ||
1745 | dev->tgt_mode = 0; | ||
1746 | |||
1747 | skb_queue_purge(&dev->resp_q); | ||
1411 | 1748 | ||
1412 | return 0; | 1749 | return 0; |
1413 | } | 1750 | } |
1414 | 1751 | ||
1415 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) | 1752 | static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, |
1416 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 | 1753 | bool target) |
1417 | |||
1418 | static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | ||
1419 | { | 1754 | { |
1420 | int payload_len = skb->len; | 1755 | int payload_len = skb->len; |
1421 | struct pn533_frame *out_frame; | 1756 | struct pn533_frame *out_frame; |
@@ -1432,14 +1767,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) | |||
1432 | return -ENOSYS; | 1767 | return -ENOSYS; |
1433 | } | 1768 | } |
1434 | 1769 | ||
1435 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | 1770 | if (target == true) { |
1436 | out_frame = (struct pn533_frame *) skb->data; | 1771 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); |
1772 | out_frame = (struct pn533_frame *) skb->data; | ||
1437 | 1773 | ||
1438 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); | 1774 | pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); |
1775 | tg = 1; | ||
1776 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1777 | out_frame->datalen += sizeof(u8); | ||
1778 | } else { | ||
1779 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1780 | out_frame = (struct pn533_frame *) skb->data; | ||
1781 | pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA); | ||
1782 | } | ||
1439 | 1783 | ||
1440 | tg = 1; | ||
1441 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); | ||
1442 | out_frame->datalen += sizeof(u8); | ||
1443 | 1784 | ||
1444 | /* The data is already in the out_frame, just update the datalen */ | 1785 | /* The data is already in the out_frame, just update the datalen */ |
1445 | out_frame->datalen += payload_len; | 1786 | out_frame->datalen += payload_len; |
@@ -1550,9 +1891,9 @@ error: | |||
1550 | return 0; | 1891 | return 0; |
1551 | } | 1892 | } |
1552 | 1893 | ||
1553 | static int pn533_data_exchange(struct nfc_dev *nfc_dev, | 1894 | static int pn533_transceive(struct nfc_dev *nfc_dev, |
1554 | struct nfc_target *target, struct sk_buff *skb, | 1895 | struct nfc_target *target, struct sk_buff *skb, |
1555 | data_exchange_cb_t cb, void *cb_context) | 1896 | data_exchange_cb_t cb, void *cb_context) |
1556 | { | 1897 | { |
1557 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1898 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1558 | struct pn533_frame *out_frame, *in_frame; | 1899 | struct pn533_frame *out_frame, *in_frame; |
@@ -1570,7 +1911,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev, | |||
1570 | goto error; | 1911 | goto error; |
1571 | } | 1912 | } |
1572 | 1913 | ||
1573 | rc = pn533_data_exchange_tx_frame(dev, skb); | 1914 | rc = pn533_build_tx_frame(dev, skb, true); |
1574 | if (rc) | 1915 | if (rc) |
1575 | goto error; | 1916 | goto error; |
1576 | 1917 | ||
@@ -1618,6 +1959,63 @@ error: | |||
1618 | return rc; | 1959 | return rc; |
1619 | } | 1960 | } |
1620 | 1961 | ||
1962 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | ||
1963 | u8 *params, int params_len) | ||
1964 | { | ||
1965 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1966 | |||
1967 | if (params_len < 0) { | ||
1968 | nfc_dev_err(&dev->interface->dev, | ||
1969 | "Error %d when sending data", | ||
1970 | params_len); | ||
1971 | |||
1972 | return params_len; | ||
1973 | } | ||
1974 | |||
1975 | if (params_len > 0 && params[0] != 0) { | ||
1976 | nfc_tm_deactivated(dev->nfc_dev); | ||
1977 | |||
1978 | dev->tgt_mode = 0; | ||
1979 | |||
1980 | return 0; | ||
1981 | } | ||
1982 | |||
1983 | queue_work(dev->wq, &dev->tg_work); | ||
1984 | |||
1985 | return 0; | ||
1986 | } | ||
1987 | |||
1988 | static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | ||
1989 | { | ||
1990 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
1991 | struct pn533_frame *out_frame; | ||
1992 | int rc; | ||
1993 | |||
1994 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1995 | |||
1996 | rc = pn533_build_tx_frame(dev, skb, false); | ||
1997 | if (rc) | ||
1998 | goto error; | ||
1999 | |||
2000 | out_frame = (struct pn533_frame *) skb->data; | ||
2001 | |||
2002 | rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, | ||
2003 | dev->in_maxlen, pn533_tm_send_complete, | ||
2004 | NULL, GFP_KERNEL); | ||
2005 | if (rc) { | ||
2006 | nfc_dev_err(&dev->interface->dev, | ||
2007 | "Error %d when trying to send data", rc); | ||
2008 | goto error; | ||
2009 | } | ||
2010 | |||
2011 | return 0; | ||
2012 | |||
2013 | error: | ||
2014 | kfree_skb(skb); | ||
2015 | |||
2016 | return rc; | ||
2017 | } | ||
2018 | |||
1621 | static void pn533_wq_mi_recv(struct work_struct *work) | 2019 | static void pn533_wq_mi_recv(struct work_struct *work) |
1622 | { | 2020 | { |
1623 | struct pn533 *dev = container_of(work, struct pn533, mi_work); | 2021 | struct pn533 *dev = container_of(work, struct pn533, mi_work); |
@@ -1638,7 +2036,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) | |||
1638 | 2036 | ||
1639 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); | 2037 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); |
1640 | 2038 | ||
1641 | rc = pn533_data_exchange_tx_frame(dev, skb_cmd); | 2039 | rc = pn533_build_tx_frame(dev, skb_cmd, true); |
1642 | if (rc) | 2040 | if (rc) |
1643 | goto error_frame; | 2041 | goto error_frame; |
1644 | 2042 | ||
@@ -1677,7 +2075,7 @@ error_cmd: | |||
1677 | 2075 | ||
1678 | kfree(arg); | 2076 | kfree(arg); |
1679 | 2077 | ||
1680 | up(&dev->cmd_lock); | 2078 | mutex_unlock(&dev->cmd_lock); |
1681 | } | 2079 | } |
1682 | 2080 | ||
1683 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | 2081 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, |
@@ -1712,7 +2110,8 @@ struct nfc_ops pn533_nfc_ops = { | |||
1712 | .stop_poll = pn533_stop_poll, | 2110 | .stop_poll = pn533_stop_poll, |
1713 | .activate_target = pn533_activate_target, | 2111 | .activate_target = pn533_activate_target, |
1714 | .deactivate_target = pn533_deactivate_target, | 2112 | .deactivate_target = pn533_deactivate_target, |
1715 | .data_exchange = pn533_data_exchange, | 2113 | .im_transceive = pn533_transceive, |
2114 | .tm_send = pn533_tm_send, | ||
1716 | }; | 2115 | }; |
1717 | 2116 | ||
1718 | static int pn533_probe(struct usb_interface *interface, | 2117 | static int pn533_probe(struct usb_interface *interface, |
@@ -1723,6 +2122,7 @@ static int pn533_probe(struct usb_interface *interface, | |||
1723 | struct usb_host_interface *iface_desc; | 2122 | struct usb_host_interface *iface_desc; |
1724 | struct usb_endpoint_descriptor *endpoint; | 2123 | struct usb_endpoint_descriptor *endpoint; |
1725 | struct pn533_config_max_retries max_retries; | 2124 | struct pn533_config_max_retries max_retries; |
2125 | struct pn533_config_timing timing; | ||
1726 | int in_endpoint = 0; | 2126 | int in_endpoint = 0; |
1727 | int out_endpoint = 0; | 2127 | int out_endpoint = 0; |
1728 | int rc = -ENOMEM; | 2128 | int rc = -ENOMEM; |
@@ -1735,7 +2135,7 @@ static int pn533_probe(struct usb_interface *interface, | |||
1735 | 2135 | ||
1736 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 2136 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
1737 | dev->interface = interface; | 2137 | dev->interface = interface; |
1738 | sema_init(&dev->cmd_lock, 1); | 2138 | mutex_init(&dev->cmd_lock); |
1739 | 2139 | ||
1740 | iface_desc = interface->cur_altsetting; | 2140 | iface_desc = interface->cur_altsetting; |
1741 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 2141 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
@@ -1779,12 +2179,18 @@ static int pn533_probe(struct usb_interface *interface, | |||
1779 | 2179 | ||
1780 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); | 2180 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); |
1781 | INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); | 2181 | INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); |
2182 | INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); | ||
2183 | INIT_WORK(&dev->poll_work, pn533_wq_poll); | ||
1782 | dev->wq = alloc_workqueue("pn533", | 2184 | dev->wq = alloc_workqueue("pn533", |
1783 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, | 2185 | WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, |
1784 | 1); | 2186 | 1); |
1785 | if (dev->wq == NULL) | 2187 | if (dev->wq == NULL) |
1786 | goto error; | 2188 | goto error; |
1787 | 2189 | ||
2190 | init_timer(&dev->listen_timer); | ||
2191 | dev->listen_timer.data = (unsigned long) dev; | ||
2192 | dev->listen_timer.function = pn533_listen_mode_timer; | ||
2193 | |||
1788 | skb_queue_head_init(&dev->resp_q); | 2194 | skb_queue_head_init(&dev->resp_q); |
1789 | 2195 | ||
1790 | usb_set_intfdata(interface, dev); | 2196 | usb_set_intfdata(interface, dev); |
@@ -1830,13 +2236,29 @@ static int pn533_probe(struct usb_interface *interface, | |||
1830 | if (rc) { | 2236 | if (rc) { |
1831 | nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" | 2237 | nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" |
1832 | " config"); | 2238 | " config"); |
1833 | goto free_nfc_dev; | 2239 | goto unregister_nfc_dev; |
2240 | } | ||
2241 | |||
2242 | timing.rfu = PN533_CONFIG_TIMING_102; | ||
2243 | timing.atr_res_timeout = PN533_CONFIG_TIMING_204; | ||
2244 | timing.dep_timeout = PN533_CONFIG_TIMING_409; | ||
2245 | |||
2246 | rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, | ||
2247 | (u8 *) &timing, sizeof(timing)); | ||
2248 | if (rc) { | ||
2249 | nfc_dev_err(&dev->interface->dev, | ||
2250 | "Error on setting RF timings"); | ||
2251 | goto unregister_nfc_dev; | ||
1834 | } | 2252 | } |
1835 | 2253 | ||
1836 | return 0; | 2254 | return 0; |
1837 | 2255 | ||
2256 | unregister_nfc_dev: | ||
2257 | nfc_unregister_device(dev->nfc_dev); | ||
2258 | |||
1838 | free_nfc_dev: | 2259 | free_nfc_dev: |
1839 | nfc_free_device(dev->nfc_dev); | 2260 | nfc_free_device(dev->nfc_dev); |
2261 | |||
1840 | destroy_wq: | 2262 | destroy_wq: |
1841 | destroy_workqueue(dev->wq); | 2263 | destroy_workqueue(dev->wq); |
1842 | error: | 2264 | error: |
@@ -1865,6 +2287,8 @@ static void pn533_disconnect(struct usb_interface *interface) | |||
1865 | 2287 | ||
1866 | skb_queue_purge(&dev->resp_q); | 2288 | skb_queue_purge(&dev->resp_q); |
1867 | 2289 | ||
2290 | del_timer(&dev->listen_timer); | ||
2291 | |||
1868 | kfree(dev->in_frame); | 2292 | kfree(dev->in_frame); |
1869 | usb_free_urb(dev->in_urb); | 2293 | usb_free_urb(dev->in_urb); |
1870 | kfree(dev->out_frame); | 2294 | kfree(dev->out_frame); |
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c index 281f18c2fb82..457eac35dc74 100644 --- a/drivers/nfc/pn544_hci.c +++ b/drivers/nfc/pn544_hci.c | |||
@@ -576,7 +576,8 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb) | |||
576 | return pn544_hci_i2c_write(client, skb->data, skb->len); | 576 | return pn544_hci_i2c_write(client, skb->data, skb->len); |
577 | } | 577 | } |
578 | 578 | ||
579 | static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | 579 | static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, |
580 | u32 im_protocols, u32 tm_protocols) | ||
580 | { | 581 | { |
581 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | 582 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); |
582 | u8 phases = 0; | 583 | u8 phases = 0; |
@@ -584,7 +585,8 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | |||
584 | u8 duration[2]; | 585 | u8 duration[2]; |
585 | u8 activated; | 586 | u8 activated; |
586 | 587 | ||
587 | pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols); | 588 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
589 | __func__, im_protocols, tm_protocols); | ||
588 | 590 | ||
589 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 591 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
590 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 592 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
@@ -604,10 +606,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | |||
604 | if (r < 0) | 606 | if (r < 0) |
605 | return r; | 607 | return r; |
606 | 608 | ||
607 | if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | | 609 | if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | |
608 | NFC_PROTO_JEWEL_MASK)) | 610 | NFC_PROTO_JEWEL_MASK)) |
609 | phases |= 1; /* Type A */ | 611 | phases |= 1; /* Type A */ |
610 | if (protocols & NFC_PROTO_FELICA_MASK) { | 612 | if (im_protocols & NFC_PROTO_FELICA_MASK) { |
611 | phases |= (1 << 2); /* Type F 212 */ | 613 | phases |= (1 << 2); /* Type F 212 */ |
612 | phases |= (1 << 3); /* Type F 424 */ | 614 | phases |= (1 << 3); /* Type F 424 */ |
613 | } | 615 | } |
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index f551e5376147..266aa1648a02 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c | |||
@@ -36,6 +36,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { | |||
36 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, | 36 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, |
37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, | 37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, |
38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, | 38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, |
39 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, | ||
39 | { 0, }, | 40 | { 0, }, |
40 | }; | 41 | }; |
41 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); | 42 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 266c7c5c86dc..ab4627cf1114 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -90,6 +90,8 @@ const char *ssb_core_name(u16 coreid) | |||
90 | return "ARM 1176"; | 90 | return "ARM 1176"; |
91 | case SSB_DEV_ARM_7TDMI: | 91 | case SSB_DEV_ARM_7TDMI: |
92 | return "ARM 7TDMI"; | 92 | return "ARM 7TDMI"; |
93 | case SSB_DEV_ARM_CM3: | ||
94 | return "ARM Cortex M3"; | ||
93 | } | 95 | } |
94 | return "UNKNOWN"; | 96 | return "UNKNOWN"; |
95 | } | 97 | } |
diff --git a/include/linux/nfc.h b/include/linux/nfc.h index 0ae9b5857c83..f4e6dd915b1c 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h | |||
@@ -56,6 +56,10 @@ | |||
56 | * %NFC_ATTR_PROTOCOLS) | 56 | * %NFC_ATTR_PROTOCOLS) |
57 | * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed | 57 | * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed |
58 | * (it sends %NFC_ATTR_DEVICE_INDEX) | 58 | * (it sends %NFC_ATTR_DEVICE_INDEX) |
59 | * @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in | ||
60 | * target mode. | ||
61 | * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated | ||
62 | * from target mode. | ||
59 | */ | 63 | */ |
60 | enum nfc_commands { | 64 | enum nfc_commands { |
61 | NFC_CMD_UNSPEC, | 65 | NFC_CMD_UNSPEC, |
@@ -71,6 +75,8 @@ enum nfc_commands { | |||
71 | NFC_EVENT_DEVICE_ADDED, | 75 | NFC_EVENT_DEVICE_ADDED, |
72 | NFC_EVENT_DEVICE_REMOVED, | 76 | NFC_EVENT_DEVICE_REMOVED, |
73 | NFC_EVENT_TARGET_LOST, | 77 | NFC_EVENT_TARGET_LOST, |
78 | NFC_EVENT_TM_ACTIVATED, | ||
79 | NFC_EVENT_TM_DEACTIVATED, | ||
74 | /* private: internal use only */ | 80 | /* private: internal use only */ |
75 | __NFC_CMD_AFTER_LAST | 81 | __NFC_CMD_AFTER_LAST |
76 | }; | 82 | }; |
@@ -94,6 +100,8 @@ enum nfc_commands { | |||
94 | * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes | 100 | * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes |
95 | * @NFC_ATTR_COMM_MODE: Passive or active mode | 101 | * @NFC_ATTR_COMM_MODE: Passive or active mode |
96 | * @NFC_ATTR_RF_MODE: Initiator or target | 102 | * @NFC_ATTR_RF_MODE: Initiator or target |
103 | * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for | ||
104 | * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for | ||
97 | */ | 105 | */ |
98 | enum nfc_attrs { | 106 | enum nfc_attrs { |
99 | NFC_ATTR_UNSPEC, | 107 | NFC_ATTR_UNSPEC, |
@@ -109,6 +117,8 @@ enum nfc_attrs { | |||
109 | NFC_ATTR_COMM_MODE, | 117 | NFC_ATTR_COMM_MODE, |
110 | NFC_ATTR_RF_MODE, | 118 | NFC_ATTR_RF_MODE, |
111 | NFC_ATTR_DEVICE_POWERED, | 119 | NFC_ATTR_DEVICE_POWERED, |
120 | NFC_ATTR_IM_PROTOCOLS, | ||
121 | NFC_ATTR_TM_PROTOCOLS, | ||
112 | /* private: internal use only */ | 122 | /* private: internal use only */ |
113 | __NFC_ATTR_AFTER_LAST | 123 | __NFC_ATTR_AFTER_LAST |
114 | }; | 124 | }; |
@@ -118,6 +128,7 @@ enum nfc_attrs { | |||
118 | #define NFC_NFCID1_MAXSIZE 10 | 128 | #define NFC_NFCID1_MAXSIZE 10 |
119 | #define NFC_SENSB_RES_MAXSIZE 12 | 129 | #define NFC_SENSB_RES_MAXSIZE 12 |
120 | #define NFC_SENSF_RES_MAXSIZE 18 | 130 | #define NFC_SENSF_RES_MAXSIZE 18 |
131 | #define NFC_GB_MAXSIZE 48 | ||
121 | 132 | ||
122 | /* NFC protocols */ | 133 | /* NFC protocols */ |
123 | #define NFC_PROTO_JEWEL 1 | 134 | #define NFC_PROTO_JEWEL 1 |
@@ -135,6 +146,7 @@ enum nfc_attrs { | |||
135 | /* NFC RF modes */ | 146 | /* NFC RF modes */ |
136 | #define NFC_RF_INITIATOR 0 | 147 | #define NFC_RF_INITIATOR 0 |
137 | #define NFC_RF_TARGET 1 | 148 | #define NFC_RF_TARGET 1 |
149 | #define NFC_RF_NONE 2 | ||
138 | 150 | ||
139 | /* NFC protocols masks used in bitsets */ | 151 | /* NFC protocols masks used in bitsets */ |
140 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) | 152 | #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index a6959f72745e..970afdf5a605 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -170,6 +170,8 @@ | |||
170 | * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, | 170 | * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, |
171 | * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, | 171 | * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, |
172 | * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. | 172 | * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. |
173 | * The channel to use can be set on the interface or be given using the | ||
174 | * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_CHANNEL_TYPE attrs. | ||
173 | * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP | 175 | * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP |
174 | * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface | 176 | * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface |
175 | * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP | 177 | * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP |
@@ -1520,6 +1522,8 @@ enum nl80211_attrs { | |||
1520 | #define NL80211_MAX_NR_CIPHER_SUITES 5 | 1522 | #define NL80211_MAX_NR_CIPHER_SUITES 5 |
1521 | #define NL80211_MAX_NR_AKM_SUITES 2 | 1523 | #define NL80211_MAX_NR_AKM_SUITES 2 |
1522 | 1524 | ||
1525 | #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 | ||
1526 | |||
1523 | /** | 1527 | /** |
1524 | * enum nl80211_iftype - (virtual) interface types | 1528 | * enum nl80211_iftype - (virtual) interface types |
1525 | * | 1529 | * |
@@ -2534,10 +2538,14 @@ enum nl80211_attr_cqm { | |||
2534 | * configured threshold | 2538 | * configured threshold |
2535 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the | 2539 | * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the |
2536 | * configured threshold | 2540 | * configured threshold |
2541 | * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: The device experienced beacon loss. | ||
2542 | * (Note that deauth/disassoc will still follow if the AP is not | ||
2543 | * available. This event might get used as roaming event, etc.) | ||
2537 | */ | 2544 | */ |
2538 | enum nl80211_cqm_rssi_threshold_event { | 2545 | enum nl80211_cqm_rssi_threshold_event { |
2539 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | 2546 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, |
2540 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | 2547 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, |
2548 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | ||
2541 | }; | 2549 | }; |
2542 | 2550 | ||
2543 | 2551 | ||
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index bc14bd738ade..bb674c02f306 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -243,6 +243,7 @@ struct ssb_bus_ops { | |||
243 | #define SSB_DEV_MINI_MACPHY 0x823 | 243 | #define SSB_DEV_MINI_MACPHY 0x823 |
244 | #define SSB_DEV_ARM_1176 0x824 | 244 | #define SSB_DEV_ARM_1176 0x824 |
245 | #define SSB_DEV_ARM_7TDMI 0x825 | 245 | #define SSB_DEV_ARM_7TDMI 0x825 |
246 | #define SSB_DEV_ARM_CM3 0x82A | ||
246 | 247 | ||
247 | /* Vendor-ID values */ | 248 | /* Vendor-ID values */ |
248 | #define SSB_VENDOR_BROADCOM 0x4243 | 249 | #define SSB_VENDOR_BROADCOM 0x4243 |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0289d4ce7070..7319f25250b6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -404,6 +404,8 @@ struct cfg80211_beacon_data { | |||
404 | * | 404 | * |
405 | * Used to configure an AP interface. | 405 | * Used to configure an AP interface. |
406 | * | 406 | * |
407 | * @channel: the channel to start the AP on | ||
408 | * @channel_type: the channel type to use | ||
407 | * @beacon: beacon data | 409 | * @beacon: beacon data |
408 | * @beacon_interval: beacon interval | 410 | * @beacon_interval: beacon interval |
409 | * @dtim_period: DTIM period | 411 | * @dtim_period: DTIM period |
@@ -417,6 +419,9 @@ struct cfg80211_beacon_data { | |||
417 | * @inactivity_timeout: time in seconds to determine station's inactivity. | 419 | * @inactivity_timeout: time in seconds to determine station's inactivity. |
418 | */ | 420 | */ |
419 | struct cfg80211_ap_settings { | 421 | struct cfg80211_ap_settings { |
422 | struct ieee80211_channel *channel; | ||
423 | enum nl80211_channel_type channel_type; | ||
424 | |||
420 | struct cfg80211_beacon_data beacon; | 425 | struct cfg80211_beacon_data beacon; |
421 | 426 | ||
422 | int beacon_interval, dtim_period; | 427 | int beacon_interval, dtim_period; |
@@ -826,6 +831,8 @@ struct mesh_config { | |||
826 | 831 | ||
827 | /** | 832 | /** |
828 | * struct mesh_setup - 802.11s mesh setup configuration | 833 | * struct mesh_setup - 802.11s mesh setup configuration |
834 | * @channel: the channel to start the mesh network on | ||
835 | * @channel_type: the channel type to use | ||
829 | * @mesh_id: the mesh ID | 836 | * @mesh_id: the mesh ID |
830 | * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes | 837 | * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes |
831 | * @sync_method: which synchronization method to use | 838 | * @sync_method: which synchronization method to use |
@@ -840,6 +847,8 @@ struct mesh_config { | |||
840 | * These parameters are fixed when the mesh is created. | 847 | * These parameters are fixed when the mesh is created. |
841 | */ | 848 | */ |
842 | struct mesh_setup { | 849 | struct mesh_setup { |
850 | struct ieee80211_channel *channel; | ||
851 | enum nl80211_channel_type channel_type; | ||
843 | const u8 *mesh_id; | 852 | const u8 *mesh_id; |
844 | u8 mesh_id_len; | 853 | u8 mesh_id_len; |
845 | u8 sync_method; | 854 | u8 sync_method; |
@@ -1411,11 +1420,14 @@ struct cfg80211_gtk_rekey_data { | |||
1411 | * | 1420 | * |
1412 | * @set_txq_params: Set TX queue parameters | 1421 | * @set_txq_params: Set TX queue parameters |
1413 | * | 1422 | * |
1414 | * @set_channel: Set channel for a given wireless interface. Some devices | 1423 | * @libertas_set_mesh_channel: Only for backward compatibility for libertas, |
1415 | * may support multi-channel operation (by channel hopping) so cfg80211 | 1424 | * as it doesn't implement join_mesh and needs to set the channel to |
1416 | * doesn't verify much. Note, however, that the passed netdev may be | 1425 | * join the mesh instead. |
1417 | * %NULL as well if the user requested changing the channel for the | 1426 | * |
1418 | * device itself, or for a monitor interface. | 1427 | * @set_monitor_channel: Set the monitor mode channel for the device. If other |
1428 | * interfaces are active this callback should reject the configuration. | ||
1429 | * If no interfaces are active or the device is down, the channel should | ||
1430 | * be stored for when a monitor interface becomes active. | ||
1419 | * @get_channel: Get the current operating channel, should return %NULL if | 1431 | * @get_channel: Get the current operating channel, should return %NULL if |
1420 | * there's no single defined operating channel if for example the | 1432 | * there's no single defined operating channel if for example the |
1421 | * device implements channel hopping for multi-channel virtual interfaces. | 1433 | * device implements channel hopping for multi-channel virtual interfaces. |
@@ -1605,9 +1617,13 @@ struct cfg80211_ops { | |||
1605 | int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, | 1617 | int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, |
1606 | struct ieee80211_txq_params *params); | 1618 | struct ieee80211_txq_params *params); |
1607 | 1619 | ||
1608 | int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, | 1620 | int (*libertas_set_mesh_channel)(struct wiphy *wiphy, |
1609 | struct ieee80211_channel *chan, | 1621 | struct net_device *dev, |
1610 | enum nl80211_channel_type channel_type); | 1622 | struct ieee80211_channel *chan); |
1623 | |||
1624 | int (*set_monitor_channel)(struct wiphy *wiphy, | ||
1625 | struct ieee80211_channel *chan, | ||
1626 | enum nl80211_channel_type channel_type); | ||
1611 | 1627 | ||
1612 | int (*scan)(struct wiphy *wiphy, struct net_device *dev, | 1628 | int (*scan)(struct wiphy *wiphy, struct net_device *dev, |
1613 | struct cfg80211_scan_request *request); | 1629 | struct cfg80211_scan_request *request); |
@@ -2263,7 +2279,10 @@ struct cfg80211_cached_keys; | |||
2263 | * @netdev: (private) Used to reference back to the netdev | 2279 | * @netdev: (private) Used to reference back to the netdev |
2264 | * @current_bss: (private) Used by the internal configuration code | 2280 | * @current_bss: (private) Used by the internal configuration code |
2265 | * @channel: (private) Used by the internal configuration code to track | 2281 | * @channel: (private) Used by the internal configuration code to track |
2266 | * user-set AP, monitor and WDS channels for wireless extensions | 2282 | * the user-set AP, monitor and WDS channel |
2283 | * @preset_chan: (private) Used by the internal configuration code to | ||
2284 | * track the channel to be used for AP later | ||
2285 | * @preset_chantype: (private) the corresponding channel type | ||
2267 | * @bssid: (private) Used by the internal configuration code | 2286 | * @bssid: (private) Used by the internal configuration code |
2268 | * @ssid: (private) Used by the internal configuration code | 2287 | * @ssid: (private) Used by the internal configuration code |
2269 | * @ssid_len: (private) Used by the internal configuration code | 2288 | * @ssid_len: (private) Used by the internal configuration code |
@@ -2313,7 +2332,8 @@ struct wireless_dev { | |||
2313 | spinlock_t event_lock; | 2332 | spinlock_t event_lock; |
2314 | 2333 | ||
2315 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ | 2334 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ |
2316 | struct ieee80211_channel *channel; | 2335 | struct ieee80211_channel *preset_chan; |
2336 | enum nl80211_channel_type preset_chantype; | ||
2317 | 2337 | ||
2318 | bool ps; | 2338 | bool ps; |
2319 | int ps_timeout; | 2339 | int ps_timeout; |
@@ -3359,11 +3379,14 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, | |||
3359 | const u8 *frame, size_t len, | 3379 | const u8 *frame, size_t len, |
3360 | int freq, int sig_dbm, gfp_t gfp); | 3380 | int freq, int sig_dbm, gfp_t gfp); |
3361 | 3381 | ||
3362 | /* | 3382 | /** |
3363 | * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used | 3383 | * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used |
3364 | * @wiphy: the wiphy | 3384 | * @wiphy: the wiphy |
3365 | * @chan: main channel | 3385 | * @chan: main channel |
3366 | * @channel_type: HT mode | 3386 | * @channel_type: HT mode |
3387 | * | ||
3388 | * This function returns true if there is no secondary channel or the secondary | ||
3389 | * channel can be used for beaconing (i.e. is not a radar channel etc.) | ||
3367 | */ | 3390 | */ |
3368 | bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | 3391 | bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, |
3369 | struct ieee80211_channel *chan, | 3392 | struct ieee80211_channel *chan, |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1937c7d98304..d152f54064fd 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1297,6 +1297,10 @@ enum ieee80211_hw_flags { | |||
1297 | * reports, by default it is set to _MCS, _GI and _BW but doesn't | 1297 | * reports, by default it is set to _MCS, _GI and _BW but doesn't |
1298 | * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only | 1298 | * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only |
1299 | * adding _BW is supported today. | 1299 | * adding _BW is supported today. |
1300 | * | ||
1301 | * @netdev_features: netdev features to be set in each netdev created | ||
1302 | * from this HW. Note only HW checksum features are currently | ||
1303 | * compatible with mac80211. Other feature bits will be rejected. | ||
1300 | */ | 1304 | */ |
1301 | struct ieee80211_hw { | 1305 | struct ieee80211_hw { |
1302 | struct ieee80211_conf conf; | 1306 | struct ieee80211_conf conf; |
@@ -1319,6 +1323,7 @@ struct ieee80211_hw { | |||
1319 | u8 max_tx_aggregation_subframes; | 1323 | u8 max_tx_aggregation_subframes; |
1320 | u8 offchannel_tx_hw_queue; | 1324 | u8 offchannel_tx_hw_queue; |
1321 | u8 radiotap_mcs_details; | 1325 | u8 radiotap_mcs_details; |
1326 | netdev_features_t netdev_features; | ||
1322 | }; | 1327 | }; |
1323 | 1328 | ||
1324 | /** | 1329 | /** |
@@ -2178,7 +2183,10 @@ enum ieee80211_rate_control_changed { | |||
2178 | * offload. Frames to transmit on the off-channel channel are transmitted | 2183 | * offload. Frames to transmit on the off-channel channel are transmitted |
2179 | * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the | 2184 | * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the |
2180 | * duration (which will always be non-zero) expires, the driver must call | 2185 | * duration (which will always be non-zero) expires, the driver must call |
2181 | * ieee80211_remain_on_channel_expired(). This callback may sleep. | 2186 | * ieee80211_remain_on_channel_expired(). |
2187 | * Note that this callback may be called while the device is in IDLE and | ||
2188 | * must be accepted in this case. | ||
2189 | * This callback may sleep. | ||
2182 | * @cancel_remain_on_channel: Requests that an ongoing off-channel period is | 2190 | * @cancel_remain_on_channel: Requests that an ongoing off-channel period is |
2183 | * aborted before it expires. This callback may sleep. | 2191 | * aborted before it expires. This callback may sleep. |
2184 | * | 2192 | * |
@@ -3551,16 +3559,6 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
3551 | gfp_t gfp); | 3559 | gfp_t gfp); |
3552 | 3560 | ||
3553 | /** | 3561 | /** |
3554 | * ieee80211_get_operstate - get the operstate of the vif | ||
3555 | * | ||
3556 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
3557 | * | ||
3558 | * The driver might need to know the operstate of the net_device | ||
3559 | * (specifically, whether the link is IF_OPER_UP after resume) | ||
3560 | */ | ||
3561 | unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif); | ||
3562 | |||
3563 | /** | ||
3564 | * ieee80211_chswitch_done - Complete channel switch process | 3562 | * ieee80211_chswitch_done - Complete channel switch process |
3565 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3563 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
3566 | * @success: make the channel switch successful or not | 3564 | * @success: make the channel switch successful or not |
@@ -3839,4 +3837,28 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, | |||
3839 | */ | 3837 | */ |
3840 | int ieee80211_ave_rssi(struct ieee80211_vif *vif); | 3838 | int ieee80211_ave_rssi(struct ieee80211_vif *vif); |
3841 | 3839 | ||
3840 | /* Extra debugging macros */ | ||
3841 | |||
3842 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
3843 | #define ht_vdbg(fmt, ...) \ | ||
3844 | pr_debug(fmt, ##__VA_ARGS__) | ||
3845 | #else | ||
3846 | #define ht_vdbg(fmt, ...) \ | ||
3847 | do { \ | ||
3848 | if (0) \ | ||
3849 | pr_debug(fmt, ##__VA_ARGS__); \ | ||
3850 | } while (0) | ||
3851 | #endif | ||
3852 | |||
3853 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
3854 | #define ibss_vdbg(fmt, ...) \ | ||
3855 | pr_debug(fmt, ##__VA_ARGS__) | ||
3856 | #else | ||
3857 | #define ibss_vdbg(fmt, ...) \ | ||
3858 | do { \ | ||
3859 | if (0) \ | ||
3860 | pr_debug(fmt, ##__VA_ARGS__); \ | ||
3861 | } while (0) | ||
3862 | #endif | ||
3863 | |||
3842 | #endif /* MAC80211_H */ | 3864 | #endif /* MAC80211_H */ |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 4467c9460857..e30e6a869714 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -31,7 +31,8 @@ struct nfc_hci_ops { | |||
31 | void (*close) (struct nfc_hci_dev *hdev); | 31 | void (*close) (struct nfc_hci_dev *hdev); |
32 | int (*hci_ready) (struct nfc_hci_dev *hdev); | 32 | int (*hci_ready) (struct nfc_hci_dev *hdev); |
33 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); | 33 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
34 | int (*start_poll) (struct nfc_hci_dev *hdev, u32 protocols); | 34 | int (*start_poll) (struct nfc_hci_dev *hdev, |
35 | u32 im_protocols, u32 tm_protocols); | ||
35 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, | 36 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, |
36 | struct nfc_target *target); | 37 | struct nfc_target *target); |
37 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, | 38 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index b7ca4a2a1d72..180964b954ab 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -53,7 +53,8 @@ struct nfc_target; | |||
53 | struct nfc_ops { | 53 | struct nfc_ops { |
54 | int (*dev_up)(struct nfc_dev *dev); | 54 | int (*dev_up)(struct nfc_dev *dev); |
55 | int (*dev_down)(struct nfc_dev *dev); | 55 | int (*dev_down)(struct nfc_dev *dev); |
56 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); | 56 | int (*start_poll)(struct nfc_dev *dev, |
57 | u32 im_protocols, u32 tm_protocols); | ||
57 | void (*stop_poll)(struct nfc_dev *dev); | 58 | void (*stop_poll)(struct nfc_dev *dev); |
58 | int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, | 59 | int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, |
59 | u8 comm_mode, u8 *gb, size_t gb_len); | 60 | u8 comm_mode, u8 *gb, size_t gb_len); |
@@ -62,9 +63,10 @@ struct nfc_ops { | |||
62 | u32 protocol); | 63 | u32 protocol); |
63 | void (*deactivate_target)(struct nfc_dev *dev, | 64 | void (*deactivate_target)(struct nfc_dev *dev, |
64 | struct nfc_target *target); | 65 | struct nfc_target *target); |
65 | int (*data_exchange)(struct nfc_dev *dev, struct nfc_target *target, | 66 | int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target, |
66 | struct sk_buff *skb, data_exchange_cb_t cb, | 67 | struct sk_buff *skb, data_exchange_cb_t cb, |
67 | void *cb_context); | 68 | void *cb_context); |
69 | int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); | ||
68 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); | 70 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); |
69 | }; | 71 | }; |
70 | 72 | ||
@@ -99,10 +101,10 @@ struct nfc_dev { | |||
99 | int targets_generation; | 101 | int targets_generation; |
100 | struct device dev; | 102 | struct device dev; |
101 | bool dev_up; | 103 | bool dev_up; |
104 | u8 rf_mode; | ||
102 | bool polling; | 105 | bool polling; |
103 | struct nfc_target *active_target; | 106 | struct nfc_target *active_target; |
104 | bool dep_link_up; | 107 | bool dep_link_up; |
105 | u32 dep_rf_mode; | ||
106 | struct nfc_genl_data genl_data; | 108 | struct nfc_genl_data genl_data; |
107 | u32 supported_protocols; | 109 | u32 supported_protocols; |
108 | 110 | ||
@@ -188,6 +190,7 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); | |||
188 | 190 | ||
189 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, | 191 | int nfc_set_remote_general_bytes(struct nfc_dev *dev, |
190 | u8 *gt, u8 gt_len); | 192 | u8 *gt, u8 gt_len); |
193 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len); | ||
191 | 194 | ||
192 | int nfc_targets_found(struct nfc_dev *dev, | 195 | int nfc_targets_found(struct nfc_dev *dev, |
193 | struct nfc_target *targets, int ntargets); | 196 | struct nfc_target *targets, int ntargets); |
@@ -196,4 +199,9 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx); | |||
196 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | 199 | int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, |
197 | u8 comm_mode, u8 rf_mode); | 200 | u8 comm_mode, u8 rf_mode); |
198 | 201 | ||
202 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
203 | u8 *gb, size_t gb_len); | ||
204 | int nfc_tm_deactivated(struct nfc_dev *dev); | ||
205 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); | ||
206 | |||
199 | #endif /* __NET_NFC_H */ | 207 | #endif /* __NET_NFC_H */ |
diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h index ab06afd462da..35e930d2f638 100644 --- a/include/net/nfc/shdlc.h +++ b/include/net/nfc/shdlc.h | |||
@@ -27,7 +27,8 @@ struct nfc_shdlc_ops { | |||
27 | void (*close) (struct nfc_shdlc *shdlc); | 27 | void (*close) (struct nfc_shdlc *shdlc); |
28 | int (*hci_ready) (struct nfc_shdlc *shdlc); | 28 | int (*hci_ready) (struct nfc_shdlc *shdlc); |
29 | int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); | 29 | int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); |
30 | int (*start_poll) (struct nfc_shdlc *shdlc, u32 protocols); | 30 | int (*start_poll) (struct nfc_shdlc *shdlc, |
31 | u32 im_protocols, u32 tm_protocols); | ||
31 | int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, | 32 | int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, |
32 | struct nfc_target *target); | 33 | struct nfc_target *target); |
33 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, | 34 | int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index fdf9e61d0651..72607174ea5a 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -417,72 +417,6 @@ static struct attribute_group netstat_group = { | |||
417 | .name = "statistics", | 417 | .name = "statistics", |
418 | .attrs = netstat_attrs, | 418 | .attrs = netstat_attrs, |
419 | }; | 419 | }; |
420 | |||
421 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | ||
422 | /* helper function that does all the locking etc for wireless stats */ | ||
423 | static ssize_t wireless_show(struct device *d, char *buf, | ||
424 | ssize_t (*format)(const struct iw_statistics *, | ||
425 | char *)) | ||
426 | { | ||
427 | struct net_device *dev = to_net_dev(d); | ||
428 | const struct iw_statistics *iw; | ||
429 | ssize_t ret = -EINVAL; | ||
430 | |||
431 | if (!rtnl_trylock()) | ||
432 | return restart_syscall(); | ||
433 | if (dev_isalive(dev)) { | ||
434 | iw = get_wireless_stats(dev); | ||
435 | if (iw) | ||
436 | ret = (*format)(iw, buf); | ||
437 | } | ||
438 | rtnl_unlock(); | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | /* show function template for wireless fields */ | ||
444 | #define WIRELESS_SHOW(name, field, format_string) \ | ||
445 | static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \ | ||
446 | { \ | ||
447 | return sprintf(buf, format_string, iw->field); \ | ||
448 | } \ | ||
449 | static ssize_t show_iw_##name(struct device *d, \ | ||
450 | struct device_attribute *attr, char *buf) \ | ||
451 | { \ | ||
452 | return wireless_show(d, buf, format_iw_##name); \ | ||
453 | } \ | ||
454 | static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) | ||
455 | |||
456 | WIRELESS_SHOW(status, status, fmt_hex); | ||
457 | WIRELESS_SHOW(link, qual.qual, fmt_dec); | ||
458 | WIRELESS_SHOW(level, qual.level, fmt_dec); | ||
459 | WIRELESS_SHOW(noise, qual.noise, fmt_dec); | ||
460 | WIRELESS_SHOW(nwid, discard.nwid, fmt_dec); | ||
461 | WIRELESS_SHOW(crypt, discard.code, fmt_dec); | ||
462 | WIRELESS_SHOW(fragment, discard.fragment, fmt_dec); | ||
463 | WIRELESS_SHOW(misc, discard.misc, fmt_dec); | ||
464 | WIRELESS_SHOW(retries, discard.retries, fmt_dec); | ||
465 | WIRELESS_SHOW(beacon, miss.beacon, fmt_dec); | ||
466 | |||
467 | static struct attribute *wireless_attrs[] = { | ||
468 | &dev_attr_status.attr, | ||
469 | &dev_attr_link.attr, | ||
470 | &dev_attr_level.attr, | ||
471 | &dev_attr_noise.attr, | ||
472 | &dev_attr_nwid.attr, | ||
473 | &dev_attr_crypt.attr, | ||
474 | &dev_attr_fragment.attr, | ||
475 | &dev_attr_retries.attr, | ||
476 | &dev_attr_misc.attr, | ||
477 | &dev_attr_beacon.attr, | ||
478 | NULL | ||
479 | }; | ||
480 | |||
481 | static struct attribute_group wireless_group = { | ||
482 | .name = "wireless", | ||
483 | .attrs = wireless_attrs, | ||
484 | }; | ||
485 | #endif | ||
486 | #endif /* CONFIG_SYSFS */ | 420 | #endif /* CONFIG_SYSFS */ |
487 | 421 | ||
488 | #ifdef CONFIG_RPS | 422 | #ifdef CONFIG_RPS |
@@ -1463,14 +1397,6 @@ int netdev_register_kobject(struct net_device *net) | |||
1463 | groups++; | 1397 | groups++; |
1464 | 1398 | ||
1465 | *groups++ = &netstat_group; | 1399 | *groups++ = &netstat_group; |
1466 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | ||
1467 | if (net->ieee80211_ptr) | ||
1468 | *groups++ = &wireless_group; | ||
1469 | #ifdef CONFIG_WIRELESS_EXT | ||
1470 | else if (net->wireless_handlers) | ||
1471 | *groups++ = &wireless_group; | ||
1472 | #endif | ||
1473 | #endif | ||
1474 | #endif /* CONFIG_SYSFS */ | 1400 | #endif /* CONFIG_SYSFS */ |
1475 | 1401 | ||
1476 | error = device_add(dev); | 1402 | error = device_add(dev); |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 3e9d931bba35..2b1470bac178 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -9,7 +9,6 @@ mac80211-y := \ | |||
9 | scan.o offchannel.o \ | 9 | scan.o offchannel.o \ |
10 | ht.o agg-tx.o agg-rx.o \ | 10 | ht.o agg-tx.o agg-rx.o \ |
11 | ibss.o \ | 11 | ibss.o \ |
12 | work.o \ | ||
13 | iface.o \ | 12 | iface.o \ |
14 | rate.o \ | 13 | rate.o \ |
15 | michael.o \ | 14 | michael.o \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index c649188314cc..32ef11d69798 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -74,18 +74,15 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
74 | 74 | ||
75 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); | 75 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); |
76 | 76 | ||
77 | #ifdef CONFIG_MAC80211_HT_DEBUG | 77 | ht_vdbg("Rx BA session stop requested for %pM tid %u %s reason: %d\n", |
78 | printk(KERN_DEBUG | 78 | sta->sta.addr, tid, |
79 | "Rx BA session stop requested for %pM tid %u %s reason: %d\n", | 79 | initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", |
80 | sta->sta.addr, tid, | 80 | (int)reason); |
81 | initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", | ||
82 | (int)reason); | ||
83 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
84 | 81 | ||
85 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 82 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
86 | &sta->sta, tid, NULL, 0)) | 83 | &sta->sta, tid, NULL, 0)) |
87 | printk(KERN_DEBUG "HW problem - can not stop rx " | 84 | pr_debug("HW problem - can not stop rx aggregation for tid %d\n", |
88 | "aggregation for tid %d\n", tid); | 85 | tid); |
89 | 86 | ||
90 | /* check if this is a self generated aggregation halt */ | 87 | /* check if this is a self generated aggregation halt */ |
91 | if (initiator == WLAN_BACK_RECIPIENT && tx) | 88 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
@@ -160,9 +157,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
160 | } | 157 | } |
161 | rcu_read_unlock(); | 158 | rcu_read_unlock(); |
162 | 159 | ||
163 | #ifdef CONFIG_MAC80211_HT_DEBUG | 160 | ht_vdbg("rx session timer expired on tid %d\n", (u16)*ptid); |
164 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 161 | |
165 | #endif | ||
166 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); | 162 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); |
167 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 163 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
168 | } | 164 | } |
@@ -249,10 +245,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
249 | status = WLAN_STATUS_REQUEST_DECLINED; | 245 | status = WLAN_STATUS_REQUEST_DECLINED; |
250 | 246 | ||
251 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 247 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
252 | #ifdef CONFIG_MAC80211_HT_DEBUG | 248 | ht_vdbg("Suspend in progress - Denying ADDBA request\n"); |
253 | printk(KERN_DEBUG "Suspend in progress. " | ||
254 | "Denying ADDBA request\n"); | ||
255 | #endif | ||
256 | goto end_no_lock; | 249 | goto end_no_lock; |
257 | } | 250 | } |
258 | 251 | ||
@@ -324,10 +317,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
324 | 317 | ||
325 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 318 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
326 | &sta->sta, tid, &start_seq_num, 0); | 319 | &sta->sta, tid, &start_seq_num, 0); |
327 | #ifdef CONFIG_MAC80211_HT_DEBUG | 320 | ht_vdbg("Rx A-MPDU request on tid %d result %d\n", tid, ret); |
328 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
329 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
330 | |||
331 | if (ret) { | 321 | if (ret) { |
332 | kfree(tid_agg_rx->reorder_buf); | 322 | kfree(tid_agg_rx->reorder_buf); |
333 | kfree(tid_agg_rx->reorder_time); | 323 | kfree(tid_agg_rx->reorder_time); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 7cf07158805c..da07f01cfe4d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -184,10 +184,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
184 | 184 | ||
185 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
186 | 186 | ||
187 | #ifdef CONFIG_MAC80211_HT_DEBUG | 187 | ht_vdbg("Tx BA session stop requested for %pM tid %u\n", |
188 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", | 188 | sta->sta.addr, tid); |
189 | sta->sta.addr, tid); | ||
190 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
191 | 189 | ||
192 | del_timer_sync(&tid_tx->addba_resp_timer); | 190 | del_timer_sync(&tid_tx->addba_resp_timer); |
193 | del_timer_sync(&tid_tx->session_timer); | 191 | del_timer_sync(&tid_tx->session_timer); |
@@ -253,17 +251,12 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
253 | if (!tid_tx || | 251 | if (!tid_tx || |
254 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { | 252 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { |
255 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
256 | #ifdef CONFIG_MAC80211_HT_DEBUG | 254 | ht_vdbg("timer expired on tid %d but we are not (or no longer) expecting addBA response there\n", |
257 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
258 | "(or no longer) expecting addBA response there\n", | ||
259 | tid); | 255 | tid); |
260 | #endif | ||
261 | return; | 256 | return; |
262 | } | 257 | } |
263 | 258 | ||
264 | #ifdef CONFIG_MAC80211_HT_DEBUG | 259 | ht_vdbg("addBA response timer expired on tid %d\n", tid); |
265 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
266 | #endif | ||
267 | 260 | ||
268 | ieee80211_stop_tx_ba_session(&sta->sta, tid); | 261 | ieee80211_stop_tx_ba_session(&sta->sta, tid); |
269 | rcu_read_unlock(); | 262 | rcu_read_unlock(); |
@@ -372,10 +365,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
372 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 365 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
373 | &sta->sta, tid, &start_seq_num, 0); | 366 | &sta->sta, tid, &start_seq_num, 0); |
374 | if (ret) { | 367 | if (ret) { |
375 | #ifdef CONFIG_MAC80211_HT_DEBUG | 368 | ht_vdbg("BA request denied - HW unavailable for tid %d\n", tid); |
376 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
377 | " tid %d\n", tid); | ||
378 | #endif | ||
379 | spin_lock_bh(&sta->lock); | 369 | spin_lock_bh(&sta->lock); |
380 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); | 370 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
381 | ieee80211_assign_tid_tx(sta, tid, NULL); | 371 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -388,9 +378,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
388 | 378 | ||
389 | /* activate the timer for the recipient's addBA response */ | 379 | /* activate the timer for the recipient's addBA response */ |
390 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 380 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
391 | #ifdef CONFIG_MAC80211_HT_DEBUG | 381 | ht_vdbg("activated addBA response timer on tid %d\n", tid); |
392 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
393 | #endif | ||
394 | 382 | ||
395 | spin_lock_bh(&sta->lock); | 383 | spin_lock_bh(&sta->lock); |
396 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; | 384 | sta->ampdu_mlme.last_addba_req_time[tid] = jiffies; |
@@ -437,9 +425,7 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
437 | 425 | ||
438 | rcu_read_unlock(); | 426 | rcu_read_unlock(); |
439 | 427 | ||
440 | #ifdef CONFIG_MAC80211_HT_DEBUG | 428 | ht_vdbg("tx session timer expired on tid %d\n", (u16)*ptid); |
441 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | ||
442 | #endif | ||
443 | 429 | ||
444 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); | 430 | ieee80211_stop_tx_ba_session(&sta->sta, *ptid); |
445 | } | 431 | } |
@@ -463,10 +449,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
463 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) | 449 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) |
464 | return -EINVAL; | 450 | return -EINVAL; |
465 | 451 | ||
466 | #ifdef CONFIG_MAC80211_HT_DEBUG | 452 | ht_vdbg("Open BA session requested for %pM tid %u\n", |
467 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", | 453 | pubsta->addr, tid); |
468 | pubsta->addr, tid); | ||
469 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
470 | 454 | ||
471 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 455 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
472 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 456 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
@@ -476,10 +460,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
476 | return -EINVAL; | 460 | return -EINVAL; |
477 | 461 | ||
478 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 462 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
479 | #ifdef CONFIG_MAC80211_HT_DEBUG | 463 | ht_vdbg("BA sessions blocked - Denying BA session request\n"); |
480 | printk(KERN_DEBUG "BA sessions blocked. " | ||
481 | "Denying BA session request\n"); | ||
482 | #endif | ||
483 | return -EINVAL; | 464 | return -EINVAL; |
484 | } | 465 | } |
485 | 466 | ||
@@ -497,10 +478,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
497 | */ | 478 | */ |
498 | if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && | 479 | if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && |
499 | !sta->sta.ht_cap.ht_supported) { | 480 | !sta->sta.ht_cap.ht_supported) { |
500 | #ifdef CONFIG_MAC80211_HT_DEBUG | 481 | ht_vdbg("BA request denied - IBSS STA %pM does not advertise HT support\n", |
501 | printk(KERN_DEBUG "BA request denied - IBSS STA %pM" | 482 | pubsta->addr); |
502 | "does not advertise HT support\n", pubsta->addr); | ||
503 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
504 | return -EINVAL; | 483 | return -EINVAL; |
505 | } | 484 | } |
506 | 485 | ||
@@ -520,12 +499,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
520 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES && | 499 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES && |
521 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + | 500 | time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] + |
522 | HT_AGG_RETRIES_PERIOD)) { | 501 | HT_AGG_RETRIES_PERIOD)) { |
523 | #ifdef CONFIG_MAC80211_HT_DEBUG | 502 | ht_vdbg("BA request denied - waiting a grace period after %d failed requests on tid %u\n", |
524 | printk(KERN_DEBUG "BA request denied - " | 503 | sta->ampdu_mlme.addba_req_num[tid], tid); |
525 | "waiting a grace period after %d failed requests " | ||
526 | "on tid %u\n", | ||
527 | sta->ampdu_mlme.addba_req_num[tid], tid); | ||
528 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
529 | ret = -EBUSY; | 504 | ret = -EBUSY; |
530 | goto err_unlock_sta; | 505 | goto err_unlock_sta; |
531 | } | 506 | } |
@@ -533,10 +508,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
533 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 508 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
534 | /* check if the TID is not in aggregation flow already */ | 509 | /* check if the TID is not in aggregation flow already */ |
535 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { | 510 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
536 | #ifdef CONFIG_MAC80211_HT_DEBUG | 511 | ht_vdbg("BA request denied - session is not idle on tid %u\n", |
537 | printk(KERN_DEBUG "BA request denied - session is not " | 512 | tid); |
538 | "idle on tid %u\n", tid); | ||
539 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
540 | ret = -EAGAIN; | 513 | ret = -EAGAIN; |
541 | goto err_unlock_sta; | 514 | goto err_unlock_sta; |
542 | } | 515 | } |
@@ -591,9 +564,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
591 | 564 | ||
592 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 565 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
593 | 566 | ||
594 | #ifdef CONFIG_MAC80211_HT_DEBUG | 567 | ht_vdbg("Aggregation is on for tid %d\n", tid); |
595 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); | ||
596 | #endif | ||
597 | 568 | ||
598 | drv_ampdu_action(local, sta->sdata, | 569 | drv_ampdu_action(local, sta->sdata, |
599 | IEEE80211_AMPDU_TX_OPERATIONAL, | 570 | IEEE80211_AMPDU_TX_OPERATIONAL, |
@@ -627,10 +598,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
627 | trace_api_start_tx_ba_cb(sdata, ra, tid); | 598 | trace_api_start_tx_ba_cb(sdata, ra, tid); |
628 | 599 | ||
629 | if (tid >= STA_TID_NUM) { | 600 | if (tid >= STA_TID_NUM) { |
630 | #ifdef CONFIG_MAC80211_HT_DEBUG | 601 | ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); |
631 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
632 | tid, STA_TID_NUM); | ||
633 | #endif | ||
634 | return; | 602 | return; |
635 | } | 603 | } |
636 | 604 | ||
@@ -638,9 +606,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
638 | sta = sta_info_get_bss(sdata, ra); | 606 | sta = sta_info_get_bss(sdata, ra); |
639 | if (!sta) { | 607 | if (!sta) { |
640 | mutex_unlock(&local->sta_mtx); | 608 | mutex_unlock(&local->sta_mtx); |
641 | #ifdef CONFIG_MAC80211_HT_DEBUG | 609 | ht_vdbg("Could not find station: %pM\n", ra); |
642 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
643 | #endif | ||
644 | return; | 610 | return; |
645 | } | 611 | } |
646 | 612 | ||
@@ -648,9 +614,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
648 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 614 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
649 | 615 | ||
650 | if (WARN_ON(!tid_tx)) { | 616 | if (WARN_ON(!tid_tx)) { |
651 | #ifdef CONFIG_MAC80211_HT_DEBUG | 617 | ht_vdbg("addBA was not requested!\n"); |
652 | printk(KERN_DEBUG "addBA was not requested!\n"); | ||
653 | #endif | ||
654 | goto unlock; | 618 | goto unlock; |
655 | } | 619 | } |
656 | 620 | ||
@@ -750,25 +714,17 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
750 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | 714 | trace_api_stop_tx_ba_cb(sdata, ra, tid); |
751 | 715 | ||
752 | if (tid >= STA_TID_NUM) { | 716 | if (tid >= STA_TID_NUM) { |
753 | #ifdef CONFIG_MAC80211_HT_DEBUG | 717 | ht_vdbg("Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); |
754 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
755 | tid, STA_TID_NUM); | ||
756 | #endif | ||
757 | return; | 718 | return; |
758 | } | 719 | } |
759 | 720 | ||
760 | #ifdef CONFIG_MAC80211_HT_DEBUG | 721 | ht_vdbg("Stopping Tx BA session for %pM tid %d\n", ra, tid); |
761 | printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", | ||
762 | ra, tid); | ||
763 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
764 | 722 | ||
765 | mutex_lock(&local->sta_mtx); | 723 | mutex_lock(&local->sta_mtx); |
766 | 724 | ||
767 | sta = sta_info_get_bss(sdata, ra); | 725 | sta = sta_info_get_bss(sdata, ra); |
768 | if (!sta) { | 726 | if (!sta) { |
769 | #ifdef CONFIG_MAC80211_HT_DEBUG | 727 | ht_vdbg("Could not find station: %pM\n", ra); |
770 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | ||
771 | #endif | ||
772 | goto unlock; | 728 | goto unlock; |
773 | } | 729 | } |
774 | 730 | ||
@@ -777,9 +733,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
777 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 733 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
778 | 734 | ||
779 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 735 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
780 | #ifdef CONFIG_MAC80211_HT_DEBUG | 736 | ht_vdbg("unexpected callback to A-MPDU stop\n"); |
781 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
782 | #endif | ||
783 | goto unlock_sta; | 737 | goto unlock_sta; |
784 | } | 738 | } |
785 | 739 | ||
@@ -855,17 +809,13 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
855 | goto out; | 809 | goto out; |
856 | 810 | ||
857 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { | 811 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { |
858 | #ifdef CONFIG_MAC80211_HT_DEBUG | 812 | ht_vdbg("wrong addBA response token, tid %d\n", tid); |
859 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
860 | #endif | ||
861 | goto out; | 813 | goto out; |
862 | } | 814 | } |
863 | 815 | ||
864 | del_timer_sync(&tid_tx->addba_resp_timer); | 816 | del_timer_sync(&tid_tx->addba_resp_timer); |
865 | 817 | ||
866 | #ifdef CONFIG_MAC80211_HT_DEBUG | 818 | ht_vdbg("switched off addBA timer for tid %d\n", tid); |
867 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | ||
868 | #endif | ||
869 | 819 | ||
870 | /* | 820 | /* |
871 | * addba_resp_timer may have fired before we got here, and | 821 | * addba_resp_timer may have fired before we got here, and |
@@ -874,11 +824,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
874 | */ | 824 | */ |
875 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | 825 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || |
876 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 826 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
877 | #ifdef CONFIG_MAC80211_HT_DEBUG | 827 | ht_vdbg("got addBA resp for tid %d but we already gave up\n", |
878 | printk(KERN_DEBUG | 828 | tid); |
879 | "got addBA resp for tid %d but we already gave up\n", | ||
880 | tid); | ||
881 | #endif | ||
882 | goto out; | 829 | goto out; |
883 | } | 830 | } |
884 | 831 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e9cecca5c44d..498c94e34427 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -674,6 +674,48 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
674 | return ret; | 674 | return ret; |
675 | } | 675 | } |
676 | 676 | ||
677 | static int ieee80211_set_channel(struct wiphy *wiphy, | ||
678 | struct net_device *netdev, | ||
679 | struct ieee80211_channel *chan, | ||
680 | enum nl80211_channel_type channel_type) | ||
681 | { | ||
682 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
683 | struct ieee80211_sub_if_data *sdata = NULL; | ||
684 | |||
685 | if (netdev) | ||
686 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
687 | |||
688 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
689 | case CHAN_MODE_HOPPING: | ||
690 | return -EBUSY; | ||
691 | case CHAN_MODE_FIXED: | ||
692 | if (local->oper_channel != chan) | ||
693 | return -EBUSY; | ||
694 | if (!sdata && local->_oper_channel_type == channel_type) | ||
695 | return 0; | ||
696 | break; | ||
697 | case CHAN_MODE_UNDEFINED: | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | ||
702 | return -EBUSY; | ||
703 | |||
704 | local->oper_channel = chan; | ||
705 | |||
706 | /* auto-detects changes */ | ||
707 | ieee80211_hw_config(local, 0); | ||
708 | |||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | ||
713 | struct ieee80211_channel *chan, | ||
714 | enum nl80211_channel_type channel_type) | ||
715 | { | ||
716 | return ieee80211_set_channel(wiphy, NULL, chan, channel_type); | ||
717 | } | ||
718 | |||
677 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 719 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
678 | const u8 *resp, size_t resp_len) | 720 | const u8 *resp, size_t resp_len) |
679 | { | 721 | { |
@@ -788,6 +830,11 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
788 | if (old) | 830 | if (old) |
789 | return -EALREADY; | 831 | return -EALREADY; |
790 | 832 | ||
833 | err = ieee80211_set_channel(wiphy, dev, params->channel, | ||
834 | params->channel_type); | ||
835 | if (err) | ||
836 | return err; | ||
837 | |||
791 | /* | 838 | /* |
792 | * Apply control port protocol, this allows us to | 839 | * Apply control port protocol, this allows us to |
793 | * not encrypt dynamic WEP control frames. | 840 | * not encrypt dynamic WEP control frames. |
@@ -1558,6 +1605,12 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1558 | err = copy_mesh_setup(ifmsh, setup); | 1605 | err = copy_mesh_setup(ifmsh, setup); |
1559 | if (err) | 1606 | if (err) |
1560 | return err; | 1607 | return err; |
1608 | |||
1609 | err = ieee80211_set_channel(wiphy, dev, setup->channel, | ||
1610 | setup->channel_type); | ||
1611 | if (err) | ||
1612 | return err; | ||
1613 | |||
1561 | ieee80211_start_mesh(sdata); | 1614 | ieee80211_start_mesh(sdata); |
1562 | 1615 | ||
1563 | return 0; | 1616 | return 0; |
@@ -1677,55 +1730,6 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1677 | return 0; | 1730 | return 0; |
1678 | } | 1731 | } |
1679 | 1732 | ||
1680 | static int ieee80211_set_channel(struct wiphy *wiphy, | ||
1681 | struct net_device *netdev, | ||
1682 | struct ieee80211_channel *chan, | ||
1683 | enum nl80211_channel_type channel_type) | ||
1684 | { | ||
1685 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1686 | struct ieee80211_sub_if_data *sdata = NULL; | ||
1687 | struct ieee80211_channel *old_oper; | ||
1688 | enum nl80211_channel_type old_oper_type; | ||
1689 | enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT; | ||
1690 | |||
1691 | if (netdev) | ||
1692 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
1693 | |||
1694 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
1695 | case CHAN_MODE_HOPPING: | ||
1696 | return -EBUSY; | ||
1697 | case CHAN_MODE_FIXED: | ||
1698 | if (local->oper_channel != chan) | ||
1699 | return -EBUSY; | ||
1700 | if (!sdata && local->_oper_channel_type == channel_type) | ||
1701 | return 0; | ||
1702 | break; | ||
1703 | case CHAN_MODE_UNDEFINED: | ||
1704 | break; | ||
1705 | } | ||
1706 | |||
1707 | if (sdata) | ||
1708 | old_vif_oper_type = sdata->vif.bss_conf.channel_type; | ||
1709 | old_oper_type = local->_oper_channel_type; | ||
1710 | |||
1711 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | ||
1712 | return -EBUSY; | ||
1713 | |||
1714 | old_oper = local->oper_channel; | ||
1715 | local->oper_channel = chan; | ||
1716 | |||
1717 | /* Update driver if changes were actually made. */ | ||
1718 | if ((old_oper != local->oper_channel) || | ||
1719 | (old_oper_type != local->_oper_channel_type)) | ||
1720 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1721 | |||
1722 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
1723 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) | ||
1724 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | ||
1725 | |||
1726 | return 0; | ||
1727 | } | ||
1728 | |||
1729 | #ifdef CONFIG_PM | 1733 | #ifdef CONFIG_PM |
1730 | static int ieee80211_suspend(struct wiphy *wiphy, | 1734 | static int ieee80211_suspend(struct wiphy *wiphy, |
1731 | struct cfg80211_wowlan *wowlan) | 1735 | struct cfg80211_wowlan *wowlan) |
@@ -2108,35 +2112,171 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2108 | return 0; | 2112 | return 0; |
2109 | } | 2113 | } |
2110 | 2114 | ||
2111 | static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, | 2115 | static int ieee80211_start_roc_work(struct ieee80211_local *local, |
2112 | struct net_device *dev, | 2116 | struct ieee80211_sub_if_data *sdata, |
2113 | struct ieee80211_channel *chan, | 2117 | struct ieee80211_channel *channel, |
2114 | enum nl80211_channel_type chantype, | 2118 | enum nl80211_channel_type channel_type, |
2115 | unsigned int duration, u64 *cookie) | 2119 | unsigned int duration, u64 *cookie, |
2120 | struct sk_buff *txskb) | ||
2116 | { | 2121 | { |
2122 | struct ieee80211_roc_work *roc, *tmp; | ||
2123 | bool queued = false; | ||
2117 | int ret; | 2124 | int ret; |
2118 | u32 random_cookie; | ||
2119 | 2125 | ||
2120 | lockdep_assert_held(&local->mtx); | 2126 | lockdep_assert_held(&local->mtx); |
2121 | 2127 | ||
2122 | if (local->hw_roc_cookie) | 2128 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); |
2123 | return -EBUSY; | 2129 | if (!roc) |
2124 | /* must be nonzero */ | 2130 | return -ENOMEM; |
2125 | random_cookie = random32() | 1; | 2131 | |
2126 | 2132 | roc->chan = channel; | |
2127 | *cookie = random_cookie; | 2133 | roc->chan_type = channel_type; |
2128 | local->hw_roc_dev = dev; | 2134 | roc->duration = duration; |
2129 | local->hw_roc_cookie = random_cookie; | 2135 | roc->req_duration = duration; |
2130 | local->hw_roc_channel = chan; | 2136 | roc->frame = txskb; |
2131 | local->hw_roc_channel_type = chantype; | 2137 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2132 | local->hw_roc_duration = duration; | 2138 | roc->sdata = sdata; |
2133 | ret = drv_remain_on_channel(local, chan, chantype, duration); | 2139 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
2140 | INIT_LIST_HEAD(&roc->dependents); | ||
2141 | |||
2142 | /* if there's one pending or we're scanning, queue this one */ | ||
2143 | if (!list_empty(&local->roc_list) || local->scanning) | ||
2144 | goto out_check_combine; | ||
2145 | |||
2146 | /* if not HW assist, just queue & schedule work */ | ||
2147 | if (!local->ops->remain_on_channel) { | ||
2148 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | ||
2149 | goto out_queue; | ||
2150 | } | ||
2151 | |||
2152 | /* otherwise actually kick it off here (for error handling) */ | ||
2153 | |||
2154 | /* | ||
2155 | * If the duration is zero, then the driver | ||
2156 | * wouldn't actually do anything. Set it to | ||
2157 | * 10 for now. | ||
2158 | * | ||
2159 | * TODO: cancel the off-channel operation | ||
2160 | * when we get the SKB's TX status and | ||
2161 | * the wait time was zero before. | ||
2162 | */ | ||
2163 | if (!duration) | ||
2164 | duration = 10; | ||
2165 | |||
2166 | ret = drv_remain_on_channel(local, channel, channel_type, duration); | ||
2134 | if (ret) { | 2167 | if (ret) { |
2135 | local->hw_roc_channel = NULL; | 2168 | kfree(roc); |
2136 | local->hw_roc_cookie = 0; | 2169 | return ret; |
2137 | } | 2170 | } |
2138 | 2171 | ||
2139 | return ret; | 2172 | roc->started = true; |
2173 | goto out_queue; | ||
2174 | |||
2175 | out_check_combine: | ||
2176 | list_for_each_entry(tmp, &local->roc_list, list) { | ||
2177 | if (tmp->chan != channel || tmp->chan_type != channel_type) | ||
2178 | continue; | ||
2179 | |||
2180 | /* | ||
2181 | * Extend this ROC if possible: | ||
2182 | * | ||
2183 | * If it hasn't started yet, just increase the duration | ||
2184 | * and add the new one to the list of dependents. | ||
2185 | */ | ||
2186 | if (!tmp->started) { | ||
2187 | list_add_tail(&roc->list, &tmp->dependents); | ||
2188 | tmp->duration = max(tmp->duration, roc->duration); | ||
2189 | queued = true; | ||
2190 | break; | ||
2191 | } | ||
2192 | |||
2193 | /* If it has already started, it's more difficult ... */ | ||
2194 | if (local->ops->remain_on_channel) { | ||
2195 | unsigned long j = jiffies; | ||
2196 | |||
2197 | /* | ||
2198 | * In the offloaded ROC case, if it hasn't begun, add | ||
2199 | * this new one to the dependent list to be handled | ||
2200 | * when the the master one begins. If it has begun, | ||
2201 | * check that there's still a minimum time left and | ||
2202 | * if so, start this one, transmitting the frame, but | ||
2203 | * add it to the list directly after this one with a | ||
2204 | * a reduced time so we'll ask the driver to execute | ||
2205 | * it right after finishing the previous one, in the | ||
2206 | * hope that it'll also be executed right afterwards, | ||
2207 | * effectively extending the old one. | ||
2208 | * If there's no minimum time left, just add it to the | ||
2209 | * normal list. | ||
2210 | */ | ||
2211 | if (!tmp->hw_begun) { | ||
2212 | list_add_tail(&roc->list, &tmp->dependents); | ||
2213 | queued = true; | ||
2214 | break; | ||
2215 | } | ||
2216 | |||
2217 | if (time_before(j + IEEE80211_ROC_MIN_LEFT, | ||
2218 | tmp->hw_start_time + | ||
2219 | msecs_to_jiffies(tmp->duration))) { | ||
2220 | int new_dur; | ||
2221 | |||
2222 | ieee80211_handle_roc_started(roc); | ||
2223 | |||
2224 | new_dur = roc->duration - | ||
2225 | jiffies_to_msecs(tmp->hw_start_time + | ||
2226 | msecs_to_jiffies( | ||
2227 | tmp->duration) - | ||
2228 | j); | ||
2229 | |||
2230 | if (new_dur > 0) { | ||
2231 | /* add right after tmp */ | ||
2232 | list_add(&roc->list, &tmp->list); | ||
2233 | } else { | ||
2234 | list_add_tail(&roc->list, | ||
2235 | &tmp->dependents); | ||
2236 | } | ||
2237 | queued = true; | ||
2238 | } | ||
2239 | } else if (del_timer_sync(&tmp->work.timer)) { | ||
2240 | unsigned long new_end; | ||
2241 | |||
2242 | /* | ||
2243 | * In the software ROC case, cancel the timer, if | ||
2244 | * that fails then the finish work is already | ||
2245 | * queued/pending and thus we queue the new ROC | ||
2246 | * normally, if that succeeds then we can extend | ||
2247 | * the timer duration and TX the frame (if any.) | ||
2248 | */ | ||
2249 | |||
2250 | list_add_tail(&roc->list, &tmp->dependents); | ||
2251 | queued = true; | ||
2252 | |||
2253 | new_end = jiffies + msecs_to_jiffies(roc->duration); | ||
2254 | |||
2255 | /* ok, it was started & we canceled timer */ | ||
2256 | if (time_after(new_end, tmp->work.timer.expires)) | ||
2257 | mod_timer(&tmp->work.timer, new_end); | ||
2258 | else | ||
2259 | add_timer(&tmp->work.timer); | ||
2260 | |||
2261 | ieee80211_handle_roc_started(roc); | ||
2262 | } | ||
2263 | break; | ||
2264 | } | ||
2265 | |||
2266 | out_queue: | ||
2267 | if (!queued) | ||
2268 | list_add_tail(&roc->list, &local->roc_list); | ||
2269 | |||
2270 | /* | ||
2271 | * cookie is either the roc (for normal roc) | ||
2272 | * or the SKB (for mgmt TX) | ||
2273 | */ | ||
2274 | if (txskb) | ||
2275 | *cookie = (unsigned long)txskb; | ||
2276 | else | ||
2277 | *cookie = (unsigned long)roc; | ||
2278 | |||
2279 | return 0; | ||
2140 | } | 2280 | } |
2141 | 2281 | ||
2142 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2282 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
@@ -2148,42 +2288,64 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2148 | { | 2288 | { |
2149 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2289 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2150 | struct ieee80211_local *local = sdata->local; | 2290 | struct ieee80211_local *local = sdata->local; |
2291 | int ret; | ||
2151 | 2292 | ||
2152 | if (local->ops->remain_on_channel) { | 2293 | mutex_lock(&local->mtx); |
2153 | int ret; | 2294 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, |
2154 | 2295 | duration, cookie, NULL); | |
2155 | mutex_lock(&local->mtx); | 2296 | mutex_unlock(&local->mtx); |
2156 | ret = ieee80211_remain_on_channel_hw(local, dev, | ||
2157 | chan, channel_type, | ||
2158 | duration, cookie); | ||
2159 | local->hw_roc_for_tx = false; | ||
2160 | mutex_unlock(&local->mtx); | ||
2161 | |||
2162 | return ret; | ||
2163 | } | ||
2164 | 2297 | ||
2165 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, | 2298 | return ret; |
2166 | duration, cookie); | ||
2167 | } | 2299 | } |
2168 | 2300 | ||
2169 | static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, | 2301 | static int ieee80211_cancel_roc(struct ieee80211_local *local, |
2170 | u64 cookie) | 2302 | u64 cookie, bool mgmt_tx) |
2171 | { | 2303 | { |
2304 | struct ieee80211_roc_work *roc, *tmp, *found = NULL; | ||
2172 | int ret; | 2305 | int ret; |
2173 | 2306 | ||
2174 | lockdep_assert_held(&local->mtx); | 2307 | mutex_lock(&local->mtx); |
2308 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
2309 | if (!mgmt_tx && (unsigned long)roc != cookie) | ||
2310 | continue; | ||
2311 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | ||
2312 | continue; | ||
2313 | |||
2314 | found = roc; | ||
2315 | break; | ||
2316 | } | ||
2175 | 2317 | ||
2176 | if (local->hw_roc_cookie != cookie) | 2318 | if (!found) { |
2319 | mutex_unlock(&local->mtx); | ||
2177 | return -ENOENT; | 2320 | return -ENOENT; |
2321 | } | ||
2178 | 2322 | ||
2179 | ret = drv_cancel_remain_on_channel(local); | 2323 | if (local->ops->remain_on_channel) { |
2180 | if (ret) | 2324 | if (found->started) { |
2181 | return ret; | 2325 | ret = drv_cancel_remain_on_channel(local); |
2326 | if (WARN_ON_ONCE(ret)) { | ||
2327 | mutex_unlock(&local->mtx); | ||
2328 | return ret; | ||
2329 | } | ||
2330 | } | ||
2182 | 2331 | ||
2183 | local->hw_roc_cookie = 0; | 2332 | list_del(&found->list); |
2184 | local->hw_roc_channel = NULL; | ||
2185 | 2333 | ||
2186 | ieee80211_recalc_idle(local); | 2334 | ieee80211_run_deferred_scan(local); |
2335 | ieee80211_start_next_roc(local); | ||
2336 | mutex_unlock(&local->mtx); | ||
2337 | |||
2338 | ieee80211_roc_notify_destroy(found); | ||
2339 | } else { | ||
2340 | /* work may be pending so use it all the time */ | ||
2341 | found->abort = true; | ||
2342 | ieee80211_queue_delayed_work(&local->hw, &found->work, 0); | ||
2343 | |||
2344 | mutex_unlock(&local->mtx); | ||
2345 | |||
2346 | /* work will clean up etc */ | ||
2347 | flush_delayed_work(&found->work); | ||
2348 | } | ||
2187 | 2349 | ||
2188 | return 0; | 2350 | return 0; |
2189 | } | 2351 | } |
@@ -2195,39 +2357,7 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
2195 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2357 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2196 | struct ieee80211_local *local = sdata->local; | 2358 | struct ieee80211_local *local = sdata->local; |
2197 | 2359 | ||
2198 | if (local->ops->cancel_remain_on_channel) { | 2360 | return ieee80211_cancel_roc(local, cookie, false); |
2199 | int ret; | ||
2200 | |||
2201 | mutex_lock(&local->mtx); | ||
2202 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
2203 | mutex_unlock(&local->mtx); | ||
2204 | |||
2205 | return ret; | ||
2206 | } | ||
2207 | |||
2208 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | ||
2209 | } | ||
2210 | |||
2211 | static enum work_done_result | ||
2212 | ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | ||
2213 | { | ||
2214 | /* | ||
2215 | * Use the data embedded in the work struct for reporting | ||
2216 | * here so if the driver mangled the SKB before dropping | ||
2217 | * it (which is the only way we really should get here) | ||
2218 | * then we don't report mangled data. | ||
2219 | * | ||
2220 | * If there was no wait time, then by the time we get here | ||
2221 | * the driver will likely not have reported the status yet, | ||
2222 | * so in that case userspace will have to deal with it. | ||
2223 | */ | ||
2224 | |||
2225 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) | ||
2226 | cfg80211_mgmt_tx_status(wk->sdata->dev, | ||
2227 | (unsigned long) wk->offchan_tx.frame, | ||
2228 | wk->data, wk->data_len, false, GFP_KERNEL); | ||
2229 | |||
2230 | return WORK_DONE_DESTROY; | ||
2231 | } | 2361 | } |
2232 | 2362 | ||
2233 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 2363 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
@@ -2241,10 +2371,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2241 | struct ieee80211_local *local = sdata->local; | 2371 | struct ieee80211_local *local = sdata->local; |
2242 | struct sk_buff *skb; | 2372 | struct sk_buff *skb; |
2243 | struct sta_info *sta; | 2373 | struct sta_info *sta; |
2244 | struct ieee80211_work *wk; | ||
2245 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 2374 | const struct ieee80211_mgmt *mgmt = (void *)buf; |
2375 | bool need_offchan = false; | ||
2246 | u32 flags; | 2376 | u32 flags; |
2247 | bool is_offchan = false; | 2377 | int ret; |
2248 | 2378 | ||
2249 | if (dont_wait_for_ack) | 2379 | if (dont_wait_for_ack) |
2250 | flags = IEEE80211_TX_CTL_NO_ACK; | 2380 | flags = IEEE80211_TX_CTL_NO_ACK; |
@@ -2252,33 +2382,28 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2252 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 2382 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
2253 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 2383 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
2254 | 2384 | ||
2255 | /* Check that we are on the requested channel for transmission */ | ||
2256 | if (chan != local->tmp_channel && | ||
2257 | chan != local->oper_channel) | ||
2258 | is_offchan = true; | ||
2259 | if (channel_type_valid && | ||
2260 | (channel_type != local->tmp_channel_type && | ||
2261 | channel_type != local->_oper_channel_type)) | ||
2262 | is_offchan = true; | ||
2263 | |||
2264 | if (chan == local->hw_roc_channel) { | ||
2265 | /* TODO: check channel type? */ | ||
2266 | is_offchan = false; | ||
2267 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
2268 | } | ||
2269 | |||
2270 | if (no_cck) | 2385 | if (no_cck) |
2271 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 2386 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
2272 | 2387 | ||
2273 | if (is_offchan && !offchan) | ||
2274 | return -EBUSY; | ||
2275 | |||
2276 | switch (sdata->vif.type) { | 2388 | switch (sdata->vif.type) { |
2277 | case NL80211_IFTYPE_ADHOC: | 2389 | case NL80211_IFTYPE_ADHOC: |
2390 | if (!sdata->vif.bss_conf.ibss_joined) | ||
2391 | need_offchan = true; | ||
2392 | /* fall through */ | ||
2393 | #ifdef CONFIG_MAC80211_MESH | ||
2394 | case NL80211_IFTYPE_MESH_POINT: | ||
2395 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
2396 | !sdata->u.mesh.mesh_id_len) | ||
2397 | need_offchan = true; | ||
2398 | /* fall through */ | ||
2399 | #endif | ||
2278 | case NL80211_IFTYPE_AP: | 2400 | case NL80211_IFTYPE_AP: |
2279 | case NL80211_IFTYPE_AP_VLAN: | 2401 | case NL80211_IFTYPE_AP_VLAN: |
2280 | case NL80211_IFTYPE_P2P_GO: | 2402 | case NL80211_IFTYPE_P2P_GO: |
2281 | case NL80211_IFTYPE_MESH_POINT: | 2403 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2404 | !ieee80211_vif_is_mesh(&sdata->vif) && | ||
2405 | !rcu_access_pointer(sdata->bss->beacon)) | ||
2406 | need_offchan = true; | ||
2282 | if (!ieee80211_is_action(mgmt->frame_control) || | 2407 | if (!ieee80211_is_action(mgmt->frame_control) || |
2283 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 2408 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
2284 | break; | 2409 | break; |
@@ -2290,103 +2415,60 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2290 | break; | 2415 | break; |
2291 | case NL80211_IFTYPE_STATION: | 2416 | case NL80211_IFTYPE_STATION: |
2292 | case NL80211_IFTYPE_P2P_CLIENT: | 2417 | case NL80211_IFTYPE_P2P_CLIENT: |
2418 | if (!sdata->u.mgd.associated) | ||
2419 | need_offchan = true; | ||
2293 | break; | 2420 | break; |
2294 | default: | 2421 | default: |
2295 | return -EOPNOTSUPP; | 2422 | return -EOPNOTSUPP; |
2296 | } | 2423 | } |
2297 | 2424 | ||
2425 | mutex_lock(&local->mtx); | ||
2426 | |||
2427 | /* Check if the operating channel is the requested channel */ | ||
2428 | if (!need_offchan) { | ||
2429 | need_offchan = chan != local->oper_channel; | ||
2430 | if (channel_type_valid && | ||
2431 | channel_type != local->_oper_channel_type) | ||
2432 | need_offchan = true; | ||
2433 | } | ||
2434 | |||
2435 | if (need_offchan && !offchan) { | ||
2436 | ret = -EBUSY; | ||
2437 | goto out_unlock; | ||
2438 | } | ||
2439 | |||
2298 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 2440 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); |
2299 | if (!skb) | 2441 | if (!skb) { |
2300 | return -ENOMEM; | 2442 | ret = -ENOMEM; |
2443 | goto out_unlock; | ||
2444 | } | ||
2301 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2445 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2302 | 2446 | ||
2303 | memcpy(skb_put(skb, len), buf, len); | 2447 | memcpy(skb_put(skb, len), buf, len); |
2304 | 2448 | ||
2305 | IEEE80211_SKB_CB(skb)->flags = flags; | 2449 | IEEE80211_SKB_CB(skb)->flags = flags; |
2306 | 2450 | ||
2307 | if (flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
2308 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
2309 | local->hw.offchannel_tx_hw_queue; | ||
2310 | |||
2311 | skb->dev = sdata->dev; | 2451 | skb->dev = sdata->dev; |
2312 | 2452 | ||
2313 | *cookie = (unsigned long) skb; | 2453 | if (!need_offchan) { |
2314 | 2454 | ieee80211_tx_skb(sdata, skb); | |
2315 | if (is_offchan && local->ops->remain_on_channel) { | 2455 | ret = 0; |
2316 | unsigned int duration; | 2456 | goto out_unlock; |
2317 | int ret; | 2457 | } |
2318 | |||
2319 | mutex_lock(&local->mtx); | ||
2320 | /* | ||
2321 | * If the duration is zero, then the driver | ||
2322 | * wouldn't actually do anything. Set it to | ||
2323 | * 100 for now. | ||
2324 | * | ||
2325 | * TODO: cancel the off-channel operation | ||
2326 | * when we get the SKB's TX status and | ||
2327 | * the wait time was zero before. | ||
2328 | */ | ||
2329 | duration = 100; | ||
2330 | if (wait) | ||
2331 | duration = wait; | ||
2332 | ret = ieee80211_remain_on_channel_hw(local, dev, chan, | ||
2333 | channel_type, | ||
2334 | duration, cookie); | ||
2335 | if (ret) { | ||
2336 | kfree_skb(skb); | ||
2337 | mutex_unlock(&local->mtx); | ||
2338 | return ret; | ||
2339 | } | ||
2340 | |||
2341 | local->hw_roc_for_tx = true; | ||
2342 | local->hw_roc_duration = wait; | ||
2343 | |||
2344 | /* | ||
2345 | * queue up frame for transmission after | ||
2346 | * ieee80211_ready_on_channel call | ||
2347 | */ | ||
2348 | 2458 | ||
2349 | /* modify cookie to prevent API mismatches */ | 2459 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; |
2350 | *cookie ^= 2; | 2460 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) |
2351 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | ||
2352 | IEEE80211_SKB_CB(skb)->hw_queue = | 2461 | IEEE80211_SKB_CB(skb)->hw_queue = |
2353 | local->hw.offchannel_tx_hw_queue; | 2462 | local->hw.offchannel_tx_hw_queue; |
2354 | local->hw_roc_skb = skb; | ||
2355 | local->hw_roc_skb_for_status = skb; | ||
2356 | mutex_unlock(&local->mtx); | ||
2357 | |||
2358 | return 0; | ||
2359 | } | ||
2360 | |||
2361 | /* | ||
2362 | * Can transmit right away if the channel was the | ||
2363 | * right one and there's no wait involved... If a | ||
2364 | * wait is involved, we might otherwise not be on | ||
2365 | * the right channel for long enough! | ||
2366 | */ | ||
2367 | if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { | ||
2368 | ieee80211_tx_skb(sdata, skb); | ||
2369 | return 0; | ||
2370 | } | ||
2371 | 2463 | ||
2372 | wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); | 2464 | /* This will handle all kinds of coalescing and immediate TX */ |
2373 | if (!wk) { | 2465 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, |
2466 | wait, cookie, skb); | ||
2467 | if (ret) | ||
2374 | kfree_skb(skb); | 2468 | kfree_skb(skb); |
2375 | return -ENOMEM; | 2469 | out_unlock: |
2376 | } | 2470 | mutex_unlock(&local->mtx); |
2377 | 2471 | return ret; | |
2378 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; | ||
2379 | wk->chan = chan; | ||
2380 | wk->chan_type = channel_type; | ||
2381 | wk->sdata = sdata; | ||
2382 | wk->done = ieee80211_offchan_tx_done; | ||
2383 | wk->offchan_tx.frame = skb; | ||
2384 | wk->offchan_tx.wait = wait; | ||
2385 | wk->data_len = len; | ||
2386 | memcpy(wk->data, buf, len); | ||
2387 | |||
2388 | ieee80211_add_work(wk); | ||
2389 | return 0; | ||
2390 | } | 2472 | } |
2391 | 2473 | ||
2392 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | 2474 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, |
@@ -2395,45 +2477,8 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | |||
2395 | { | 2477 | { |
2396 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2478 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2397 | struct ieee80211_local *local = sdata->local; | 2479 | struct ieee80211_local *local = sdata->local; |
2398 | struct ieee80211_work *wk; | ||
2399 | int ret = -ENOENT; | ||
2400 | |||
2401 | mutex_lock(&local->mtx); | ||
2402 | |||
2403 | if (local->ops->cancel_remain_on_channel) { | ||
2404 | cookie ^= 2; | ||
2405 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | ||
2406 | |||
2407 | if (ret == 0) { | ||
2408 | kfree_skb(local->hw_roc_skb); | ||
2409 | local->hw_roc_skb = NULL; | ||
2410 | local->hw_roc_skb_for_status = NULL; | ||
2411 | } | ||
2412 | |||
2413 | mutex_unlock(&local->mtx); | ||
2414 | 2480 | ||
2415 | return ret; | 2481 | return ieee80211_cancel_roc(local, cookie, true); |
2416 | } | ||
2417 | |||
2418 | list_for_each_entry(wk, &local->work_list, list) { | ||
2419 | if (wk->sdata != sdata) | ||
2420 | continue; | ||
2421 | |||
2422 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
2423 | continue; | ||
2424 | |||
2425 | if (cookie != (unsigned long) wk->offchan_tx.frame) | ||
2426 | continue; | ||
2427 | |||
2428 | wk->timeout = jiffies; | ||
2429 | |||
2430 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
2431 | ret = 0; | ||
2432 | break; | ||
2433 | } | ||
2434 | mutex_unlock(&local->mtx); | ||
2435 | |||
2436 | return ret; | ||
2437 | } | 2482 | } |
2438 | 2483 | ||
2439 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 2484 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
@@ -2677,7 +2722,7 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2677 | return -EINVAL; | 2722 | return -EINVAL; |
2678 | 2723 | ||
2679 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2724 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG |
2680 | printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer); | 2725 | pr_debug("TDLS mgmt action %d peer %pM\n", action_code, peer); |
2681 | #endif | 2726 | #endif |
2682 | 2727 | ||
2683 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 2728 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
@@ -2788,7 +2833,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
2788 | return -EINVAL; | 2833 | return -EINVAL; |
2789 | 2834 | ||
2790 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2835 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG |
2791 | printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer); | 2836 | pr_debug("TDLS oper %d peer %pM\n", oper, peer); |
2792 | #endif | 2837 | #endif |
2793 | 2838 | ||
2794 | switch (oper) { | 2839 | switch (oper) { |
@@ -2933,7 +2978,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2933 | #endif | 2978 | #endif |
2934 | .change_bss = ieee80211_change_bss, | 2979 | .change_bss = ieee80211_change_bss, |
2935 | .set_txq_params = ieee80211_set_txq_params, | 2980 | .set_txq_params = ieee80211_set_txq_params, |
2936 | .set_channel = ieee80211_set_channel, | 2981 | .set_monitor_channel = ieee80211_set_monitor_channel, |
2937 | .suspend = ieee80211_suspend, | 2982 | .suspend = ieee80211_suspend, |
2938 | .resume = ieee80211_resume, | 2983 | .resume = ieee80211_resume, |
2939 | .scan = ieee80211_scan, | 2984 | .scan = ieee80211_scan, |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index c76cf7230c7d..f0f87e5a1d35 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -41,6 +41,10 @@ __ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
41 | if (!sdata->u.ap.beacon) | 41 | if (!sdata->u.ap.beacon) |
42 | continue; | 42 | continue; |
43 | break; | 43 | break; |
44 | case NL80211_IFTYPE_MESH_POINT: | ||
45 | if (!sdata->wdev.mesh_id_len) | ||
46 | continue; | ||
47 | break; | ||
44 | default: | 48 | default: |
45 | break; | 49 | break; |
46 | } | 50 | } |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 7ed433c66d68..d4272ff43f71 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -607,6 +607,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
607 | MESHPARAMS_ADD(min_discovery_timeout); | 607 | MESHPARAMS_ADD(min_discovery_timeout); |
608 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); | 608 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); |
609 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); | 609 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); |
610 | MESHPARAMS_ADD(dot11MeshForwarding); | ||
610 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); | 611 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); |
611 | MESHPARAMS_ADD(rssi_threshold); | 612 | MESHPARAMS_ADD(rssi_threshold); |
612 | MESHPARAMS_ADD(ht_opmode); | 613 | MESHPARAMS_ADD(ht_opmode); |
@@ -685,6 +686,6 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | |||
685 | 686 | ||
686 | sprintf(buf, "netdev:%s", sdata->name); | 687 | sprintf(buf, "netdev:%s", sdata->name); |
687 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 688 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
688 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 689 | pr_err("mac80211: debugfs: failed to rename debugfs " |
689 | "dir to %s\n", buf); | 690 | "dir to %s\n", buf); |
690 | } | 691 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33d9d0c3e3d0..725cb4be229d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -82,8 +82,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
82 | 82 | ||
83 | local->oper_channel = chan; | 83 | local->oper_channel = chan; |
84 | channel_type = ifibss->channel_type; | 84 | channel_type = ifibss->channel_type; |
85 | if (channel_type > NL80211_CHAN_HT20 && | 85 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) |
86 | !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | ||
87 | channel_type = NL80211_CHAN_HT20; | 86 | channel_type = NL80211_CHAN_HT20; |
88 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 87 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
89 | /* can only fail due to HT40+/- mismatch */ | 88 | /* can only fail due to HT40+/- mismatch */ |
@@ -281,11 +280,8 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
281 | if (sta_info_insert_rcu(sta)) | 280 | if (sta_info_insert_rcu(sta)) |
282 | return sta_info_get(sdata, addr); | 281 | return sta_info_get(sdata, addr); |
283 | if (auth) { | 282 | if (auth) { |
284 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 283 | ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", |
285 | printk(KERN_DEBUG "TX Auth SA=%pM DA=%pM BSSID=%pM" | 284 | sdata->vif.addr, sdata->u.ibss.bssid, addr); |
286 | "(auth_transaction=1)\n", sdata->vif.addr, | ||
287 | sdata->u.ibss.bssid, addr); | ||
288 | #endif | ||
289 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, | 285 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, |
290 | addr, sdata->u.ibss.bssid, NULL, 0, 0); | 286 | addr, sdata->u.ibss.bssid, NULL, 0, 0); |
291 | } | 287 | } |
@@ -355,11 +351,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
355 | 351 | ||
356 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | 352 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) |
357 | return; | 353 | return; |
358 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 354 | ibss_vdbg("%s: RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", |
359 | printk(KERN_DEBUG "%s: RX Auth SA=%pM DA=%pM BSSID=%pM." | 355 | sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, |
360 | "(auth_transaction=%d)\n", | 356 | auth_transaction); |
361 | sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | ||
362 | #endif | ||
363 | sta_info_destroy_addr(sdata, mgmt->sa); | 357 | sta_info_destroy_addr(sdata, mgmt->sa); |
364 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | 358 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); |
365 | rcu_read_unlock(); | 359 | rcu_read_unlock(); |
@@ -422,15 +416,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
422 | ieee80211_mandatory_rates(local, band); | 416 | ieee80211_mandatory_rates(local, band); |
423 | 417 | ||
424 | if (sta->sta.supp_rates[band] != prev_rates) { | 418 | if (sta->sta.supp_rates[band] != prev_rates) { |
425 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 419 | ibss_vdbg("%s: updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n", |
426 | printk(KERN_DEBUG | 420 | sdata->name, sta->sta.addr, |
427 | "%s: updated supp_rates set " | 421 | prev_rates, |
428 | "for %pM based on beacon" | 422 | sta->sta.supp_rates[band]); |
429 | "/probe_resp (0x%x -> 0x%x)\n", | ||
430 | sdata->name, sta->sta.addr, | ||
431 | prev_rates, | ||
432 | sta->sta.supp_rates[band]); | ||
433 | #endif | ||
434 | rates_updated = true; | 423 | rates_updated = true; |
435 | } | 424 | } |
436 | } else { | 425 | } else { |
@@ -545,22 +534,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
545 | rx_timestamp = drv_get_tsf(local, sdata); | 534 | rx_timestamp = drv_get_tsf(local, sdata); |
546 | } | 535 | } |
547 | 536 | ||
548 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 537 | ibss_vdbg("RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", |
549 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" | 538 | mgmt->sa, mgmt->bssid, |
550 | "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", | 539 | (unsigned long long)rx_timestamp, |
551 | mgmt->sa, mgmt->bssid, | 540 | (unsigned long long)beacon_timestamp, |
552 | (unsigned long long)rx_timestamp, | 541 | (unsigned long long)(rx_timestamp - beacon_timestamp), |
553 | (unsigned long long)beacon_timestamp, | 542 | jiffies); |
554 | (unsigned long long)(rx_timestamp - beacon_timestamp), | ||
555 | jiffies); | ||
556 | #endif | ||
557 | 543 | ||
558 | if (beacon_timestamp > rx_timestamp) { | 544 | if (beacon_timestamp > rx_timestamp) { |
559 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 545 | ibss_vdbg("%s: beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", |
560 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 546 | sdata->name, mgmt->bssid); |
561 | "local TSF - IBSS merge with BSSID %pM\n", | ||
562 | sdata->name, mgmt->bssid); | ||
563 | #endif | ||
564 | ieee80211_sta_join_ibss(sdata, bss); | 547 | ieee80211_sta_join_ibss(sdata, bss); |
565 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); | 548 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); |
566 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 549 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
@@ -662,8 +645,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
662 | if (ifibss->fixed_channel) | 645 | if (ifibss->fixed_channel) |
663 | return; | 646 | return; |
664 | 647 | ||
665 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 648 | pr_debug("%s: No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n", |
666 | "IBSS networks with same SSID (merge)\n", sdata->name); | 649 | sdata->name); |
667 | 650 | ||
668 | ieee80211_request_internal_scan(sdata, | 651 | ieee80211_request_internal_scan(sdata, |
669 | ifibss->ssid, ifibss->ssid_len, NULL); | 652 | ifibss->ssid, ifibss->ssid_len, NULL); |
@@ -691,8 +674,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
691 | bssid[0] |= 0x02; | 674 | bssid[0] |= 0x02; |
692 | } | 675 | } |
693 | 676 | ||
694 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 677 | pr_debug("%s: Creating new IBSS network, BSSID %pM\n", |
695 | sdata->name, bssid); | 678 | sdata->name, bssid); |
696 | 679 | ||
697 | capability = WLAN_CAPABILITY_IBSS; | 680 | capability = WLAN_CAPABILITY_IBSS; |
698 | 681 | ||
@@ -723,10 +706,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
723 | lockdep_assert_held(&ifibss->mtx); | 706 | lockdep_assert_held(&ifibss->mtx); |
724 | 707 | ||
725 | active_ibss = ieee80211_sta_active_ibss(sdata); | 708 | active_ibss = ieee80211_sta_active_ibss(sdata); |
726 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 709 | ibss_vdbg("%s: sta_find_ibss (active_ibss=%d)\n", |
727 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 710 | sdata->name, active_ibss); |
728 | sdata->name, active_ibss); | ||
729 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
730 | 711 | ||
731 | if (active_ibss) | 712 | if (active_ibss) |
732 | return; | 713 | return; |
@@ -749,29 +730,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
749 | struct ieee80211_bss *bss; | 730 | struct ieee80211_bss *bss; |
750 | 731 | ||
751 | bss = (void *)cbss->priv; | 732 | bss = (void *)cbss->priv; |
752 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 733 | ibss_vdbg(" sta_find_ibss: selected %pM current %pM\n", |
753 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " | 734 | cbss->bssid, ifibss->bssid); |
754 | "%pM\n", cbss->bssid, ifibss->bssid); | 735 | pr_debug("%s: Selected IBSS BSSID %pM based on configured SSID\n", |
755 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 736 | sdata->name, cbss->bssid); |
756 | |||
757 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | ||
758 | " based on configured SSID\n", | ||
759 | sdata->name, cbss->bssid); | ||
760 | 737 | ||
761 | ieee80211_sta_join_ibss(sdata, bss); | 738 | ieee80211_sta_join_ibss(sdata, bss); |
762 | ieee80211_rx_bss_put(local, bss); | 739 | ieee80211_rx_bss_put(local, bss); |
763 | return; | 740 | return; |
764 | } | 741 | } |
765 | 742 | ||
766 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 743 | ibss_vdbg(" did not try to join ibss\n"); |
767 | printk(KERN_DEBUG " did not try to join ibss\n"); | ||
768 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
769 | 744 | ||
770 | /* Selected IBSS not found in current scan results - try to scan */ | 745 | /* Selected IBSS not found in current scan results - try to scan */ |
771 | if (time_after(jiffies, ifibss->last_scan_completed + | 746 | if (time_after(jiffies, ifibss->last_scan_completed + |
772 | IEEE80211_SCAN_INTERVAL)) { | 747 | IEEE80211_SCAN_INTERVAL)) { |
773 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 748 | pr_debug("%s: Trigger new scan to find an IBSS to join\n", |
774 | "join\n", sdata->name); | 749 | sdata->name); |
775 | 750 | ||
776 | ieee80211_request_internal_scan(sdata, | 751 | ieee80211_request_internal_scan(sdata, |
777 | ifibss->ssid, ifibss->ssid_len, | 752 | ifibss->ssid, ifibss->ssid_len, |
@@ -785,9 +760,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
785 | ieee80211_sta_create_ibss(sdata); | 760 | ieee80211_sta_create_ibss(sdata); |
786 | return; | 761 | return; |
787 | } | 762 | } |
788 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 763 | pr_debug("%s: IBSS not allowed on %d MHz\n", |
789 | " %d MHz\n", sdata->name, | 764 | sdata->name, |
790 | local->hw.conf.channel->center_freq); | 765 | local->hw.conf.channel->center_freq); |
791 | 766 | ||
792 | /* No IBSS found - decrease scan interval and continue | 767 | /* No IBSS found - decrease scan interval and continue |
793 | * scanning. */ | 768 | * scanning. */ |
@@ -822,12 +797,9 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
822 | 797 | ||
823 | tx_last_beacon = drv_tx_last_beacon(local); | 798 | tx_last_beacon = drv_tx_last_beacon(local); |
824 | 799 | ||
825 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 800 | ibss_vdbg("%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n", |
826 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" | 801 | sdata->name, mgmt->sa, mgmt->da, |
827 | " (tx_last_beacon=%d)\n", | 802 | mgmt->bssid, tx_last_beacon); |
828 | sdata->name, mgmt->sa, mgmt->da, | ||
829 | mgmt->bssid, tx_last_beacon); | ||
830 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
831 | 803 | ||
832 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) | 804 | if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) |
833 | return; | 805 | return; |
@@ -840,11 +812,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
840 | pos = mgmt->u.probe_req.variable; | 812 | pos = mgmt->u.probe_req.variable; |
841 | if (pos[0] != WLAN_EID_SSID || | 813 | if (pos[0] != WLAN_EID_SSID || |
842 | pos + 2 + pos[1] > end) { | 814 | pos + 2 + pos[1] > end) { |
843 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 815 | ibss_vdbg("%s: Invalid SSID IE in ProbeReq from %pM\n", |
844 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 816 | sdata->name, mgmt->sa); |
845 | "from %pM\n", | ||
846 | sdata->name, mgmt->sa); | ||
847 | #endif | ||
848 | return; | 817 | return; |
849 | } | 818 | } |
850 | if (pos[1] != 0 && | 819 | if (pos[1] != 0 && |
@@ -861,10 +830,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
861 | 830 | ||
862 | resp = (struct ieee80211_mgmt *) skb->data; | 831 | resp = (struct ieee80211_mgmt *) skb->data; |
863 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 832 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
864 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 833 | ibss_vdbg("%s: Sending ProbeResp to %pM\n", sdata->name, resp->da); |
865 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", | ||
866 | sdata->name, resp->da); | ||
867 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | ||
868 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 834 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
869 | ieee80211_tx_skb(sdata, skb); | 835 | ieee80211_tx_skb(sdata, skb); |
870 | } | 836 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3f3cd50fff16..e6cbf5b68c89 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,55 +317,30 @@ struct mesh_preq_queue { | |||
317 | u8 flags; | 317 | u8 flags; |
318 | }; | 318 | }; |
319 | 319 | ||
320 | enum ieee80211_work_type { | 320 | #if HZ/100 == 0 |
321 | IEEE80211_WORK_ABORT, | 321 | #define IEEE80211_ROC_MIN_LEFT 1 |
322 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | 322 | #else |
323 | IEEE80211_WORK_OFFCHANNEL_TX, | 323 | #define IEEE80211_ROC_MIN_LEFT (HZ/100) |
324 | }; | 324 | #endif |
325 | |||
326 | /** | ||
327 | * enum work_done_result - indicates what to do after work was done | ||
328 | * | ||
329 | * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. | ||
330 | * @WORK_DONE_REQUEUE: This work item was reset to be reused, and | ||
331 | * should be requeued. | ||
332 | */ | ||
333 | enum work_done_result { | ||
334 | WORK_DONE_DESTROY, | ||
335 | WORK_DONE_REQUEUE, | ||
336 | }; | ||
337 | 325 | ||
338 | struct ieee80211_work { | 326 | struct ieee80211_roc_work { |
339 | struct list_head list; | 327 | struct list_head list; |
328 | struct list_head dependents; | ||
340 | 329 | ||
341 | struct rcu_head rcu_head; | 330 | struct delayed_work work; |
342 | 331 | ||
343 | struct ieee80211_sub_if_data *sdata; | 332 | struct ieee80211_sub_if_data *sdata; |
344 | 333 | ||
345 | enum work_done_result (*done)(struct ieee80211_work *wk, | ||
346 | struct sk_buff *skb); | ||
347 | |||
348 | struct ieee80211_channel *chan; | 334 | struct ieee80211_channel *chan; |
349 | enum nl80211_channel_type chan_type; | 335 | enum nl80211_channel_type chan_type; |
350 | 336 | ||
351 | unsigned long timeout; | 337 | bool started, abort, hw_begun, notified; |
352 | enum ieee80211_work_type type; | ||
353 | 338 | ||
354 | bool started; | 339 | unsigned long hw_start_time; |
355 | 340 | ||
356 | union { | 341 | u32 duration, req_duration; |
357 | struct { | 342 | struct sk_buff *frame; |
358 | u32 duration; | 343 | u64 mgmt_tx_cookie; |
359 | } remain; | ||
360 | struct { | ||
361 | struct sk_buff *frame; | ||
362 | u32 wait; | ||
363 | bool status; | ||
364 | } offchan_tx; | ||
365 | }; | ||
366 | |||
367 | size_t data_len; | ||
368 | u8 data[]; | ||
369 | }; | 344 | }; |
370 | 345 | ||
371 | /* flags used in struct ieee80211_if_managed.flags */ | 346 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -399,7 +374,6 @@ struct ieee80211_mgd_auth_data { | |||
399 | struct ieee80211_mgd_assoc_data { | 374 | struct ieee80211_mgd_assoc_data { |
400 | struct cfg80211_bss *bss; | 375 | struct cfg80211_bss *bss; |
401 | const u8 *supp_rates; | 376 | const u8 *supp_rates; |
402 | const u8 *ht_operation_ie; | ||
403 | 377 | ||
404 | unsigned long timeout; | 378 | unsigned long timeout; |
405 | int tries; | 379 | int tries; |
@@ -414,6 +388,8 @@ struct ieee80211_mgd_assoc_data { | |||
414 | bool sent_assoc; | 388 | bool sent_assoc; |
415 | bool synced; | 389 | bool synced; |
416 | 390 | ||
391 | u8 ap_ht_param; | ||
392 | |||
417 | size_t ie_len; | 393 | size_t ie_len; |
418 | u8 ie[]; | 394 | u8 ie[]; |
419 | }; | 395 | }; |
@@ -847,13 +823,6 @@ struct ieee80211_local { | |||
847 | const struct ieee80211_ops *ops; | 823 | const struct ieee80211_ops *ops; |
848 | 824 | ||
849 | /* | 825 | /* |
850 | * work stuff, potentially off-channel (in the future) | ||
851 | */ | ||
852 | struct list_head work_list; | ||
853 | struct timer_list work_timer; | ||
854 | struct work_struct work_work; | ||
855 | |||
856 | /* | ||
857 | * private workqueue to mac80211. mac80211 makes this accessible | 826 | * private workqueue to mac80211. mac80211 makes this accessible |
858 | * via ieee80211_queue_work() | 827 | * via ieee80211_queue_work() |
859 | */ | 828 | */ |
@@ -1087,14 +1056,12 @@ struct ieee80211_local { | |||
1087 | } debugfs; | 1056 | } debugfs; |
1088 | #endif | 1057 | #endif |
1089 | 1058 | ||
1090 | struct ieee80211_channel *hw_roc_channel; | 1059 | /* |
1091 | struct net_device *hw_roc_dev; | 1060 | * Remain-on-channel support |
1092 | struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status; | 1061 | */ |
1062 | struct list_head roc_list; | ||
1093 | struct work_struct hw_roc_start, hw_roc_done; | 1063 | struct work_struct hw_roc_start, hw_roc_done; |
1094 | enum nl80211_channel_type hw_roc_channel_type; | 1064 | unsigned long hw_roc_start_time; |
1095 | unsigned int hw_roc_duration; | ||
1096 | u32 hw_roc_cookie; | ||
1097 | bool hw_roc_for_tx; | ||
1098 | 1065 | ||
1099 | struct idr ack_status_frames; | 1066 | struct idr ack_status_frames; |
1100 | spinlock_t ack_status_lock; | 1067 | spinlock_t ack_status_lock; |
@@ -1290,7 +1257,12 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
1290 | bool offchannel_ps_enable); | 1257 | bool offchannel_ps_enable); |
1291 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1258 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1292 | bool offchannel_ps_disable); | 1259 | bool offchannel_ps_disable); |
1293 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | 1260 | void ieee80211_roc_setup(struct ieee80211_local *local); |
1261 | void ieee80211_start_next_roc(struct ieee80211_local *local); | ||
1262 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); | ||
1263 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); | ||
1264 | void ieee80211_sw_roc_work(struct work_struct *work); | ||
1265 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | ||
1294 | 1266 | ||
1295 | /* interface handling */ | 1267 | /* interface handling */ |
1296 | int ieee80211_iface_init(void); | 1268 | int ieee80211_iface_init(void); |
@@ -1500,18 +1472,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1500 | enum nl80211_channel_type channel_type, | 1472 | enum nl80211_channel_type channel_type, |
1501 | u16 prot_mode); | 1473 | u16 prot_mode); |
1502 | 1474 | ||
1503 | /* internal work items */ | ||
1504 | void ieee80211_work_init(struct ieee80211_local *local); | ||
1505 | void ieee80211_add_work(struct ieee80211_work *wk); | ||
1506 | void free_work(struct ieee80211_work *wk); | ||
1507 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); | ||
1508 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1509 | struct ieee80211_channel *chan, | ||
1510 | enum nl80211_channel_type channel_type, | ||
1511 | unsigned int duration, u64 *cookie); | ||
1512 | int ieee80211_wk_cancel_remain_on_channel( | ||
1513 | struct ieee80211_sub_if_data *sdata, u64 cookie); | ||
1514 | |||
1515 | /* channel management */ | 1475 | /* channel management */ |
1516 | enum ieee80211_chan_mode { | 1476 | enum ieee80211_chan_mode { |
1517 | CHAN_MODE_UNDEFINED, | 1477 | CHAN_MODE_UNDEFINED, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8664111d0566..87aeb4f21ffd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -58,7 +58,7 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
58 | } | 58 | } |
59 | 59 | ||
60 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 60 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
61 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | 61 | pr_debug("%s: setting MTU %d\n", dev->name, new_mtu); |
62 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 62 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
63 | dev->mtu = new_mtu; | 63 | dev->mtu = new_mtu; |
64 | return 0; | 64 | return 0; |
@@ -528,10 +528,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
528 | */ | 528 | */ |
529 | netif_tx_stop_all_queues(sdata->dev); | 529 | netif_tx_stop_all_queues(sdata->dev); |
530 | 530 | ||
531 | /* | 531 | ieee80211_roc_purge(sdata); |
532 | * Purge work for this interface. | ||
533 | */ | ||
534 | ieee80211_work_purge(sdata); | ||
535 | 532 | ||
536 | /* | 533 | /* |
537 | * Remove all stations associated with this interface. | 534 | * Remove all stations associated with this interface. |
@@ -637,18 +634,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
637 | ieee80211_configure_filter(local); | 634 | ieee80211_configure_filter(local); |
638 | break; | 635 | break; |
639 | default: | 636 | default: |
640 | mutex_lock(&local->mtx); | ||
641 | if (local->hw_roc_dev == sdata->dev && | ||
642 | local->hw_roc_channel) { | ||
643 | /* ignore return value since this is racy */ | ||
644 | drv_cancel_remain_on_channel(local); | ||
645 | ieee80211_queue_work(&local->hw, &local->hw_roc_done); | ||
646 | } | ||
647 | mutex_unlock(&local->mtx); | ||
648 | |||
649 | flush_work(&local->hw_roc_start); | ||
650 | flush_work(&local->hw_roc_done); | ||
651 | |||
652 | flush_work(&sdata->work); | 637 | flush_work(&sdata->work); |
653 | /* | 638 | /* |
654 | * When we get here, the interface is marked down. | 639 | * When we get here, the interface is marked down. |
@@ -1238,7 +1223,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1238 | 1223 | ||
1239 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { | 1224 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { |
1240 | /* not a contiguous mask ... not handled now! */ | 1225 | /* not a contiguous mask ... not handled now! */ |
1241 | printk(KERN_DEBUG "not contiguous\n"); | 1226 | pr_debug("not contiguous\n"); |
1242 | break; | 1227 | break; |
1243 | } | 1228 | } |
1244 | 1229 | ||
@@ -1364,6 +1349,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1364 | sdata->u.mgd.use_4addr = params->use_4addr; | 1349 | sdata->u.mgd.use_4addr = params->use_4addr; |
1365 | } | 1350 | } |
1366 | 1351 | ||
1352 | ndev->features |= local->hw.netdev_features; | ||
1353 | |||
1367 | ret = register_netdevice(ndev); | 1354 | ret = register_netdevice(ndev); |
1368 | if (ret) | 1355 | if (ret) |
1369 | goto fail; | 1356 | goto fail; |
@@ -1454,9 +1441,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1454 | { | 1441 | { |
1455 | struct ieee80211_sub_if_data *sdata; | 1442 | struct ieee80211_sub_if_data *sdata; |
1456 | int count = 0; | 1443 | int count = 0; |
1457 | bool working = false, scanning = false, hw_roc = false; | 1444 | bool working = false, scanning = false; |
1458 | struct ieee80211_work *wk; | ||
1459 | unsigned int led_trig_start = 0, led_trig_stop = 0; | 1445 | unsigned int led_trig_start = 0, led_trig_stop = 0; |
1446 | struct ieee80211_roc_work *roc; | ||
1460 | 1447 | ||
1461 | #ifdef CONFIG_PROVE_LOCKING | 1448 | #ifdef CONFIG_PROVE_LOCKING |
1462 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | 1449 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
@@ -1491,9 +1478,11 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1491 | count++; | 1478 | count++; |
1492 | } | 1479 | } |
1493 | 1480 | ||
1494 | list_for_each_entry(wk, &local->work_list, list) { | 1481 | if (!local->ops->remain_on_channel) { |
1495 | working = true; | 1482 | list_for_each_entry(roc, &local->roc_list, list) { |
1496 | wk->sdata->vif.bss_conf.idle = false; | 1483 | working = true; |
1484 | roc->sdata->vif.bss_conf.idle = false; | ||
1485 | } | ||
1497 | } | 1486 | } |
1498 | 1487 | ||
1499 | if (local->scan_sdata && | 1488 | if (local->scan_sdata && |
@@ -1502,9 +1491,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1502 | local->scan_sdata->vif.bss_conf.idle = false; | 1491 | local->scan_sdata->vif.bss_conf.idle = false; |
1503 | } | 1492 | } |
1504 | 1493 | ||
1505 | if (local->hw_roc_channel) | ||
1506 | hw_roc = true; | ||
1507 | |||
1508 | list_for_each_entry(sdata, &local->interfaces, list) { | 1494 | list_for_each_entry(sdata, &local->interfaces, list) { |
1509 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 1495 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
1510 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1496 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -1516,7 +1502,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1516 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | 1502 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); |
1517 | } | 1503 | } |
1518 | 1504 | ||
1519 | if (working || scanning || hw_roc) | 1505 | if (working || scanning) |
1520 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 1506 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
1521 | else | 1507 | else |
1522 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 1508 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
@@ -1528,8 +1514,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1528 | 1514 | ||
1529 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | 1515 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); |
1530 | 1516 | ||
1531 | if (hw_roc) | ||
1532 | return ieee80211_idle_off(local, "hw remain-on-channel"); | ||
1533 | if (working) | 1517 | if (working) |
1534 | return ieee80211_idle_off(local, "working"); | 1518 | return ieee80211_idle_off(local, "working"); |
1535 | if (scanning) | 1519 | if (scanning) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f5548e953259..d81c178c7712 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -625,8 +625,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
625 | 625 | ||
626 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 626 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
627 | 627 | ||
628 | ieee80211_work_init(local); | ||
629 | |||
630 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 628 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
631 | 629 | ||
632 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 630 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
@@ -669,7 +667,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
669 | 667 | ||
670 | ieee80211_led_names(local); | 668 | ieee80211_led_names(local); |
671 | 669 | ||
672 | ieee80211_hw_roc_setup(local); | 670 | ieee80211_roc_setup(local); |
673 | 671 | ||
674 | return &local->hw; | 672 | return &local->hw; |
675 | } | 673 | } |
@@ -682,6 +680,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
682 | enum ieee80211_band band; | 680 | enum ieee80211_band band; |
683 | int channels, max_bitrates; | 681 | int channels, max_bitrates; |
684 | bool supp_ht; | 682 | bool supp_ht; |
683 | netdev_features_t feature_whitelist; | ||
685 | static const u32 cipher_suites[] = { | 684 | static const u32 cipher_suites[] = { |
686 | /* keep WEP first, it may be removed below */ | 685 | /* keep WEP first, it may be removed below */ |
687 | WLAN_CIPHER_SUITE_WEP40, | 686 | WLAN_CIPHER_SUITE_WEP40, |
@@ -708,6 +707,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
708 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) | 707 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) |
709 | return -EINVAL; | 708 | return -EINVAL; |
710 | 709 | ||
710 | /* Only HW csum features are currently compatible with mac80211 */ | ||
711 | feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
712 | NETIF_F_HW_CSUM; | ||
713 | if (WARN_ON(hw->netdev_features & ~feature_whitelist)) | ||
714 | return -EINVAL; | ||
715 | |||
711 | if (hw->max_report_rates == 0) | 716 | if (hw->max_report_rates == 0) |
712 | hw->max_report_rates = hw->max_rates; | 717 | hw->max_report_rates = hw->max_rates; |
713 | 718 | ||
@@ -1009,12 +1014,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1009 | 1014 | ||
1010 | rtnl_unlock(); | 1015 | rtnl_unlock(); |
1011 | 1016 | ||
1012 | /* | ||
1013 | * Now all work items will be gone, but the | ||
1014 | * timer might still be armed, so delete it | ||
1015 | */ | ||
1016 | del_timer_sync(&local->work_timer); | ||
1017 | |||
1018 | cancel_work_sync(&local->restart_work); | 1017 | cancel_work_sync(&local->restart_work); |
1019 | cancel_work_sync(&local->reconfig_filter); | 1018 | cancel_work_sync(&local->reconfig_filter); |
1020 | 1019 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2913113c5833..7cf19509fb68 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -524,8 +524,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
524 | bool free_plinks; | 524 | bool free_plinks; |
525 | 525 | ||
526 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 526 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
527 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 527 | pr_debug("%s: running mesh housekeeping\n", sdata->name); |
528 | sdata->name); | ||
529 | #endif | 528 | #endif |
530 | 529 | ||
531 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 530 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 9b59658e8650..fa7c58035246 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG | 16 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG |
17 | #define mhwmp_dbg(fmt, args...) \ | 17 | #define mhwmp_dbg(fmt, args...) \ |
18 | printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) | 18 | pr_debug("Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) |
19 | #else | 19 | #else |
20 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) | 20 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) |
21 | #endif | 21 | #endif |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index b39224d8255c..572f706fd65b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "mesh.h" | 19 | #include "mesh.h" |
20 | 20 | ||
21 | #ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG | 21 | #ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG |
22 | #define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 22 | #define mpath_dbg(fmt, args...) pr_debug(fmt, ##args) |
23 | #else | 23 | #else |
24 | #define mpath_dbg(fmt, args...) do { (void)(0); } while (0) | 24 | #define mpath_dbg(fmt, args...) do { (void)(0); } while (0) |
25 | #endif | 25 | #endif |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 60ef235c9d9b..be4fad128c34 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 16 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
17 | #define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) | 17 | #define mpl_dbg(fmt, args...) pr_debug(fmt, ##args) |
18 | #else | 18 | #else |
19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) | 19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) |
20 | #endif | 20 | #endif |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 38d30e8ce6dc..0ccdad49f987 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG | 15 | #ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG |
16 | #define msync_dbg(fmt, args...) \ | 16 | #define msync_dbg(fmt, args...) \ |
17 | printk(KERN_DEBUG "Mesh sync (%s): " fmt "\n", sdata->name, ##args) | 17 | pr_debug("Mesh sync (%s): " fmt "\n", sdata->name, ##args) |
18 | #else | 18 | #else |
19 | #define msync_dbg(fmt, args...) do { (void)(0); } while (0) | 19 | #define msync_dbg(fmt, args...) do { (void)(0); } while (0) |
20 | #endif | 20 | #endif |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d94627c2929c..0f45d02e0ba7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -258,12 +258,11 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
258 | } | 258 | } |
259 | 259 | ||
260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
261 | struct sk_buff *skb, const u8 *ht_oper_ie, | 261 | struct sk_buff *skb, u8 ap_ht_param, |
262 | struct ieee80211_supported_band *sband, | 262 | struct ieee80211_supported_band *sband, |
263 | struct ieee80211_channel *channel, | 263 | struct ieee80211_channel *channel, |
264 | enum ieee80211_smps_mode smps) | 264 | enum ieee80211_smps_mode smps) |
265 | { | 265 | { |
266 | struct ieee80211_ht_operation *ht_oper; | ||
267 | u8 *pos; | 266 | u8 *pos; |
268 | u32 flags = channel->flags; | 267 | u32 flags = channel->flags; |
269 | u16 cap; | 268 | u16 cap; |
@@ -271,21 +270,13 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
271 | 270 | ||
272 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | 271 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); |
273 | 272 | ||
274 | if (!ht_oper_ie) | ||
275 | return; | ||
276 | |||
277 | if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation)) | ||
278 | return; | ||
279 | |||
280 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | 273 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); |
281 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | 274 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); |
282 | 275 | ||
283 | ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2); | ||
284 | |||
285 | /* determine capability flags */ | 276 | /* determine capability flags */ |
286 | cap = ht_cap.cap; | 277 | cap = ht_cap.cap; |
287 | 278 | ||
288 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 279 | switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
289 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 280 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
290 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 281 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
291 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 282 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -509,7 +500,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
509 | } | 500 | } |
510 | 501 | ||
511 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 502 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
512 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie, | 503 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
513 | sband, local->oper_channel, ifmgd->ap_smps); | 504 | sband, local->oper_channel, ifmgd->ap_smps); |
514 | 505 | ||
515 | /* if present, add any custom non-vendor IEs that go after HT */ | 506 | /* if present, add any custom non-vendor IEs that go after HT */ |
@@ -939,11 +930,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
939 | return; | 930 | return; |
940 | } | 931 | } |
941 | 932 | ||
942 | if (!list_empty(&local->work_list)) { | ||
943 | local->ps_sdata = NULL; | ||
944 | goto change; | ||
945 | } | ||
946 | |||
947 | list_for_each_entry(sdata, &local->interfaces, list) { | 933 | list_for_each_entry(sdata, &local->interfaces, list) { |
948 | if (!ieee80211_sdata_running(sdata)) | 934 | if (!ieee80211_sdata_running(sdata)) |
949 | continue; | 935 | continue; |
@@ -1016,7 +1002,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1016 | local->ps_sdata = NULL; | 1002 | local->ps_sdata = NULL; |
1017 | } | 1003 | } |
1018 | 1004 | ||
1019 | change: | ||
1020 | ieee80211_change_ps(local); | 1005 | ieee80211_change_ps(local); |
1021 | } | 1006 | } |
1022 | 1007 | ||
@@ -1585,6 +1570,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1585 | net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n", | 1570 | net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n", |
1586 | sdata->name); | 1571 | sdata->name); |
1587 | #endif | 1572 | #endif |
1573 | ieee80211_cqm_rssi_notify(&sdata->vif, | ||
1574 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); | ||
1588 | 1575 | ||
1589 | /* | 1576 | /* |
1590 | * The driver/our work has already reported this event or the | 1577 | * The driver/our work has already reported this event or the |
@@ -1667,8 +1654,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1667 | 1654 | ||
1668 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1655 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1669 | 1656 | ||
1670 | printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", | 1657 | pr_debug("%s: Connection to AP %pM lost\n", sdata->name, bssid); |
1671 | sdata->name, bssid); | ||
1672 | 1658 | ||
1673 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 1659 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
1674 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1660 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
@@ -1802,9 +1788,10 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1802 | return RX_MGMT_NONE; | 1788 | return RX_MGMT_NONE; |
1803 | 1789 | ||
1804 | if (status_code != WLAN_STATUS_SUCCESS) { | 1790 | if (status_code != WLAN_STATUS_SUCCESS) { |
1805 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | 1791 | pr_debug("%s: %pM denied authentication (status %d)\n", |
1806 | sdata->name, mgmt->sa, status_code); | 1792 | sdata->name, mgmt->sa, status_code); |
1807 | goto out; | 1793 | ieee80211_destroy_auth_data(sdata, false); |
1794 | return RX_MGMT_CFG80211_RX_AUTH; | ||
1808 | } | 1795 | } |
1809 | 1796 | ||
1810 | switch (ifmgd->auth_data->algorithm) { | 1797 | switch (ifmgd->auth_data->algorithm) { |
@@ -1825,8 +1812,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1825 | return RX_MGMT_NONE; | 1812 | return RX_MGMT_NONE; |
1826 | } | 1813 | } |
1827 | 1814 | ||
1828 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | 1815 | pr_debug("%s: authenticated\n", sdata->name); |
1829 | out: | ||
1830 | ifmgd->auth_data->done = true; | 1816 | ifmgd->auth_data->done = true; |
1831 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | 1817 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; |
1832 | run_again(ifmgd, ifmgd->auth_data->timeout); | 1818 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -1839,8 +1825,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1839 | goto out_err; | 1825 | goto out_err; |
1840 | } | 1826 | } |
1841 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { | 1827 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { |
1842 | printk(KERN_DEBUG "%s: failed moving %pM to auth\n", | 1828 | pr_debug("%s: failed moving %pM to auth\n", sdata->name, bssid); |
1843 | sdata->name, bssid); | ||
1844 | goto out_err; | 1829 | goto out_err; |
1845 | } | 1830 | } |
1846 | mutex_unlock(&sdata->local->sta_mtx); | 1831 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -1874,8 +1859,8 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1874 | 1859 | ||
1875 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1860 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1876 | 1861 | ||
1877 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1862 | pr_debug("%s: deauthenticated from %pM (Reason: %u)\n", |
1878 | sdata->name, bssid, reason_code); | 1863 | sdata->name, bssid, reason_code); |
1879 | 1864 | ||
1880 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1865 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1881 | 1866 | ||
@@ -1905,8 +1890,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1905 | 1890 | ||
1906 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1891 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1907 | 1892 | ||
1908 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1893 | pr_debug("%s: disassociated from %pM (Reason: %u)\n", |
1909 | sdata->name, mgmt->sa, reason_code); | 1894 | sdata->name, mgmt->sa, reason_code); |
1910 | 1895 | ||
1911 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1896 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1912 | 1897 | ||
@@ -1998,17 +1983,15 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
1998 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | 1983 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
1999 | 1984 | ||
2000 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1985 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
2001 | printk(KERN_DEBUG | 1986 | pr_debug("%s: invalid AID value 0x%x; bits 15:14 not set\n", |
2002 | "%s: invalid AID value 0x%x; bits 15:14 not set\n", | 1987 | sdata->name, aid); |
2003 | sdata->name, aid); | ||
2004 | aid &= ~(BIT(15) | BIT(14)); | 1988 | aid &= ~(BIT(15) | BIT(14)); |
2005 | 1989 | ||
2006 | ifmgd->broken_ap = false; | 1990 | ifmgd->broken_ap = false; |
2007 | 1991 | ||
2008 | if (aid == 0 || aid > IEEE80211_MAX_AID) { | 1992 | if (aid == 0 || aid > IEEE80211_MAX_AID) { |
2009 | printk(KERN_DEBUG | 1993 | pr_debug("%s: invalid AID value %d (out of range), turn off PS\n", |
2010 | "%s: invalid AID value %d (out of range), turn off PS\n", | 1994 | sdata->name, aid); |
2011 | sdata->name, aid); | ||
2012 | aid = 0; | 1995 | aid = 0; |
2013 | ifmgd->broken_ap = true; | 1996 | ifmgd->broken_ap = true; |
2014 | } | 1997 | } |
@@ -2017,8 +2000,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2017 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2000 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
2018 | 2001 | ||
2019 | if (!elems.supp_rates) { | 2002 | if (!elems.supp_rates) { |
2020 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 2003 | pr_debug("%s: no SuppRates element in AssocResp\n", |
2021 | sdata->name); | 2004 | sdata->name); |
2022 | return false; | 2005 | return false; |
2023 | } | 2006 | } |
2024 | 2007 | ||
@@ -2058,9 +2041,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2058 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 2041 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
2059 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 2042 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
2060 | if (err) { | 2043 | if (err) { |
2061 | printk(KERN_DEBUG | 2044 | pr_debug("%s: failed to move station %pM to desired state\n", |
2062 | "%s: failed to move station %pM to desired state\n", | 2045 | sdata->name, sta->sta.addr); |
2063 | sdata->name, sta->sta.addr); | ||
2064 | WARN_ON(__sta_info_destroy(sta)); | 2046 | WARN_ON(__sta_info_destroy(sta)); |
2065 | mutex_unlock(&sdata->local->sta_mtx); | 2047 | mutex_unlock(&sdata->local->sta_mtx); |
2066 | return false; | 2048 | return false; |
@@ -2143,10 +2125,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2143 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 2125 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2144 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 2126 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
2145 | 2127 | ||
2146 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | 2128 | pr_debug("%s: RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n", |
2147 | "status=%d aid=%d)\n", | 2129 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, |
2148 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | 2130 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
2149 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
2150 | 2131 | ||
2151 | pos = mgmt->u.assoc_resp.variable; | 2132 | pos = mgmt->u.assoc_resp.variable; |
2152 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2133 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
@@ -2157,9 +2138,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2157 | u32 tu, ms; | 2138 | u32 tu, ms; |
2158 | tu = get_unaligned_le32(elems.timeout_int + 1); | 2139 | tu = get_unaligned_le32(elems.timeout_int + 1); |
2159 | ms = tu * 1024 / 1000; | 2140 | ms = tu * 1024 / 1000; |
2160 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | 2141 | pr_debug("%s: %pM rejected association temporarily; comeback duration %u TU (%u ms)\n", |
2161 | "comeback duration %u TU (%u ms)\n", | 2142 | sdata->name, mgmt->sa, tu, ms); |
2162 | sdata->name, mgmt->sa, tu, ms); | ||
2163 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); | 2143 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); |
2164 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 2144 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
2165 | run_again(ifmgd, assoc_data->timeout); | 2145 | run_again(ifmgd, assoc_data->timeout); |
@@ -2169,11 +2149,11 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2169 | *bss = assoc_data->bss; | 2149 | *bss = assoc_data->bss; |
2170 | 2150 | ||
2171 | if (status_code != WLAN_STATUS_SUCCESS) { | 2151 | if (status_code != WLAN_STATUS_SUCCESS) { |
2172 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | 2152 | pr_debug("%s: %pM denied association (code=%d)\n", |
2173 | sdata->name, mgmt->sa, status_code); | 2153 | sdata->name, mgmt->sa, status_code); |
2174 | ieee80211_destroy_assoc_data(sdata, false); | 2154 | ieee80211_destroy_assoc_data(sdata, false); |
2175 | } else { | 2155 | } else { |
2176 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | 2156 | pr_debug("%s: associated\n", sdata->name); |
2177 | 2157 | ||
2178 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | 2158 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { |
2179 | /* oops -- internal error -- send timeout for now */ | 2159 | /* oops -- internal error -- send timeout for now */ |
@@ -2281,7 +2261,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2281 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | 2261 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && |
2282 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { | 2262 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { |
2283 | /* got probe response, continue with auth */ | 2263 | /* got probe response, continue with auth */ |
2284 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | 2264 | pr_debug("%s: direct probe responded\n", sdata->name); |
2285 | ifmgd->auth_data->tries = 0; | 2265 | ifmgd->auth_data->tries = 0; |
2286 | ifmgd->auth_data->timeout = jiffies; | 2266 | ifmgd->auth_data->timeout = jiffies; |
2287 | run_again(ifmgd, ifmgd->auth_data->timeout); | 2267 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -2645,8 +2625,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2645 | auth_data->tries++; | 2625 | auth_data->tries++; |
2646 | 2626 | ||
2647 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 2627 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
2648 | printk(KERN_DEBUG "%s: authentication with %pM timed out\n", | 2628 | pr_debug("%s: authentication with %pM timed out\n", |
2649 | sdata->name, auth_data->bss->bssid); | 2629 | sdata->name, auth_data->bss->bssid); |
2650 | 2630 | ||
2651 | /* | 2631 | /* |
2652 | * Most likely AP is not in the range so remove the | 2632 | * Most likely AP is not in the range so remove the |
@@ -2658,9 +2638,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2658 | } | 2638 | } |
2659 | 2639 | ||
2660 | if (auth_data->bss->proberesp_ies) { | 2640 | if (auth_data->bss->proberesp_ies) { |
2661 | printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n", | 2641 | pr_debug("%s: send auth to %pM (try %d/%d)\n", |
2662 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2642 | sdata->name, auth_data->bss->bssid, auth_data->tries, |
2663 | IEEE80211_AUTH_MAX_TRIES); | 2643 | IEEE80211_AUTH_MAX_TRIES); |
2664 | 2644 | ||
2665 | auth_data->expected_transaction = 2; | 2645 | auth_data->expected_transaction = 2; |
2666 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, | 2646 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, |
@@ -2670,9 +2650,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2670 | } else { | 2650 | } else { |
2671 | const u8 *ssidie; | 2651 | const u8 *ssidie; |
2672 | 2652 | ||
2673 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", | 2653 | pr_debug("%s: direct probe to %pM (try %d/%i)\n", |
2674 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2654 | sdata->name, auth_data->bss->bssid, auth_data->tries, |
2675 | IEEE80211_AUTH_MAX_TRIES); | 2655 | IEEE80211_AUTH_MAX_TRIES); |
2676 | 2656 | ||
2677 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | 2657 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); |
2678 | if (!ssidie) | 2658 | if (!ssidie) |
@@ -2700,8 +2680,8 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2700 | 2680 | ||
2701 | assoc_data->tries++; | 2681 | assoc_data->tries++; |
2702 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { | 2682 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { |
2703 | printk(KERN_DEBUG "%s: association with %pM timed out\n", | 2683 | pr_debug("%s: association with %pM timed out\n", |
2704 | sdata->name, assoc_data->bss->bssid); | 2684 | sdata->name, assoc_data->bss->bssid); |
2705 | 2685 | ||
2706 | /* | 2686 | /* |
2707 | * Most likely AP is not in the range so remove the | 2687 | * Most likely AP is not in the range so remove the |
@@ -2712,9 +2692,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2712 | return -ETIMEDOUT; | 2692 | return -ETIMEDOUT; |
2713 | } | 2693 | } |
2714 | 2694 | ||
2715 | printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n", | 2695 | pr_debug("%s: associate with %pM (try %d/%d)\n", |
2716 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, | 2696 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, |
2717 | IEEE80211_ASSOC_MAX_TRIES); | 2697 | IEEE80211_ASSOC_MAX_TRIES); |
2718 | ieee80211_send_assoc(sdata); | 2698 | ieee80211_send_assoc(sdata); |
2719 | 2699 | ||
2720 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 2700 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
@@ -3085,13 +3065,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3085 | * since we look at probe response/beacon data here | 3065 | * since we look at probe response/beacon data here |
3086 | * it should be OK. | 3066 | * it should be OK. |
3087 | */ | 3067 | */ |
3088 | printk(KERN_DEBUG | 3068 | pr_debug("%s: Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", |
3089 | "%s: Wrong control channel: center-freq: %d" | 3069 | sdata->name, cbss->channel->center_freq, |
3090 | " ht-cfreq: %d ht->primary_chan: %d" | 3070 | ht_cfreq, ht_oper->primary_chan, |
3091 | " band: %d. Disabling HT.\n", | 3071 | cbss->channel->band); |
3092 | sdata->name, cbss->channel->center_freq, | ||
3093 | ht_cfreq, ht_oper->primary_chan, | ||
3094 | cbss->channel->band); | ||
3095 | ht_oper = NULL; | 3072 | ht_oper = NULL; |
3096 | } | 3073 | } |
3097 | } | 3074 | } |
@@ -3115,9 +3092,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3115 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 3092 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
3116 | /* can only fail due to HT40+/- mismatch */ | 3093 | /* can only fail due to HT40+/- mismatch */ |
3117 | channel_type = NL80211_CHAN_HT20; | 3094 | channel_type = NL80211_CHAN_HT20; |
3118 | printk(KERN_DEBUG | 3095 | pr_debug("%s: disabling 40 MHz due to multi-vif mismatch\n", |
3119 | "%s: disabling 40 MHz due to multi-vif mismatch\n", | 3096 | sdata->name); |
3120 | sdata->name); | ||
3121 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3097 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; |
3122 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | 3098 | WARN_ON(!ieee80211_set_channel_type(local, sdata, |
3123 | channel_type)); | 3099 | channel_type)); |
@@ -3146,9 +3122,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3146 | * we can connect -- with a warning. | 3122 | * we can connect -- with a warning. |
3147 | */ | 3123 | */ |
3148 | if (!basic_rates && min_rate_index >= 0) { | 3124 | if (!basic_rates && min_rate_index >= 0) { |
3149 | printk(KERN_DEBUG | 3125 | pr_debug("%s: No basic rates, using min rate instead\n", |
3150 | "%s: No basic rates, using min rate instead.\n", | 3126 | sdata->name); |
3151 | sdata->name); | ||
3152 | basic_rates = BIT(min_rate_index); | 3127 | basic_rates = BIT(min_rate_index); |
3153 | } | 3128 | } |
3154 | 3129 | ||
@@ -3174,9 +3149,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3174 | err = sta_info_insert(sta); | 3149 | err = sta_info_insert(sta); |
3175 | sta = NULL; | 3150 | sta = NULL; |
3176 | if (err) { | 3151 | if (err) { |
3177 | printk(KERN_DEBUG | 3152 | pr_debug("%s: failed to insert STA entry for the AP (error %d)\n", |
3178 | "%s: failed to insert STA entry for the AP (error %d)\n", | 3153 | sdata->name, err); |
3179 | sdata->name, err); | ||
3180 | return err; | 3154 | return err; |
3181 | } | 3155 | } |
3182 | } else | 3156 | } else |
@@ -3254,8 +3228,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3254 | if (ifmgd->associated) | 3228 | if (ifmgd->associated) |
3255 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 3229 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
3256 | 3230 | ||
3257 | printk(KERN_DEBUG "%s: authenticate with %pM\n", | 3231 | pr_debug("%s: authenticate with %pM\n", sdata->name, req->bss->bssid); |
3258 | sdata->name, req->bss->bssid); | ||
3259 | 3232 | ||
3260 | err = ieee80211_prep_connection(sdata, req->bss, false); | 3233 | err = ieee80211_prep_connection(sdata, req->bss, false); |
3261 | if (err) | 3234 | if (err) |
@@ -3290,7 +3263,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3290 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3263 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
3291 | struct ieee80211_mgd_assoc_data *assoc_data; | 3264 | struct ieee80211_mgd_assoc_data *assoc_data; |
3292 | struct ieee80211_supported_band *sband; | 3265 | struct ieee80211_supported_band *sband; |
3293 | const u8 *ssidie; | 3266 | const u8 *ssidie, *ht_ie; |
3294 | int i, err; | 3267 | int i, err; |
3295 | 3268 | ||
3296 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 3269 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
@@ -3338,11 +3311,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3338 | * We can set this to true for non-11n hardware, that'll be checked | 3311 | * We can set this to true for non-11n hardware, that'll be checked |
3339 | * separately along with the peer capabilities. | 3312 | * separately along with the peer capabilities. |
3340 | */ | 3313 | */ |
3341 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 3314 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { |
3342 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3315 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3343 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3316 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3344 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 3317 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3345 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3318 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3319 | netdev_info(sdata->dev, | ||
3320 | "disabling HT due to WEP/TKIP use\n"); | ||
3321 | } | ||
3322 | } | ||
3346 | 3323 | ||
3347 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3324 | if (req->flags & ASSOC_REQ_DISABLE_HT) |
3348 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3325 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
@@ -3350,8 +3327,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3350 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3327 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3351 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3328 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3352 | if (!sband->ht_cap.ht_supported || | 3329 | if (!sband->ht_cap.ht_supported || |
3353 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) | 3330 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3354 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3331 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3332 | netdev_info(sdata->dev, | ||
3333 | "disabling HT as WMM/QoS is not supported\n"); | ||
3334 | } | ||
3355 | 3335 | ||
3356 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3336 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
3357 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 3337 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
@@ -3377,8 +3357,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3377 | (local->hw.queues >= IEEE80211_NUM_ACS); | 3357 | (local->hw.queues >= IEEE80211_NUM_ACS); |
3378 | assoc_data->supp_rates = bss->supp_rates; | 3358 | assoc_data->supp_rates = bss->supp_rates; |
3379 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3359 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3380 | assoc_data->ht_operation_ie = | 3360 | |
3381 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); | 3361 | ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); |
3362 | if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) | ||
3363 | assoc_data->ap_ht_param = | ||
3364 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | ||
3365 | else | ||
3366 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
3382 | 3367 | ||
3383 | if (bss->wmm_used && bss->uapsd_supported && | 3368 | if (bss->wmm_used && bss->uapsd_supported && |
3384 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3369 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3425,8 +3410,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3425 | * Wait up to one beacon interval ... | 3410 | * Wait up to one beacon interval ... |
3426 | * should this be more if we miss one? | 3411 | * should this be more if we miss one? |
3427 | */ | 3412 | */ |
3428 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | 3413 | pr_debug("%s: waiting for beacon from %pM\n", |
3429 | sdata->name, ifmgd->bssid); | 3414 | sdata->name, ifmgd->bssid); |
3430 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); | 3415 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); |
3431 | } else { | 3416 | } else { |
3432 | assoc_data->have_beacon = true; | 3417 | assoc_data->have_beacon = true; |
@@ -3445,8 +3430,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3445 | corrupt_type = "beacon"; | 3430 | corrupt_type = "beacon"; |
3446 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) | 3431 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) |
3447 | corrupt_type = "probe response"; | 3432 | corrupt_type = "probe response"; |
3448 | printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n", | 3433 | pr_debug("%s: associating with AP with corrupt %s\n", |
3449 | sdata->name, corrupt_type); | 3434 | sdata->name, corrupt_type); |
3450 | } | 3435 | } |
3451 | 3436 | ||
3452 | err = 0; | 3437 | err = 0; |
@@ -3475,9 +3460,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3475 | return 0; | 3460 | return 0; |
3476 | } | 3461 | } |
3477 | 3462 | ||
3478 | printk(KERN_DEBUG | 3463 | pr_debug("%s: deauthenticating from %pM by local choice (reason=%d)\n", |
3479 | "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 3464 | sdata->name, req->bssid, req->reason_code); |
3480 | sdata->name, req->bssid, req->reason_code); | ||
3481 | 3465 | ||
3482 | if (ifmgd->associated && | 3466 | if (ifmgd->associated && |
3483 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) | 3467 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) |
@@ -3519,8 +3503,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3519 | return -ENOLINK; | 3503 | return -ENOLINK; |
3520 | } | 3504 | } |
3521 | 3505 | ||
3522 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 3506 | pr_debug("%s: disassociating from %pM by local choice (reason=%d)\n", |
3523 | sdata->name, req->bss->bssid, req->reason_code); | 3507 | sdata->name, req->bss->bssid, req->reason_code); |
3524 | 3508 | ||
3525 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 3509 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
3526 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, | 3510 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, |
@@ -3561,10 +3545,3 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
3561 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 3545 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
3562 | } | 3546 | } |
3563 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 3547 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
3564 | |||
3565 | unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif) | ||
3566 | { | ||
3567 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
3568 | return sdata->dev->operstate; | ||
3569 | } | ||
3570 | EXPORT_SYMBOL(ieee80211_get_operstate); | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 935aa4b6deee..abb226dc4753 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
17 | #include "ieee80211_i.h" | 17 | #include "ieee80211_i.h" |
18 | #include "driver-trace.h" | 18 | #include "driver-trace.h" |
19 | #include "driver-ops.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Tell our hardware to disable PS. | 22 | * Tell our hardware to disable PS. |
@@ -181,34 +182,58 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
181 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&local->iflist_mtx); |
182 | } | 183 | } |
183 | 184 | ||
185 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | ||
186 | { | ||
187 | if (roc->notified) | ||
188 | return; | ||
189 | |||
190 | if (roc->mgmt_tx_cookie) { | ||
191 | if (!WARN_ON(!roc->frame)) { | ||
192 | ieee80211_tx_skb(roc->sdata, roc->frame); | ||
193 | roc->frame = NULL; | ||
194 | } | ||
195 | } else { | ||
196 | cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc, | ||
197 | roc->chan, roc->chan_type, | ||
198 | roc->req_duration, GFP_KERNEL); | ||
199 | } | ||
200 | |||
201 | roc->notified = true; | ||
202 | } | ||
203 | |||
184 | static void ieee80211_hw_roc_start(struct work_struct *work) | 204 | static void ieee80211_hw_roc_start(struct work_struct *work) |
185 | { | 205 | { |
186 | struct ieee80211_local *local = | 206 | struct ieee80211_local *local = |
187 | container_of(work, struct ieee80211_local, hw_roc_start); | 207 | container_of(work, struct ieee80211_local, hw_roc_start); |
188 | struct ieee80211_sub_if_data *sdata; | 208 | struct ieee80211_roc_work *roc, *dep, *tmp; |
189 | 209 | ||
190 | mutex_lock(&local->mtx); | 210 | mutex_lock(&local->mtx); |
191 | 211 | ||
192 | if (!local->hw_roc_channel) { | 212 | if (list_empty(&local->roc_list)) |
193 | mutex_unlock(&local->mtx); | 213 | goto out_unlock; |
194 | return; | ||
195 | } | ||
196 | 214 | ||
197 | if (local->hw_roc_skb) { | 215 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
198 | sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); | 216 | list); |
199 | ieee80211_tx_skb(sdata, local->hw_roc_skb); | 217 | |
200 | local->hw_roc_skb = NULL; | 218 | if (!roc->started) |
201 | } else { | 219 | goto out_unlock; |
202 | cfg80211_ready_on_channel(local->hw_roc_dev, | ||
203 | local->hw_roc_cookie, | ||
204 | local->hw_roc_channel, | ||
205 | local->hw_roc_channel_type, | ||
206 | local->hw_roc_duration, | ||
207 | GFP_KERNEL); | ||
208 | } | ||
209 | 220 | ||
210 | ieee80211_recalc_idle(local); | 221 | roc->hw_begun = true; |
222 | roc->hw_start_time = local->hw_roc_start_time; | ||
211 | 223 | ||
224 | ieee80211_handle_roc_started(roc); | ||
225 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) { | ||
226 | ieee80211_handle_roc_started(dep); | ||
227 | |||
228 | if (dep->duration > roc->duration) { | ||
229 | u32 dur = dep->duration; | ||
230 | dep->duration = dur - roc->duration; | ||
231 | roc->duration = dur; | ||
232 | list_del(&dep->list); | ||
233 | list_add(&dep->list, &roc->list); | ||
234 | } | ||
235 | } | ||
236 | out_unlock: | ||
212 | mutex_unlock(&local->mtx); | 237 | mutex_unlock(&local->mtx); |
213 | } | 238 | } |
214 | 239 | ||
@@ -216,52 +241,179 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw) | |||
216 | { | 241 | { |
217 | struct ieee80211_local *local = hw_to_local(hw); | 242 | struct ieee80211_local *local = hw_to_local(hw); |
218 | 243 | ||
244 | local->hw_roc_start_time = jiffies; | ||
245 | |||
219 | trace_api_ready_on_channel(local); | 246 | trace_api_ready_on_channel(local); |
220 | 247 | ||
221 | ieee80211_queue_work(hw, &local->hw_roc_start); | 248 | ieee80211_queue_work(hw, &local->hw_roc_start); |
222 | } | 249 | } |
223 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); | 250 | EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); |
224 | 251 | ||
225 | static void ieee80211_hw_roc_done(struct work_struct *work) | 252 | void ieee80211_start_next_roc(struct ieee80211_local *local) |
226 | { | 253 | { |
227 | struct ieee80211_local *local = | 254 | struct ieee80211_roc_work *roc; |
228 | container_of(work, struct ieee80211_local, hw_roc_done); | ||
229 | 255 | ||
230 | mutex_lock(&local->mtx); | 256 | lockdep_assert_held(&local->mtx); |
231 | 257 | ||
232 | if (!local->hw_roc_channel) { | 258 | if (list_empty(&local->roc_list)) { |
233 | mutex_unlock(&local->mtx); | 259 | ieee80211_run_deferred_scan(local); |
234 | return; | 260 | return; |
235 | } | 261 | } |
236 | 262 | ||
237 | /* was never transmitted */ | 263 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, |
238 | if (local->hw_roc_skb) { | 264 | list); |
239 | u64 cookie; | ||
240 | 265 | ||
241 | cookie = local->hw_roc_cookie ^ 2; | 266 | if (local->ops->remain_on_channel) { |
267 | int ret, duration = roc->duration; | ||
242 | 268 | ||
243 | cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, | 269 | /* XXX: duplicated, see ieee80211_start_roc_work() */ |
244 | local->hw_roc_skb->data, | 270 | if (!duration) |
245 | local->hw_roc_skb->len, false, | 271 | duration = 10; |
246 | GFP_KERNEL); | ||
247 | 272 | ||
248 | kfree_skb(local->hw_roc_skb); | 273 | ret = drv_remain_on_channel(local, roc->chan, |
249 | local->hw_roc_skb = NULL; | 274 | roc->chan_type, |
250 | local->hw_roc_skb_for_status = NULL; | 275 | duration); |
276 | |||
277 | roc->started = true; | ||
278 | |||
279 | if (ret) { | ||
280 | wiphy_warn(local->hw.wiphy, | ||
281 | "failed to start next HW ROC (%d)\n", ret); | ||
282 | /* | ||
283 | * queue the work struct again to avoid recursion | ||
284 | * when multiple failures occur | ||
285 | */ | ||
286 | ieee80211_remain_on_channel_expired(&local->hw); | ||
287 | } | ||
288 | } else { | ||
289 | /* delay it a bit */ | ||
290 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | ||
291 | round_jiffies_relative(HZ/2)); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | ||
296 | { | ||
297 | struct ieee80211_roc_work *dep, *tmp; | ||
298 | |||
299 | /* was never transmitted */ | ||
300 | if (roc->frame) { | ||
301 | cfg80211_mgmt_tx_status(roc->sdata->dev, | ||
302 | (unsigned long)roc->frame, | ||
303 | roc->frame->data, roc->frame->len, | ||
304 | false, GFP_KERNEL); | ||
305 | kfree_skb(roc->frame); | ||
251 | } | 306 | } |
252 | 307 | ||
253 | if (!local->hw_roc_for_tx) | 308 | if (!roc->mgmt_tx_cookie) |
254 | cfg80211_remain_on_channel_expired(local->hw_roc_dev, | 309 | cfg80211_remain_on_channel_expired(roc->sdata->dev, |
255 | local->hw_roc_cookie, | 310 | (unsigned long)roc, |
256 | local->hw_roc_channel, | 311 | roc->chan, roc->chan_type, |
257 | local->hw_roc_channel_type, | ||
258 | GFP_KERNEL); | 312 | GFP_KERNEL); |
259 | 313 | ||
260 | local->hw_roc_channel = NULL; | 314 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
261 | local->hw_roc_cookie = 0; | 315 | ieee80211_roc_notify_destroy(dep); |
316 | |||
317 | kfree(roc); | ||
318 | } | ||
319 | |||
320 | void ieee80211_sw_roc_work(struct work_struct *work) | ||
321 | { | ||
322 | struct ieee80211_roc_work *roc = | ||
323 | container_of(work, struct ieee80211_roc_work, work.work); | ||
324 | struct ieee80211_sub_if_data *sdata = roc->sdata; | ||
325 | struct ieee80211_local *local = sdata->local; | ||
326 | |||
327 | mutex_lock(&local->mtx); | ||
328 | |||
329 | if (roc->abort) | ||
330 | goto finish; | ||
331 | |||
332 | if (WARN_ON(list_empty(&local->roc_list))) | ||
333 | goto out_unlock; | ||
334 | |||
335 | if (WARN_ON(roc != list_first_entry(&local->roc_list, | ||
336 | struct ieee80211_roc_work, | ||
337 | list))) | ||
338 | goto out_unlock; | ||
339 | |||
340 | if (!roc->started) { | ||
341 | struct ieee80211_roc_work *dep; | ||
342 | |||
343 | /* start this ROC */ | ||
262 | 344 | ||
263 | ieee80211_recalc_idle(local); | 345 | /* switch channel etc */ |
346 | ieee80211_recalc_idle(local); | ||
264 | 347 | ||
348 | local->tmp_channel = roc->chan; | ||
349 | local->tmp_channel_type = roc->chan_type; | ||
350 | ieee80211_hw_config(local, 0); | ||
351 | |||
352 | /* tell userspace or send frame */ | ||
353 | ieee80211_handle_roc_started(roc); | ||
354 | list_for_each_entry(dep, &roc->dependents, list) | ||
355 | ieee80211_handle_roc_started(dep); | ||
356 | |||
357 | /* if it was pure TX, just finish right away */ | ||
358 | if (!roc->duration) | ||
359 | goto finish; | ||
360 | |||
361 | roc->started = true; | ||
362 | ieee80211_queue_delayed_work(&local->hw, &roc->work, | ||
363 | msecs_to_jiffies(roc->duration)); | ||
364 | } else { | ||
365 | /* finish this ROC */ | ||
366 | finish: | ||
367 | list_del(&roc->list); | ||
368 | ieee80211_roc_notify_destroy(roc); | ||
369 | |||
370 | if (roc->started) { | ||
371 | drv_flush(local, false); | ||
372 | |||
373 | local->tmp_channel = NULL; | ||
374 | ieee80211_hw_config(local, 0); | ||
375 | |||
376 | ieee80211_offchannel_return(local, true); | ||
377 | } | ||
378 | |||
379 | ieee80211_recalc_idle(local); | ||
380 | |||
381 | ieee80211_start_next_roc(local); | ||
382 | ieee80211_run_deferred_scan(local); | ||
383 | } | ||
384 | |||
385 | out_unlock: | ||
386 | mutex_unlock(&local->mtx); | ||
387 | } | ||
388 | |||
389 | static void ieee80211_hw_roc_done(struct work_struct *work) | ||
390 | { | ||
391 | struct ieee80211_local *local = | ||
392 | container_of(work, struct ieee80211_local, hw_roc_done); | ||
393 | struct ieee80211_roc_work *roc; | ||
394 | |||
395 | mutex_lock(&local->mtx); | ||
396 | |||
397 | if (list_empty(&local->roc_list)) | ||
398 | goto out_unlock; | ||
399 | |||
400 | roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, | ||
401 | list); | ||
402 | |||
403 | if (!roc->started) | ||
404 | goto out_unlock; | ||
405 | |||
406 | list_del(&roc->list); | ||
407 | |||
408 | ieee80211_roc_notify_destroy(roc); | ||
409 | |||
410 | /* if there's another roc, start it now */ | ||
411 | ieee80211_start_next_roc(local); | ||
412 | |||
413 | /* or scan maybe */ | ||
414 | ieee80211_run_deferred_scan(local); | ||
415 | |||
416 | out_unlock: | ||
265 | mutex_unlock(&local->mtx); | 417 | mutex_unlock(&local->mtx); |
266 | } | 418 | } |
267 | 419 | ||
@@ -275,8 +427,48 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) | |||
275 | } | 427 | } |
276 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); | 428 | EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); |
277 | 429 | ||
278 | void ieee80211_hw_roc_setup(struct ieee80211_local *local) | 430 | void ieee80211_roc_setup(struct ieee80211_local *local) |
279 | { | 431 | { |
280 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); | 432 | INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); |
281 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); | 433 | INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); |
434 | INIT_LIST_HEAD(&local->roc_list); | ||
435 | } | ||
436 | |||
437 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) | ||
438 | { | ||
439 | struct ieee80211_local *local = sdata->local; | ||
440 | struct ieee80211_roc_work *roc, *tmp; | ||
441 | LIST_HEAD(tmp_list); | ||
442 | |||
443 | mutex_lock(&local->mtx); | ||
444 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | ||
445 | if (roc->sdata != sdata) | ||
446 | continue; | ||
447 | |||
448 | if (roc->started && local->ops->remain_on_channel) { | ||
449 | /* can race, so ignore return value */ | ||
450 | drv_cancel_remain_on_channel(local); | ||
451 | } | ||
452 | |||
453 | list_move_tail(&roc->list, &tmp_list); | ||
454 | roc->abort = true; | ||
455 | } | ||
456 | |||
457 | ieee80211_start_next_roc(local); | ||
458 | ieee80211_run_deferred_scan(local); | ||
459 | mutex_unlock(&local->mtx); | ||
460 | |||
461 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | ||
462 | if (local->ops->remain_on_channel) { | ||
463 | list_del(&roc->list); | ||
464 | ieee80211_roc_notify_destroy(roc); | ||
465 | } else { | ||
466 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | ||
467 | |||
468 | /* work will clean up etc */ | ||
469 | flush_delayed_work(&roc->work); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | WARN_ON_ONCE(!list_empty(&tmp_list)); | ||
282 | } | 474 | } |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index af1c4e26e965..98c128be3827 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -77,6 +77,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
77 | int err = drv_suspend(local, wowlan); | 77 | int err = drv_suspend(local, wowlan); |
78 | if (err < 0) { | 78 | if (err < 0) { |
79 | local->quiescing = false; | 79 | local->quiescing = false; |
80 | local->wowlan = false; | ||
80 | return err; | 81 | return err; |
81 | } else if (err > 0) { | 82 | } else if (err > 0) { |
82 | WARN_ON(err != 1); | 83 | WARN_ON(err != 1); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7bcecf73aafb..6fd2cb0838c4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1137,22 +1137,22 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1137 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1137 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1138 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1138 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1139 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1139 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1140 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1140 | pr_debug("%s: STA %pM aid %d enters power save mode\n", |
1141 | sdata->name, sta->sta.addr, sta->sta.aid); | 1141 | sdata->name, sta->sta.addr, sta->sta.aid); |
1142 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1142 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static void ap_sta_ps_end(struct sta_info *sta) | 1145 | static void ap_sta_ps_end(struct sta_info *sta) |
1146 | { | 1146 | { |
1147 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1147 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1148 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1148 | pr_debug("%s: STA %pM aid %d exits power save mode\n", |
1149 | sta->sdata->name, sta->sta.addr, sta->sta.aid); | 1149 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1150 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1150 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1151 | 1151 | ||
1152 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 1152 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
1153 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1153 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1154 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1154 | pr_debug("%s: STA %pM aid %d driver-ps-blocked\n", |
1155 | sta->sdata->name, sta->sta.addr, sta->sta.aid); | 1155 | sta->sdata->name, sta->sta.addr, sta->sta.aid); |
1156 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1156 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1157 | return; | 1157 | return; |
1158 | } | 1158 | } |
@@ -1387,12 +1387,10 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1388 | struct ieee80211_hdr *hdr = | 1388 | struct ieee80211_hdr *hdr = |
1389 | (struct ieee80211_hdr *) entry->skb_list.next->data; | 1389 | (struct ieee80211_hdr *) entry->skb_list.next->data; |
1390 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " | 1390 | pr_debug("%s: RX reassembly removed oldest fragment entry (idx=%d age=%lu seq=%d last_frag=%d addr1=%pM addr2=%pM\n", |
1391 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " | 1391 | sdata->name, idx, |
1392 | "addr1=%pM addr2=%pM\n", | 1392 | jiffies - entry->first_frag_time, entry->seq, |
1393 | sdata->name, idx, | 1393 | entry->last_frag, hdr->addr1, hdr->addr2); |
1394 | jiffies - entry->first_frag_time, entry->seq, | ||
1395 | entry->last_frag, hdr->addr1, hdr->addr2); | ||
1396 | #endif | 1394 | #endif |
1397 | __skb_queue_purge(&entry->skb_list); | 1395 | __skb_queue_purge(&entry->skb_list); |
1398 | } | 1396 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6d90a562669f..267b2940fadd 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -322,7 +322,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
322 | ieee80211_mlme_notify_scan_completed(local); | 322 | ieee80211_mlme_notify_scan_completed(local); |
323 | ieee80211_ibss_notify_scan_completed(local); | 323 | ieee80211_ibss_notify_scan_completed(local); |
324 | ieee80211_mesh_notify_scan_completed(local); | 324 | ieee80211_mesh_notify_scan_completed(local); |
325 | ieee80211_queue_work(&local->hw, &local->work_work); | 325 | ieee80211_start_next_roc(local); |
326 | } | 326 | } |
327 | 327 | ||
328 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 328 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
@@ -375,7 +375,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
375 | static bool ieee80211_can_scan(struct ieee80211_local *local, | 375 | static bool ieee80211_can_scan(struct ieee80211_local *local, |
376 | struct ieee80211_sub_if_data *sdata) | 376 | struct ieee80211_sub_if_data *sdata) |
377 | { | 377 | { |
378 | if (!list_empty(&local->work_list)) | 378 | if (!list_empty(&local->roc_list)) |
379 | return false; | 379 | return false; |
380 | 380 | ||
381 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 381 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index de455f8bbb91..77dcf2f89d42 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -333,9 +333,8 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local, | |||
333 | } | 333 | } |
334 | 334 | ||
335 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 335 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
336 | printk(KERN_DEBUG | 336 | pr_debug("%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n", |
337 | "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n", | 337 | sdata->name, sta->sta.addr, state + 1, err); |
338 | sdata->name, sta->sta.addr, state + 1, err); | ||
339 | err = 0; | 338 | err = 0; |
340 | } | 339 | } |
341 | 340 | ||
@@ -619,8 +618,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
619 | 618 | ||
620 | local->total_ps_buffered--; | 619 | local->total_ps_buffered--; |
621 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 620 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
622 | printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", | 621 | pr_debug("Buffered frame expired (STA %pM)\n", sta->sta.addr); |
623 | sta->sta.addr); | ||
624 | #endif | 622 | #endif |
625 | dev_kfree_skb(skb); | 623 | dev_kfree_skb(skb); |
626 | } | 624 | } |
@@ -889,10 +887,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
889 | continue; | 887 | continue; |
890 | 888 | ||
891 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 889 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
892 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 890 | ibss_vdbg("%s: expiring inactive STA %pM\n", |
893 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 891 | sdata->name, sta->sta.addr); |
894 | sdata->name, sta->sta.addr); | ||
895 | #endif | ||
896 | WARN_ON(__sta_info_destroy(sta)); | 892 | WARN_ON(__sta_info_destroy(sta)); |
897 | } | 893 | } |
898 | } | 894 | } |
@@ -991,9 +987,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
991 | sta_info_recalc_tim(sta); | 987 | sta_info_recalc_tim(sta); |
992 | 988 | ||
993 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 989 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
994 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 990 | pr_debug("%s: STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n", |
995 | "since STA not sleeping anymore\n", sdata->name, | 991 | sdata->name, sta->sta.addr, sta->sta.aid, filtered, buffered); |
996 | sta->sta.addr, sta->sta.aid, filtered, buffered); | ||
997 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 992 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
998 | } | 993 | } |
999 | 994 | ||
@@ -1385,8 +1380,8 @@ int sta_info_move_state(struct sta_info *sta, | |||
1385 | } | 1380 | } |
1386 | 1381 | ||
1387 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1382 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1388 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | 1383 | pr_debug("%s: moving STA %pM to state %d\n", |
1389 | sta->sdata->name, sta->sta.addr, new_state); | 1384 | sta->sdata->name, sta->sta.addr, new_state); |
1390 | #endif | 1385 | #endif |
1391 | 1386 | ||
1392 | /* | 1387 | /* |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 28cfa981cfb1..6b4f42527887 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -520,36 +520,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
520 | 520 | ||
521 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { | 521 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
522 | u64 cookie = (unsigned long)skb; | 522 | u64 cookie = (unsigned long)skb; |
523 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
523 | 524 | ||
524 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 525 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
525 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | 526 | ieee80211_is_qos_nullfunc(hdr->frame_control)) |
526 | acked = info->flags & IEEE80211_TX_STAT_ACK; | ||
527 | |||
528 | cfg80211_probe_status(skb->dev, hdr->addr1, | 527 | cfg80211_probe_status(skb->dev, hdr->addr1, |
529 | cookie, acked, GFP_ATOMIC); | 528 | cookie, acked, GFP_ATOMIC); |
530 | } else { | 529 | else |
531 | struct ieee80211_work *wk; | ||
532 | |||
533 | rcu_read_lock(); | ||
534 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
535 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
536 | continue; | ||
537 | if (wk->offchan_tx.frame != skb) | ||
538 | continue; | ||
539 | wk->offchan_tx.status = true; | ||
540 | break; | ||
541 | } | ||
542 | rcu_read_unlock(); | ||
543 | if (local->hw_roc_skb_for_status == skb) { | ||
544 | cookie = local->hw_roc_cookie ^ 2; | ||
545 | local->hw_roc_skb_for_status = NULL; | ||
546 | } | ||
547 | |||
548 | cfg80211_mgmt_tx_status( | 530 | cfg80211_mgmt_tx_status( |
549 | skb->dev, cookie, skb->data, skb->len, | 531 | skb->dev, cookie, skb->data, skb->len, |
550 | !!(info->flags & IEEE80211_TX_STAT_ACK), | 532 | acked, GFP_ATOMIC); |
551 | GFP_ATOMIC); | ||
552 | } | ||
553 | } | 533 | } |
554 | 534 | ||
555 | if (unlikely(info->ack_frame_id)) { | 535 | if (unlikely(info->ack_frame_id)) { |
@@ -589,7 +569,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
589 | /* send frame to monitor interfaces now */ | 569 | /* send frame to monitor interfaces now */ |
590 | rtap_len = ieee80211_tx_radiotap_len(info); | 570 | rtap_len = ieee80211_tx_radiotap_len(info); |
591 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { | 571 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { |
592 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | 572 | pr_err("ieee80211_tx_status: headroom too small\n"); |
593 | dev_kfree_skb(skb); | 573 | dev_kfree_skb(skb); |
594 | return; | 574 | return; |
595 | } | 575 | } |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 51077a956a83..68be47ca208f 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -263,12 +263,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
263 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 263 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
264 | { | 264 | { |
265 | int i; | 265 | int i; |
266 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); | 266 | pr_debug("TKIP decrypt: data(len=%zd)", payload_len); |
267 | for (i = 0; i < payload_len; i++) | 267 | for (i = 0; i < payload_len; i++) |
268 | printk(" %02x", payload[i]); | 268 | printk(" %02x", payload[i]); |
269 | printk("\n"); | 269 | printk("\n"); |
270 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", | 270 | pr_debug("TKIP decrypt: iv16=%04x iv32=%08x\n", iv16, iv32); |
271 | iv16, iv32); | ||
272 | } | 271 | } |
273 | #endif | 272 | #endif |
274 | 273 | ||
@@ -283,11 +282,10 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
283 | (iv32 == key->u.tkip.rx[queue].iv32 && | 282 | (iv32 == key->u.tkip.rx[queue].iv32 && |
284 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 283 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
285 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 284 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
286 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " | 285 | pr_debug("TKIP replay detected for RX frame from %pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", |
287 | "%pM (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", | 286 | ta, iv32, iv16, |
288 | ta, | 287 | key->u.tkip.rx[queue].iv32, |
289 | iv32, iv16, key->u.tkip.rx[queue].iv32, | 288 | key->u.tkip.rx[queue].iv16); |
290 | key->u.tkip.rx[queue].iv16); | ||
291 | #endif | 289 | #endif |
292 | return TKIP_DECRYPT_REPLAY; | 290 | return TKIP_DECRYPT_REPLAY; |
293 | } | 291 | } |
@@ -306,13 +304,12 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
306 | { | 304 | { |
307 | int i; | 305 | int i; |
308 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; | 306 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; |
309 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%pM" | 307 | pr_debug("TKIP decrypt: Phase1 TA=%pM TK=", ta); |
310 | " TK=", ta); | ||
311 | for (i = 0; i < 16; i++) | 308 | for (i = 0; i < 16; i++) |
312 | printk("%02x ", | 309 | printk("%02x ", |
313 | key->conf.key[key_offset + i]); | 310 | key->conf.key[key_offset + i]); |
314 | printk("\n"); | 311 | printk("\n"); |
315 | printk(KERN_DEBUG "TKIP decrypt: P1K="); | 312 | pr_debug("TKIP decrypt: P1K="); |
316 | for (i = 0; i < 5; i++) | 313 | for (i = 0; i < 5; i++) |
317 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); | 314 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); |
318 | printk("\n"); | 315 | printk("\n"); |
@@ -336,7 +333,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, | |||
336 | #ifdef CONFIG_MAC80211_TKIP_DEBUG | 333 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
337 | { | 334 | { |
338 | int i; | 335 | int i; |
339 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); | 336 | pr_debug("TKIP decrypt: Phase2 rc4key="); |
340 | for (i = 0; i < 16; i++) | 337 | for (i = 0; i < 16; i++) |
341 | printk("%02x ", rc4key[i]); | 338 | printk("%02x ", rc4key[i]); |
342 | printk("\n"); | 339 | printk("\n"); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e453212fa17f..af25c4e7ec5c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -297,9 +297,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
297 | if (unlikely(!assoc && | 297 | if (unlikely(!assoc && |
298 | ieee80211_is_data(hdr->frame_control))) { | 298 | ieee80211_is_data(hdr->frame_control))) { |
299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
300 | printk(KERN_DEBUG "%s: dropped data frame to not " | 300 | pr_debug("%s: dropped data frame to not associated station %pM\n", |
301 | "associated station %pM\n", | 301 | tx->sdata->name, hdr->addr1); |
302 | tx->sdata->name, hdr->addr1); | ||
303 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 302 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
304 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 303 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
305 | return TX_DROP; | 304 | return TX_DROP; |
@@ -467,8 +466,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
467 | } | 466 | } |
468 | 467 | ||
469 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 468 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
470 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", | 469 | pr_debug("STA %pM aid %d: PS buffer for AC %d\n", |
471 | sta->sta.addr, sta->sta.aid, ac); | 470 | sta->sta.addr, sta->sta.aid, ac); |
472 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 471 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
473 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 472 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
474 | purge_old_ps_buffers(tx->local); | 473 | purge_old_ps_buffers(tx->local); |
@@ -502,9 +501,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
502 | } | 501 | } |
503 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 502 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
504 | else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { | 503 | else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { |
505 | printk(KERN_DEBUG | 504 | pr_debug("%s: STA %pM in PS mode, but polling/in SP -> send frame\n", |
506 | "%s: STA %pM in PS mode, but polling/in SP -> send frame\n", | 505 | tx->sdata->name, sta->sta.addr); |
507 | tx->sdata->name, sta->sta.addr); | ||
508 | } | 506 | } |
509 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 507 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
510 | 508 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 8dd4712620ff..1df4019f294b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -804,7 +804,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
804 | struct ieee80211_local *local = sdata->local; | 804 | struct ieee80211_local *local = sdata->local; |
805 | struct ieee80211_tx_queue_params qparam; | 805 | struct ieee80211_tx_queue_params qparam; |
806 | int ac; | 806 | int ac; |
807 | bool use_11b; | 807 | bool use_11b, enable_qos; |
808 | int aCWmin, aCWmax; | 808 | int aCWmin, aCWmax; |
809 | 809 | ||
810 | if (!local->ops->conf_tx) | 810 | if (!local->ops->conf_tx) |
@@ -818,6 +818,13 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
818 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && | 818 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && |
819 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 819 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
820 | 820 | ||
821 | /* | ||
822 | * By default disable QoS in STA mode for old access points, which do | ||
823 | * not support 802.11e. New APs will provide proper queue parameters, | ||
824 | * that we will configure later. | ||
825 | */ | ||
826 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); | ||
827 | |||
821 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 828 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
822 | /* Set defaults according to 802.11-2007 Table 7-37 */ | 829 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
823 | aCWmax = 1023; | 830 | aCWmax = 1023; |
@@ -826,38 +833,47 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
826 | else | 833 | else |
827 | aCWmin = 15; | 834 | aCWmin = 15; |
828 | 835 | ||
829 | switch (ac) { | 836 | if (enable_qos) { |
830 | case IEEE80211_AC_BK: | 837 | switch (ac) { |
831 | qparam.cw_max = aCWmax; | 838 | case IEEE80211_AC_BK: |
832 | qparam.cw_min = aCWmin; | 839 | qparam.cw_max = aCWmax; |
833 | qparam.txop = 0; | 840 | qparam.cw_min = aCWmin; |
834 | qparam.aifs = 7; | 841 | qparam.txop = 0; |
835 | break; | 842 | qparam.aifs = 7; |
836 | default: /* never happens but let's not leave undefined */ | 843 | break; |
837 | case IEEE80211_AC_BE: | 844 | /* never happens but let's not leave undefined */ |
845 | default: | ||
846 | case IEEE80211_AC_BE: | ||
847 | qparam.cw_max = aCWmax; | ||
848 | qparam.cw_min = aCWmin; | ||
849 | qparam.txop = 0; | ||
850 | qparam.aifs = 3; | ||
851 | break; | ||
852 | case IEEE80211_AC_VI: | ||
853 | qparam.cw_max = aCWmin; | ||
854 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | ||
855 | if (use_11b) | ||
856 | qparam.txop = 6016/32; | ||
857 | else | ||
858 | qparam.txop = 3008/32; | ||
859 | qparam.aifs = 2; | ||
860 | break; | ||
861 | case IEEE80211_AC_VO: | ||
862 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | ||
863 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | ||
864 | if (use_11b) | ||
865 | qparam.txop = 3264/32; | ||
866 | else | ||
867 | qparam.txop = 1504/32; | ||
868 | qparam.aifs = 2; | ||
869 | break; | ||
870 | } | ||
871 | } else { | ||
872 | /* Confiure old 802.11b/g medium access rules. */ | ||
838 | qparam.cw_max = aCWmax; | 873 | qparam.cw_max = aCWmax; |
839 | qparam.cw_min = aCWmin; | 874 | qparam.cw_min = aCWmin; |
840 | qparam.txop = 0; | 875 | qparam.txop = 0; |
841 | qparam.aifs = 3; | ||
842 | break; | ||
843 | case IEEE80211_AC_VI: | ||
844 | qparam.cw_max = aCWmin; | ||
845 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | ||
846 | if (use_11b) | ||
847 | qparam.txop = 6016/32; | ||
848 | else | ||
849 | qparam.txop = 3008/32; | ||
850 | qparam.aifs = 2; | ||
851 | break; | ||
852 | case IEEE80211_AC_VO: | ||
853 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | ||
854 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | ||
855 | if (use_11b) | ||
856 | qparam.txop = 3264/32; | ||
857 | else | ||
858 | qparam.txop = 1504/32; | ||
859 | qparam.aifs = 2; | 876 | qparam.aifs = 2; |
860 | break; | ||
861 | } | 877 | } |
862 | 878 | ||
863 | qparam.uapsd = false; | 879 | qparam.uapsd = false; |
@@ -866,12 +882,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
866 | drv_conf_tx(local, sdata, ac, &qparam); | 882 | drv_conf_tx(local, sdata, ac, &qparam); |
867 | } | 883 | } |
868 | 884 | ||
869 | /* after reinitialize QoS TX queues setting to default, | ||
870 | * disable QoS at all */ | ||
871 | |||
872 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 885 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
873 | sdata->vif.bss_conf.qos = | 886 | sdata->vif.bss_conf.qos = enable_qos; |
874 | sdata->vif.type != NL80211_IFTYPE_STATION; | ||
875 | if (bss_notify) | 887 | if (bss_notify) |
876 | ieee80211_bss_info_change_notify(sdata, | 888 | ieee80211_bss_info_change_notify(sdata, |
877 | BSS_CHANGED_QOS); | 889 | BSS_CHANGED_QOS); |
@@ -1267,14 +1279,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1267 | /* add STAs back */ | 1279 | /* add STAs back */ |
1268 | mutex_lock(&local->sta_mtx); | 1280 | mutex_lock(&local->sta_mtx); |
1269 | list_for_each_entry(sta, &local->sta_list, list) { | 1281 | list_for_each_entry(sta, &local->sta_list, list) { |
1270 | if (sta->uploaded) { | 1282 | enum ieee80211_sta_state state; |
1271 | enum ieee80211_sta_state state; | ||
1272 | 1283 | ||
1273 | for (state = IEEE80211_STA_NOTEXIST; | 1284 | if (!sta->uploaded) |
1274 | state < sta->sta_state; state++) | 1285 | continue; |
1275 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | 1286 | |
1276 | state, state + 1)); | 1287 | /* AP-mode stations will be added later */ |
1277 | } | 1288 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) |
1289 | continue; | ||
1290 | |||
1291 | for (state = IEEE80211_STA_NOTEXIST; | ||
1292 | state < sta->sta_state; state++) | ||
1293 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1294 | state + 1)); | ||
1278 | } | 1295 | } |
1279 | mutex_unlock(&local->sta_mtx); | 1296 | mutex_unlock(&local->sta_mtx); |
1280 | 1297 | ||
@@ -1371,6 +1388,24 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1371 | } | 1388 | } |
1372 | } | 1389 | } |
1373 | 1390 | ||
1391 | /* APs are now beaconing, add back stations */ | ||
1392 | mutex_lock(&local->sta_mtx); | ||
1393 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1394 | enum ieee80211_sta_state state; | ||
1395 | |||
1396 | if (!sta->uploaded) | ||
1397 | continue; | ||
1398 | |||
1399 | if (sta->sdata->vif.type != NL80211_IFTYPE_AP) | ||
1400 | continue; | ||
1401 | |||
1402 | for (state = IEEE80211_STA_NOTEXIST; | ||
1403 | state < sta->sta_state; state++) | ||
1404 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1405 | state + 1)); | ||
1406 | } | ||
1407 | mutex_unlock(&local->sta_mtx); | ||
1408 | |||
1374 | /* add back keys */ | 1409 | /* add back keys */ |
1375 | list_for_each_entry(sdata, &local->interfaces, list) | 1410 | list_for_each_entry(sdata, &local->interfaces, list) |
1376 | if (ieee80211_sdata_running(sdata)) | 1411 | if (ieee80211_sdata_running(sdata)) |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c deleted file mode 100644 index b2650a9d45ff..000000000000 --- a/net/mac80211/work.c +++ /dev/null | |||
@@ -1,370 +0,0 @@ | |||
1 | /* | ||
2 | * mac80211 work implementation | ||
3 | * | ||
4 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/delay.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/if_arp.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <net/mac80211.h> | ||
24 | #include <asm/unaligned.h> | ||
25 | |||
26 | #include "ieee80211_i.h" | ||
27 | #include "rate.h" | ||
28 | #include "driver-ops.h" | ||
29 | |||
30 | enum work_action { | ||
31 | WORK_ACT_NONE, | ||
32 | WORK_ACT_TIMEOUT, | ||
33 | }; | ||
34 | |||
35 | |||
36 | /* utils */ | ||
37 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | ||
38 | { | ||
39 | lockdep_assert_held(&local->mtx); | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * We can have multiple work items (and connection probing) | ||
44 | * scheduling this timer, but we need to take care to only | ||
45 | * reschedule it when it should fire _earlier_ than it was | ||
46 | * asked for before, or if it's not pending right now. This | ||
47 | * function ensures that. Note that it then is required to | ||
48 | * run this function for all timeouts after the first one | ||
49 | * has happened -- the work that runs from this timer will | ||
50 | * do that. | ||
51 | */ | ||
52 | static void run_again(struct ieee80211_local *local, | ||
53 | unsigned long timeout) | ||
54 | { | ||
55 | ASSERT_WORK_MTX(local); | ||
56 | |||
57 | if (!timer_pending(&local->work_timer) || | ||
58 | time_before(timeout, local->work_timer.expires)) | ||
59 | mod_timer(&local->work_timer, timeout); | ||
60 | } | ||
61 | |||
62 | void free_work(struct ieee80211_work *wk) | ||
63 | { | ||
64 | kfree_rcu(wk, rcu_head); | ||
65 | } | ||
66 | |||
67 | static enum work_action __must_check | ||
68 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | ||
69 | { | ||
70 | /* | ||
71 | * First time we run, do nothing -- the generic code will | ||
72 | * have switched to the right channel etc. | ||
73 | */ | ||
74 | if (!wk->started) { | ||
75 | wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); | ||
76 | |||
77 | cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, | ||
78 | wk->chan, wk->chan_type, | ||
79 | wk->remain.duration, GFP_KERNEL); | ||
80 | |||
81 | return WORK_ACT_NONE; | ||
82 | } | ||
83 | |||
84 | return WORK_ACT_TIMEOUT; | ||
85 | } | ||
86 | |||
87 | static enum work_action __must_check | ||
88 | ieee80211_offchannel_tx(struct ieee80211_work *wk) | ||
89 | { | ||
90 | if (!wk->started) { | ||
91 | wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait); | ||
92 | |||
93 | /* | ||
94 | * After this, offchan_tx.frame remains but now is no | ||
95 | * longer a valid pointer -- we still need it as the | ||
96 | * cookie for canceling this work/status matching. | ||
97 | */ | ||
98 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | ||
99 | |||
100 | return WORK_ACT_NONE; | ||
101 | } | ||
102 | |||
103 | return WORK_ACT_TIMEOUT; | ||
104 | } | ||
105 | |||
106 | static void ieee80211_work_timer(unsigned long data) | ||
107 | { | ||
108 | struct ieee80211_local *local = (void *) data; | ||
109 | |||
110 | if (local->quiescing) | ||
111 | return; | ||
112 | |||
113 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
114 | } | ||
115 | |||
116 | static void ieee80211_work_work(struct work_struct *work) | ||
117 | { | ||
118 | struct ieee80211_local *local = | ||
119 | container_of(work, struct ieee80211_local, work_work); | ||
120 | struct ieee80211_work *wk, *tmp; | ||
121 | LIST_HEAD(free_work); | ||
122 | enum work_action rma; | ||
123 | bool remain_off_channel = false; | ||
124 | |||
125 | /* | ||
126 | * ieee80211_queue_work() should have picked up most cases, | ||
127 | * here we'll pick the rest. | ||
128 | */ | ||
129 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | ||
130 | return; | ||
131 | |||
132 | mutex_lock(&local->mtx); | ||
133 | |||
134 | if (local->scanning) { | ||
135 | mutex_unlock(&local->mtx); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | ieee80211_recalc_idle(local); | ||
140 | |||
141 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
142 | bool started = wk->started; | ||
143 | |||
144 | /* mark work as started if it's on the current off-channel */ | ||
145 | if (!started && local->tmp_channel && | ||
146 | wk->chan == local->tmp_channel && | ||
147 | wk->chan_type == local->tmp_channel_type) { | ||
148 | started = true; | ||
149 | wk->timeout = jiffies; | ||
150 | } | ||
151 | |||
152 | if (!started && !local->tmp_channel) { | ||
153 | ieee80211_offchannel_stop_vifs(local, true); | ||
154 | |||
155 | local->tmp_channel = wk->chan; | ||
156 | local->tmp_channel_type = wk->chan_type; | ||
157 | |||
158 | ieee80211_hw_config(local, 0); | ||
159 | |||
160 | started = true; | ||
161 | wk->timeout = jiffies; | ||
162 | } | ||
163 | |||
164 | /* don't try to work with items that aren't started */ | ||
165 | if (!started) | ||
166 | continue; | ||
167 | |||
168 | if (time_is_after_jiffies(wk->timeout)) { | ||
169 | /* | ||
170 | * This work item isn't supposed to be worked on | ||
171 | * right now, but take care to adjust the timer | ||
172 | * properly. | ||
173 | */ | ||
174 | run_again(local, wk->timeout); | ||
175 | continue; | ||
176 | } | ||
177 | |||
178 | switch (wk->type) { | ||
179 | default: | ||
180 | WARN_ON(1); | ||
181 | /* nothing */ | ||
182 | rma = WORK_ACT_NONE; | ||
183 | break; | ||
184 | case IEEE80211_WORK_ABORT: | ||
185 | rma = WORK_ACT_TIMEOUT; | ||
186 | break; | ||
187 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | ||
188 | rma = ieee80211_remain_on_channel_timeout(wk); | ||
189 | break; | ||
190 | case IEEE80211_WORK_OFFCHANNEL_TX: | ||
191 | rma = ieee80211_offchannel_tx(wk); | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | wk->started = started; | ||
196 | |||
197 | switch (rma) { | ||
198 | case WORK_ACT_NONE: | ||
199 | /* might have changed the timeout */ | ||
200 | run_again(local, wk->timeout); | ||
201 | break; | ||
202 | case WORK_ACT_TIMEOUT: | ||
203 | list_del_rcu(&wk->list); | ||
204 | synchronize_rcu(); | ||
205 | list_add(&wk->list, &free_work); | ||
206 | break; | ||
207 | default: | ||
208 | WARN(1, "unexpected: %d", rma); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | list_for_each_entry(wk, &local->work_list, list) { | ||
213 | if (!wk->started) | ||
214 | continue; | ||
215 | if (wk->chan != local->tmp_channel || | ||
216 | wk->chan_type != local->tmp_channel_type) | ||
217 | continue; | ||
218 | remain_off_channel = true; | ||
219 | } | ||
220 | |||
221 | if (!remain_off_channel && local->tmp_channel) { | ||
222 | local->tmp_channel = NULL; | ||
223 | ieee80211_hw_config(local, 0); | ||
224 | |||
225 | ieee80211_offchannel_return(local, true); | ||
226 | |||
227 | /* give connection some time to breathe */ | ||
228 | run_again(local, jiffies + HZ/2); | ||
229 | } | ||
230 | |||
231 | ieee80211_recalc_idle(local); | ||
232 | ieee80211_run_deferred_scan(local); | ||
233 | |||
234 | mutex_unlock(&local->mtx); | ||
235 | |||
236 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
237 | wk->done(wk, NULL); | ||
238 | list_del(&wk->list); | ||
239 | kfree(wk); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | void ieee80211_add_work(struct ieee80211_work *wk) | ||
244 | { | ||
245 | struct ieee80211_local *local; | ||
246 | |||
247 | if (WARN_ON(!wk->chan)) | ||
248 | return; | ||
249 | |||
250 | if (WARN_ON(!wk->sdata)) | ||
251 | return; | ||
252 | |||
253 | if (WARN_ON(!wk->done)) | ||
254 | return; | ||
255 | |||
256 | if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) | ||
257 | return; | ||
258 | |||
259 | wk->started = false; | ||
260 | |||
261 | local = wk->sdata->local; | ||
262 | mutex_lock(&local->mtx); | ||
263 | list_add_tail(&wk->list, &local->work_list); | ||
264 | mutex_unlock(&local->mtx); | ||
265 | |||
266 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
267 | } | ||
268 | |||
269 | void ieee80211_work_init(struct ieee80211_local *local) | ||
270 | { | ||
271 | INIT_LIST_HEAD(&local->work_list); | ||
272 | setup_timer(&local->work_timer, ieee80211_work_timer, | ||
273 | (unsigned long)local); | ||
274 | INIT_WORK(&local->work_work, ieee80211_work_work); | ||
275 | } | ||
276 | |||
277 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | ||
278 | { | ||
279 | struct ieee80211_local *local = sdata->local; | ||
280 | struct ieee80211_work *wk; | ||
281 | bool cleanup = false; | ||
282 | |||
283 | mutex_lock(&local->mtx); | ||
284 | list_for_each_entry(wk, &local->work_list, list) { | ||
285 | if (wk->sdata != sdata) | ||
286 | continue; | ||
287 | cleanup = true; | ||
288 | wk->type = IEEE80211_WORK_ABORT; | ||
289 | wk->started = true; | ||
290 | wk->timeout = jiffies; | ||
291 | } | ||
292 | mutex_unlock(&local->mtx); | ||
293 | |||
294 | /* run cleanups etc. */ | ||
295 | if (cleanup) | ||
296 | ieee80211_work_work(&local->work_work); | ||
297 | |||
298 | mutex_lock(&local->mtx); | ||
299 | list_for_each_entry(wk, &local->work_list, list) { | ||
300 | if (wk->sdata != sdata) | ||
301 | continue; | ||
302 | WARN_ON(1); | ||
303 | break; | ||
304 | } | ||
305 | mutex_unlock(&local->mtx); | ||
306 | } | ||
307 | |||
308 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, | ||
309 | struct sk_buff *skb) | ||
310 | { | ||
311 | /* | ||
312 | * We are done serving the remain-on-channel command. | ||
313 | */ | ||
314 | cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk, | ||
315 | wk->chan, wk->chan_type, | ||
316 | GFP_KERNEL); | ||
317 | |||
318 | return WORK_DONE_DESTROY; | ||
319 | } | ||
320 | |||
321 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
322 | struct ieee80211_channel *chan, | ||
323 | enum nl80211_channel_type channel_type, | ||
324 | unsigned int duration, u64 *cookie) | ||
325 | { | ||
326 | struct ieee80211_work *wk; | ||
327 | |||
328 | wk = kzalloc(sizeof(*wk), GFP_KERNEL); | ||
329 | if (!wk) | ||
330 | return -ENOMEM; | ||
331 | |||
332 | wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; | ||
333 | wk->chan = chan; | ||
334 | wk->chan_type = channel_type; | ||
335 | wk->sdata = sdata; | ||
336 | wk->done = ieee80211_remain_done; | ||
337 | |||
338 | wk->remain.duration = duration; | ||
339 | |||
340 | *cookie = (unsigned long) wk; | ||
341 | |||
342 | ieee80211_add_work(wk); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
348 | u64 cookie) | ||
349 | { | ||
350 | struct ieee80211_local *local = sdata->local; | ||
351 | struct ieee80211_work *wk, *tmp; | ||
352 | bool found = false; | ||
353 | |||
354 | mutex_lock(&local->mtx); | ||
355 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
356 | if ((unsigned long) wk == cookie) { | ||
357 | wk->timeout = jiffies; | ||
358 | found = true; | ||
359 | break; | ||
360 | } | ||
361 | } | ||
362 | mutex_unlock(&local->mtx); | ||
363 | |||
364 | if (!found) | ||
365 | return -ENOENT; | ||
366 | |||
367 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
368 | |||
369 | return 0; | ||
370 | } | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index 9f6ce011d35d..4177bb5104b9 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -121,14 +121,14 @@ error: | |||
121 | * The device remains polling for targets until a target is found or | 121 | * The device remains polling for targets until a target is found or |
122 | * the nfc_stop_poll function is called. | 122 | * the nfc_stop_poll function is called. |
123 | */ | 123 | */ |
124 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | 124 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) |
125 | { | 125 | { |
126 | int rc; | 126 | int rc; |
127 | 127 | ||
128 | pr_debug("dev_name=%s protocols=0x%x\n", | 128 | pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n", |
129 | dev_name(&dev->dev), protocols); | 129 | dev_name(&dev->dev), im_protocols, tm_protocols); |
130 | 130 | ||
131 | if (!protocols) | 131 | if (!im_protocols && !tm_protocols) |
132 | return -EINVAL; | 132 | return -EINVAL; |
133 | 133 | ||
134 | device_lock(&dev->dev); | 134 | device_lock(&dev->dev); |
@@ -143,9 +143,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | |||
143 | goto error; | 143 | goto error; |
144 | } | 144 | } |
145 | 145 | ||
146 | rc = dev->ops->start_poll(dev, protocols); | 146 | rc = dev->ops->start_poll(dev, im_protocols, tm_protocols); |
147 | if (!rc) | 147 | if (!rc) { |
148 | dev->polling = true; | 148 | dev->polling = true; |
149 | dev->rf_mode = NFC_RF_NONE; | ||
150 | } | ||
149 | 151 | ||
150 | error: | 152 | error: |
151 | device_unlock(&dev->dev); | 153 | device_unlock(&dev->dev); |
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | |||
235 | } | 237 | } |
236 | 238 | ||
237 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); | 239 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); |
238 | if (!rc) | 240 | if (!rc) { |
239 | dev->active_target = target; | 241 | dev->active_target = target; |
242 | dev->rf_mode = NFC_RF_INITIATOR; | ||
243 | } | ||
240 | 244 | ||
241 | error: | 245 | error: |
242 | device_unlock(&dev->dev); | 246 | device_unlock(&dev->dev); |
@@ -264,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
264 | goto error; | 268 | goto error; |
265 | } | 269 | } |
266 | 270 | ||
267 | if (dev->dep_rf_mode == NFC_RF_TARGET) { | ||
268 | rc = -EOPNOTSUPP; | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | rc = dev->ops->dep_link_down(dev); | 271 | rc = dev->ops->dep_link_down(dev); |
273 | if (!rc) { | 272 | if (!rc) { |
274 | dev->dep_link_up = false; | 273 | dev->dep_link_up = false; |
@@ -286,7 +285,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
286 | u8 comm_mode, u8 rf_mode) | 285 | u8 comm_mode, u8 rf_mode) |
287 | { | 286 | { |
288 | dev->dep_link_up = true; | 287 | dev->dep_link_up = true; |
289 | dev->dep_rf_mode = rf_mode; | ||
290 | 288 | ||
291 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 289 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
292 | 290 | ||
@@ -330,6 +328,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
330 | rc = dev->ops->activate_target(dev, target, protocol); | 328 | rc = dev->ops->activate_target(dev, target, protocol); |
331 | if (!rc) { | 329 | if (!rc) { |
332 | dev->active_target = target; | 330 | dev->active_target = target; |
331 | dev->rf_mode = NFC_RF_INITIATOR; | ||
333 | 332 | ||
334 | if (dev->ops->check_presence) | 333 | if (dev->ops->check_presence) |
335 | mod_timer(&dev->check_pres_timer, jiffies + | 334 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -409,27 +408,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
409 | goto error; | 408 | goto error; |
410 | } | 409 | } |
411 | 410 | ||
412 | if (dev->active_target == NULL) { | 411 | if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) { |
413 | rc = -ENOTCONN; | 412 | if (dev->active_target->idx != target_idx) { |
414 | kfree_skb(skb); | 413 | rc = -EADDRNOTAVAIL; |
415 | goto error; | 414 | kfree_skb(skb); |
416 | } | 415 | goto error; |
416 | } | ||
417 | 417 | ||
418 | if (dev->active_target->idx != target_idx) { | 418 | if (dev->ops->check_presence) |
419 | rc = -EADDRNOTAVAIL; | 419 | del_timer_sync(&dev->check_pres_timer); |
420 | |||
421 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | ||
422 | cb_context); | ||
423 | |||
424 | if (!rc && dev->ops->check_presence) | ||
425 | mod_timer(&dev->check_pres_timer, jiffies + | ||
426 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
427 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | ||
428 | rc = dev->ops->tm_send(dev, skb); | ||
429 | } else { | ||
430 | rc = -ENOTCONN; | ||
420 | kfree_skb(skb); | 431 | kfree_skb(skb); |
421 | goto error; | 432 | goto error; |
422 | } | 433 | } |
423 | 434 | ||
424 | if (dev->ops->check_presence) | ||
425 | del_timer_sync(&dev->check_pres_timer); | ||
426 | |||
427 | rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, | ||
428 | cb_context); | ||
429 | |||
430 | if (!rc && dev->ops->check_presence) | ||
431 | mod_timer(&dev->check_pres_timer, jiffies + | ||
432 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
433 | 435 | ||
434 | error: | 436 | error: |
435 | device_unlock(&dev->dev); | 437 | device_unlock(&dev->dev); |
@@ -447,6 +449,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
447 | } | 449 | } |
448 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 450 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
449 | 451 | ||
452 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len) | ||
453 | { | ||
454 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | ||
455 | |||
456 | return nfc_llcp_general_bytes(dev, gb_len); | ||
457 | } | ||
458 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
459 | |||
460 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
461 | { | ||
462 | /* Only LLCP target mode for now */ | ||
463 | if (dev->dep_link_up == false) { | ||
464 | kfree_skb(skb); | ||
465 | return -ENOLINK; | ||
466 | } | ||
467 | |||
468 | return nfc_llcp_data_received(dev, skb); | ||
469 | } | ||
470 | EXPORT_SYMBOL(nfc_tm_data_received); | ||
471 | |||
472 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
473 | u8 *gb, size_t gb_len) | ||
474 | { | ||
475 | int rc; | ||
476 | |||
477 | device_lock(&dev->dev); | ||
478 | |||
479 | dev->polling = false; | ||
480 | |||
481 | if (gb != NULL) { | ||
482 | rc = nfc_set_remote_general_bytes(dev, gb, gb_len); | ||
483 | if (rc < 0) | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | dev->rf_mode = NFC_RF_TARGET; | ||
488 | |||
489 | if (protocol == NFC_PROTO_NFC_DEP_MASK) | ||
490 | nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET); | ||
491 | |||
492 | rc = nfc_genl_tm_activated(dev, protocol); | ||
493 | |||
494 | out: | ||
495 | device_unlock(&dev->dev); | ||
496 | |||
497 | return rc; | ||
498 | } | ||
499 | EXPORT_SYMBOL(nfc_tm_activated); | ||
500 | |||
501 | int nfc_tm_deactivated(struct nfc_dev *dev) | ||
502 | { | ||
503 | dev->dep_link_up = false; | ||
504 | |||
505 | return nfc_genl_tm_deactivated(dev); | ||
506 | } | ||
507 | EXPORT_SYMBOL(nfc_tm_deactivated); | ||
508 | |||
450 | /** | 509 | /** |
451 | * nfc_alloc_send_skb - allocate a skb for data exchange responses | 510 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
452 | * | 511 | * |
@@ -678,7 +737,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
678 | struct nfc_dev *dev; | 737 | struct nfc_dev *dev; |
679 | 738 | ||
680 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 739 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
681 | !ops->deactivate_target || !ops->data_exchange) | 740 | !ops->deactivate_target || !ops->im_transceive) |
682 | return NULL; | 741 | return NULL; |
683 | 742 | ||
684 | if (!supported_protocols) | 743 | if (!supported_protocols) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d2b588..a8b0b71e8f86 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) | |||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 484 | static int hci_start_poll(struct nfc_dev *nfc_dev, |
485 | u32 im_protocols, u32 tm_protocols) | ||
485 | { | 486 | { |
486 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 487 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
487 | 488 | ||
488 | if (hdev->ops->start_poll) | 489 | if (hdev->ops->start_poll) |
489 | return hdev->ops->start_poll(hdev, protocols); | 490 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
490 | else | 491 | else |
491 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 492 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
492 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 493 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
@@ -511,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, | |||
511 | { | 512 | { |
512 | } | 513 | } |
513 | 514 | ||
514 | static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 515 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
515 | struct sk_buff *skb, data_exchange_cb_t cb, | 516 | struct sk_buff *skb, data_exchange_cb_t cb, |
516 | void *cb_context) | 517 | void *cb_context) |
517 | { | 518 | { |
518 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 519 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
519 | int r; | 520 | int r; |
@@ -579,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = { | |||
579 | .stop_poll = hci_stop_poll, | 580 | .stop_poll = hci_stop_poll, |
580 | .activate_target = hci_activate_target, | 581 | .activate_target = hci_activate_target, |
581 | .deactivate_target = hci_deactivate_target, | 582 | .deactivate_target = hci_deactivate_target, |
582 | .data_exchange = hci_data_exchange, | 583 | .im_transceive = hci_transceive, |
583 | .check_presence = hci_check_presence, | 584 | .check_presence = hci_check_presence, |
584 | }; | 585 | }; |
585 | 586 | ||
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 5665dc6d893a..6b836e6242b7 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
765 | return 0; | 765 | return 0; |
766 | } | 766 | } |
767 | 767 | ||
768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols) | 768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, |
769 | u32 im_protocols, u32 tm_protocols) | ||
769 | { | 770 | { |
770 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); | 771 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); |
771 | 772 | ||
772 | pr_debug("\n"); | 773 | pr_debug("\n"); |
773 | 774 | ||
774 | if (shdlc->ops->start_poll) | 775 | if (shdlc->ops->start_poll) |
775 | return shdlc->ops->start_poll(shdlc, protocols); | 776 | return shdlc->ops->start_poll(shdlc, |
777 | im_protocols, tm_protocols); | ||
776 | 778 | ||
777 | return 0; | 779 | return 0; |
778 | } | 780 | } |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index bf8ae4f0b90c..b982b5b890d7 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) | |||
51 | return tlv[2]; | 51 | return tlv[2]; |
52 | } | 52 | } |
53 | 53 | ||
54 | static u8 llcp_tlv16(u8 *tlv, u8 type) | 54 | static u16 llcp_tlv16(u8 *tlv, u8 type) |
55 | { | 55 | { |
56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | 56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) |
57 | return 0; | 57 | return 0; |
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv) | |||
67 | 67 | ||
68 | static u16 llcp_tlv_miux(u8 *tlv) | 68 | static u16 llcp_tlv_miux(u8 *tlv) |
69 | { | 69 | { |
70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; | 70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; |
71 | } | 71 | } |
72 | 72 | ||
73 | static u16 llcp_tlv_wks(u8 *tlv) | 73 | static u16 llcp_tlv_wks(u8 *tlv) |
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 121 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 122 | { |
123 | u8 *tlv = tlv_array, type, length, offset = 0; | 123 | u8 *tlv = tlv_array, type, length, offset = 0; |
124 | 124 | ||
@@ -149,8 +149,45 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
149 | case LLCP_TLV_OPT: | 149 | case LLCP_TLV_OPT: |
150 | local->remote_opt = llcp_tlv_opt(tlv); | 150 | local->remote_opt = llcp_tlv_opt(tlv); |
151 | break; | 151 | break; |
152 | default: | ||
153 | pr_err("Invalid gt tlv value 0x%x\n", type); | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | offset += length + 2; | ||
158 | tlv += length + 2; | ||
159 | } | ||
160 | |||
161 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n", | ||
162 | local->remote_version, local->remote_miu, | ||
163 | local->remote_lto, local->remote_opt, | ||
164 | local->remote_wks); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
170 | u8 *tlv_array, u16 tlv_array_len) | ||
171 | { | ||
172 | u8 *tlv = tlv_array, type, length, offset = 0; | ||
173 | |||
174 | pr_debug("TLV array length %d\n", tlv_array_len); | ||
175 | |||
176 | if (sock == NULL) | ||
177 | return -ENOTCONN; | ||
178 | |||
179 | while (offset < tlv_array_len) { | ||
180 | type = tlv[0]; | ||
181 | length = tlv[1]; | ||
182 | |||
183 | pr_debug("type 0x%x length %d\n", type, length); | ||
184 | |||
185 | switch (type) { | ||
186 | case LLCP_TLV_MIUX: | ||
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | ||
188 | break; | ||
152 | case LLCP_TLV_RW: | 189 | case LLCP_TLV_RW: |
153 | local->remote_rw = llcp_tlv_rw(tlv); | 190 | sock->rw = llcp_tlv_rw(tlv); |
154 | break; | 191 | break; |
155 | case LLCP_TLV_SN: | 192 | case LLCP_TLV_SN: |
156 | break; | 193 | break; |
@@ -163,10 +200,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
163 | tlv += length + 2; | 200 | tlv += length + 2; |
164 | } | 201 | } |
165 | 202 | ||
166 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | 203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); |
167 | local->remote_version, local->remote_miu, | ||
168 | local->remote_lto, local->remote_opt, | ||
169 | local->remote_wks, local->remote_rw); | ||
170 | 204 | ||
171 | return 0; | 205 | return 0; |
172 | } | 206 | } |
@@ -474,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 508 | ||
475 | while (remaining_len > 0) { | 509 | while (remaining_len > 0) { |
476 | 510 | ||
477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); | 511 | frag_len = min_t(size_t, sock->miu, remaining_len); |
478 | 512 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 513 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 514 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 42994fac26d6..5d503eeb15a1 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -31,47 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | |||
31 | 31 | ||
32 | static struct list_head llcp_devices; | 32 | static struct list_head llcp_devices; |
33 | 33 | ||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 34 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) |
35 | { | 35 | { |
36 | struct nfc_llcp_sock *parent, *s, *n; | 36 | write_lock(&l->lock); |
37 | struct sock *sk, *parent_sk; | 37 | sk_add_node(sk, &l->head); |
38 | int i; | 38 | write_unlock(&l->lock); |
39 | 39 | } | |
40 | mutex_lock(&local->socket_lock); | ||
41 | |||
42 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
43 | parent = local->sockets[i]; | ||
44 | if (parent == NULL) | ||
45 | continue; | ||
46 | |||
47 | /* Release all child sockets */ | ||
48 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
49 | list_del_init(&s->list); | ||
50 | sk = &s->sk; | ||
51 | |||
52 | lock_sock(sk); | ||
53 | |||
54 | if (sk->sk_state == LLCP_CONNECTED) | ||
55 | nfc_put_device(s->dev); | ||
56 | 40 | ||
57 | sk->sk_state = LLCP_CLOSED; | 41 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) |
42 | { | ||
43 | write_lock(&l->lock); | ||
44 | sk_del_node_init(sk); | ||
45 | write_unlock(&l->lock); | ||
46 | } | ||
58 | 47 | ||
59 | release_sock(sk); | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) |
49 | { | ||
50 | struct sock *sk; | ||
51 | struct hlist_node *node, *tmp; | ||
52 | struct nfc_llcp_sock *llcp_sock; | ||
60 | 53 | ||
61 | sock_orphan(sk); | 54 | write_lock(&local->sockets.lock); |
62 | 55 | ||
63 | s->local = NULL; | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
64 | } | 57 | llcp_sock = nfc_llcp_sock(sk); |
65 | 58 | ||
66 | parent_sk = &parent->sk; | 59 | lock_sock(sk); |
67 | 60 | ||
68 | lock_sock(parent_sk); | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | ||
69 | 63 | ||
70 | if (parent_sk->sk_state == LLCP_LISTEN) { | 64 | if (sk->sk_state == LLCP_LISTEN) { |
71 | struct nfc_llcp_sock *lsk, *n; | 65 | struct nfc_llcp_sock *lsk, *n; |
72 | struct sock *accept_sk; | 66 | struct sock *accept_sk; |
73 | 67 | ||
74 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
75 | accept_queue) { | 69 | accept_queue) { |
76 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
77 | lock_sock(accept_sk); | 71 | lock_sock(accept_sk); |
@@ -83,24 +77,53 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
83 | release_sock(accept_sk); | 77 | release_sock(accept_sk); |
84 | 78 | ||
85 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
86 | |||
87 | lsk->local = NULL; | ||
88 | } | 80 | } |
89 | } | 81 | } |
90 | 82 | ||
91 | if (parent_sk->sk_state == LLCP_CONNECTED) | 83 | sk->sk_state = LLCP_CLOSED; |
92 | nfc_put_device(parent->dev); | ||
93 | |||
94 | parent_sk->sk_state = LLCP_CLOSED; | ||
95 | 84 | ||
96 | release_sock(parent_sk); | 85 | release_sock(sk); |
97 | 86 | ||
98 | sock_orphan(parent_sk); | 87 | sock_orphan(sk); |
99 | 88 | ||
100 | parent->local = NULL; | 89 | sk_del_node_init(sk); |
101 | } | 90 | } |
102 | 91 | ||
103 | mutex_unlock(&local->socket_lock); | 92 | write_unlock(&local->sockets.lock); |
93 | } | ||
94 | |||
95 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ||
96 | { | ||
97 | kref_get(&local->ref); | ||
98 | |||
99 | return local; | ||
100 | } | ||
101 | |||
102 | static void local_release(struct kref *ref) | ||
103 | { | ||
104 | struct nfc_llcp_local *local; | ||
105 | |||
106 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
107 | |||
108 | list_del(&local->list); | ||
109 | nfc_llcp_socket_release(local); | ||
110 | del_timer_sync(&local->link_timer); | ||
111 | skb_queue_purge(&local->tx_queue); | ||
112 | destroy_workqueue(local->tx_wq); | ||
113 | destroy_workqueue(local->rx_wq); | ||
114 | destroy_workqueue(local->timeout_wq); | ||
115 | kfree_skb(local->rx_pending); | ||
116 | kfree(local); | ||
117 | } | ||
118 | |||
119 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | ||
120 | { | ||
121 | WARN_ON(local == NULL); | ||
122 | |||
123 | if (local == NULL) | ||
124 | return 0; | ||
125 | |||
126 | return kref_put(&local->ref, local_release); | ||
104 | } | 127 | } |
105 | 128 | ||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 129 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) |
@@ -384,31 +407,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
384 | return -EINVAL; | 407 | return -EINVAL; |
385 | } | 408 | } |
386 | 409 | ||
387 | return nfc_llcp_parse_tlv(local, | 410 | return nfc_llcp_parse_gb_tlv(local, |
388 | &local->remote_gb[3], | 411 | &local->remote_gb[3], |
389 | local->remote_gb_len - 3); | 412 | local->remote_gb_len - 3); |
390 | } | ||
391 | |||
392 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
393 | { | ||
394 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
395 | tx_work); | ||
396 | struct sk_buff *skb; | ||
397 | |||
398 | skb = skb_dequeue(&local->tx_queue); | ||
399 | if (skb != NULL) { | ||
400 | pr_debug("Sending pending skb\n"); | ||
401 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET, | ||
402 | 16, 1, skb->data, skb->len, true); | ||
403 | |||
404 | nfc_data_exchange(local->dev, local->target_idx, | ||
405 | skb, nfc_llcp_recv, local); | ||
406 | } else { | ||
407 | nfc_llcp_send_symm(local->dev); | ||
408 | } | ||
409 | |||
410 | mod_timer(&local->link_timer, | ||
411 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
412 | } | 413 | } |
413 | 414 | ||
414 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | 415 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
@@ -443,46 +444,146 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
443 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 444 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
444 | } | 445 | } |
445 | 446 | ||
447 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
448 | { | ||
449 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
450 | tx_work); | ||
451 | struct sk_buff *skb; | ||
452 | struct sock *sk; | ||
453 | struct nfc_llcp_sock *llcp_sock; | ||
454 | |||
455 | skb = skb_dequeue(&local->tx_queue); | ||
456 | if (skb != NULL) { | ||
457 | sk = skb->sk; | ||
458 | llcp_sock = nfc_llcp_sock(sk); | ||
459 | if (llcp_sock != NULL) { | ||
460 | int ret; | ||
461 | |||
462 | pr_debug("Sending pending skb\n"); | ||
463 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", | ||
464 | DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb->len, true); | ||
466 | |||
467 | ret = nfc_data_exchange(local->dev, local->target_idx, | ||
468 | skb, nfc_llcp_recv, local); | ||
469 | |||
470 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
471 | skb = skb_get(skb); | ||
472 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
473 | skb); | ||
474 | } | ||
475 | } else { | ||
476 | nfc_llcp_send_symm(local->dev); | ||
477 | } | ||
478 | } else { | ||
479 | nfc_llcp_send_symm(local->dev); | ||
480 | } | ||
481 | |||
482 | mod_timer(&local->link_timer, | ||
483 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | ||
484 | } | ||
485 | |||
486 | static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, | ||
487 | u8 ssap) | ||
488 | { | ||
489 | struct sock *sk; | ||
490 | struct nfc_llcp_sock *llcp_sock; | ||
491 | struct hlist_node *node; | ||
492 | |||
493 | read_lock(&local->connecting_sockets.lock); | ||
494 | |||
495 | sk_for_each(sk, node, &local->connecting_sockets.head) { | ||
496 | llcp_sock = nfc_llcp_sock(sk); | ||
497 | |||
498 | if (llcp_sock->ssap == ssap) { | ||
499 | sock_hold(&llcp_sock->sk); | ||
500 | goto out; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | llcp_sock = NULL; | ||
505 | |||
506 | out: | ||
507 | read_unlock(&local->connecting_sockets.lock); | ||
508 | |||
509 | return llcp_sock; | ||
510 | } | ||
511 | |||
446 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 512 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
447 | u8 ssap, u8 dsap) | 513 | u8 ssap, u8 dsap) |
448 | { | 514 | { |
449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 515 | struct sock *sk; |
516 | struct hlist_node *node; | ||
517 | struct nfc_llcp_sock *llcp_sock; | ||
450 | 518 | ||
451 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 519 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
452 | 520 | ||
453 | if (ssap == 0 && dsap == 0) | 521 | if (ssap == 0 && dsap == 0) |
454 | return NULL; | 522 | return NULL; |
455 | 523 | ||
456 | mutex_lock(&local->socket_lock); | 524 | read_lock(&local->sockets.lock); |
457 | sock = local->sockets[ssap]; | ||
458 | if (sock == NULL) { | ||
459 | mutex_unlock(&local->socket_lock); | ||
460 | return NULL; | ||
461 | } | ||
462 | 525 | ||
463 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | 526 | llcp_sock = NULL; |
464 | 527 | ||
465 | if (sock->dsap == dsap) { | 528 | sk_for_each(sk, node, &local->sockets.head) { |
466 | sock_hold(&sock->sk); | 529 | llcp_sock = nfc_llcp_sock(sk); |
467 | mutex_unlock(&local->socket_lock); | 530 | |
468 | return sock; | 531 | if (llcp_sock->ssap == ssap && |
532 | llcp_sock->dsap == dsap) | ||
533 | break; | ||
469 | } | 534 | } |
470 | 535 | ||
471 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 536 | read_unlock(&local->sockets.lock); |
472 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 537 | |
473 | &llcp_sock->sk, llcp_sock->dsap); | 538 | if (llcp_sock == NULL) |
474 | if (llcp_sock->dsap == dsap) { | 539 | return NULL; |
475 | sock_hold(&llcp_sock->sk); | 540 | |
476 | mutex_unlock(&local->socket_lock); | 541 | sock_hold(&llcp_sock->sk); |
477 | return llcp_sock; | 542 | |
478 | } | 543 | return llcp_sock; |
544 | } | ||
545 | |||
546 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | ||
547 | u8 *sn, size_t sn_len) | ||
548 | { | ||
549 | struct sock *sk; | ||
550 | struct hlist_node *node; | ||
551 | struct nfc_llcp_sock *llcp_sock; | ||
552 | |||
553 | pr_debug("sn %zd\n", sn_len); | ||
554 | |||
555 | if (sn == NULL || sn_len == 0) | ||
556 | return NULL; | ||
557 | |||
558 | read_lock(&local->sockets.lock); | ||
559 | |||
560 | llcp_sock = NULL; | ||
561 | |||
562 | sk_for_each(sk, node, &local->sockets.head) { | ||
563 | llcp_sock = nfc_llcp_sock(sk); | ||
564 | |||
565 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
566 | continue; | ||
567 | |||
568 | if (llcp_sock->service_name == NULL || | ||
569 | llcp_sock->service_name_len == 0) | ||
570 | continue; | ||
571 | |||
572 | if (llcp_sock->service_name_len != sn_len) | ||
573 | continue; | ||
574 | |||
575 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
576 | break; | ||
479 | } | 577 | } |
480 | 578 | ||
481 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | 579 | read_unlock(&local->sockets.lock); |
482 | 580 | ||
483 | mutex_unlock(&local->socket_lock); | 581 | if (llcp_sock == NULL) |
582 | return NULL; | ||
484 | 583 | ||
485 | return NULL; | 584 | sock_hold(&llcp_sock->sk); |
585 | |||
586 | return llcp_sock; | ||
486 | } | 587 | } |
487 | 588 | ||
488 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | 589 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) |
@@ -518,35 +619,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
518 | { | 619 | { |
519 | struct sock *new_sk, *parent; | 620 | struct sock *new_sk, *parent; |
520 | struct nfc_llcp_sock *sock, *new_sock; | 621 | struct nfc_llcp_sock *sock, *new_sock; |
521 | u8 dsap, ssap, bound_sap, reason; | 622 | u8 dsap, ssap, reason; |
522 | 623 | ||
523 | dsap = nfc_llcp_dsap(skb); | 624 | dsap = nfc_llcp_dsap(skb); |
524 | ssap = nfc_llcp_ssap(skb); | 625 | ssap = nfc_llcp_ssap(skb); |
525 | 626 | ||
526 | pr_debug("%d %d\n", dsap, ssap); | 627 | pr_debug("%d %d\n", dsap, ssap); |
527 | 628 | ||
528 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
529 | skb->len - LLCP_HEADER_SIZE); | ||
530 | |||
531 | if (dsap != LLCP_SAP_SDP) { | 629 | if (dsap != LLCP_SAP_SDP) { |
532 | bound_sap = dsap; | 630 | sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); |
533 | 631 | if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { | |
534 | mutex_lock(&local->socket_lock); | ||
535 | sock = local->sockets[dsap]; | ||
536 | if (sock == NULL) { | ||
537 | mutex_unlock(&local->socket_lock); | ||
538 | reason = LLCP_DM_NOBOUND; | 632 | reason = LLCP_DM_NOBOUND; |
539 | goto fail; | 633 | goto fail; |
540 | } | 634 | } |
541 | |||
542 | sock_hold(&sock->sk); | ||
543 | mutex_unlock(&local->socket_lock); | ||
544 | |||
545 | lock_sock(&sock->sk); | ||
546 | |||
547 | if (sock->dsap == LLCP_SAP_SDP && | ||
548 | sock->sk.sk_state == LLCP_LISTEN) | ||
549 | goto enqueue; | ||
550 | } else { | 635 | } else { |
551 | u8 *sn; | 636 | u8 *sn; |
552 | size_t sn_len; | 637 | size_t sn_len; |
@@ -559,40 +644,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
559 | 644 | ||
560 | pr_debug("Service name length %zu\n", sn_len); | 645 | pr_debug("Service name length %zu\n", sn_len); |
561 | 646 | ||
562 | mutex_lock(&local->socket_lock); | 647 | sock = nfc_llcp_sock_get_sn(local, sn, sn_len); |
563 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 648 | if (sock == NULL) { |
564 | bound_sap++) { | 649 | reason = LLCP_DM_NOBOUND; |
565 | sock = local->sockets[bound_sap]; | 650 | goto fail; |
566 | if (sock == NULL) | ||
567 | continue; | ||
568 | |||
569 | if (sock->service_name == NULL || | ||
570 | sock->service_name_len == 0) | ||
571 | continue; | ||
572 | |||
573 | if (sock->service_name_len != sn_len) | ||
574 | continue; | ||
575 | |||
576 | if (sock->dsap == LLCP_SAP_SDP && | ||
577 | sock->sk.sk_state == LLCP_LISTEN && | ||
578 | !memcmp(sn, sock->service_name, sn_len)) { | ||
579 | pr_debug("Found service name at SAP %d\n", | ||
580 | bound_sap); | ||
581 | sock_hold(&sock->sk); | ||
582 | mutex_unlock(&local->socket_lock); | ||
583 | |||
584 | lock_sock(&sock->sk); | ||
585 | |||
586 | goto enqueue; | ||
587 | } | ||
588 | } | 651 | } |
589 | mutex_unlock(&local->socket_lock); | ||
590 | } | 652 | } |
591 | 653 | ||
592 | reason = LLCP_DM_NOBOUND; | 654 | lock_sock(&sock->sk); |
593 | goto fail; | ||
594 | 655 | ||
595 | enqueue: | ||
596 | parent = &sock->sk; | 656 | parent = &sock->sk; |
597 | 657 | ||
598 | if (sk_acceptq_is_full(parent)) { | 658 | if (sk_acceptq_is_full(parent)) { |
@@ -612,15 +672,19 @@ enqueue: | |||
612 | 672 | ||
613 | new_sock = nfc_llcp_sock(new_sk); | 673 | new_sock = nfc_llcp_sock(new_sk); |
614 | new_sock->dev = local->dev; | 674 | new_sock->dev = local->dev; |
615 | new_sock->local = local; | 675 | new_sock->local = nfc_llcp_local_get(local); |
676 | new_sock->miu = local->remote_miu; | ||
616 | new_sock->nfc_protocol = sock->nfc_protocol; | 677 | new_sock->nfc_protocol = sock->nfc_protocol; |
617 | new_sock->ssap = bound_sap; | 678 | new_sock->ssap = sock->ssap; |
618 | new_sock->dsap = ssap; | 679 | new_sock->dsap = ssap; |
619 | new_sock->parent = parent; | 680 | new_sock->parent = parent; |
620 | 681 | ||
682 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], | ||
683 | skb->len - LLCP_HEADER_SIZE); | ||
684 | |||
621 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | 685 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); |
622 | 686 | ||
623 | list_add_tail(&new_sock->list, &sock->list); | 687 | nfc_llcp_sock_link(&local->sockets, new_sk); |
624 | 688 | ||
625 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | 689 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); |
626 | 690 | ||
@@ -654,12 +718,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
654 | 718 | ||
655 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 719 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
656 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 720 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
657 | local->remote_rw); | 721 | sock->rw); |
658 | 722 | ||
659 | /* Try to queue some I frames for transmission */ | 723 | /* Try to queue some I frames for transmission */ |
660 | while (sock->remote_ready && | 724 | while (sock->remote_ready && |
661 | skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { | 725 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { |
662 | struct sk_buff *pdu, *pending_pdu; | 726 | struct sk_buff *pdu; |
663 | 727 | ||
664 | pdu = skb_dequeue(&sock->tx_queue); | 728 | pdu = skb_dequeue(&sock->tx_queue); |
665 | if (pdu == NULL) | 729 | if (pdu == NULL) |
@@ -668,10 +732,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
668 | /* Update N(S)/N(R) */ | 732 | /* Update N(S)/N(R) */ |
669 | nfc_llcp_set_nrns(sock, pdu); | 733 | nfc_llcp_set_nrns(sock, pdu); |
670 | 734 | ||
671 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
672 | |||
673 | skb_queue_tail(&local->tx_queue, pdu); | 735 | skb_queue_tail(&local->tx_queue, pdu); |
674 | skb_queue_tail(&sock->tx_pending_queue, pending_pdu); | ||
675 | nr_frames++; | 736 | nr_frames++; |
676 | } | 737 | } |
677 | 738 | ||
@@ -728,11 +789,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
728 | 789 | ||
729 | llcp_sock->send_ack_n = nr; | 790 | llcp_sock->send_ack_n = nr; |
730 | 791 | ||
731 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) | 792 | /* Remove and free all skbs until ns == nr */ |
732 | if (nfc_llcp_ns(s) <= nr) { | 793 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { |
733 | skb_unlink(s, &llcp_sock->tx_pending_queue); | 794 | skb_unlink(s, &llcp_sock->tx_pending_queue); |
734 | kfree_skb(s); | 795 | kfree_skb(s); |
735 | } | 796 | |
797 | if (nfc_llcp_ns(s) == nr) | ||
798 | break; | ||
799 | } | ||
800 | |||
801 | /* Re-queue the remaining skbs for transmission */ | ||
802 | skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue, | ||
803 | s, tmp) { | ||
804 | skb_unlink(s, &llcp_sock->tx_pending_queue); | ||
805 | skb_queue_head(&local->tx_queue, s); | ||
806 | } | ||
736 | } | 807 | } |
737 | 808 | ||
738 | if (ptype == LLCP_PDU_RR) | 809 | if (ptype == LLCP_PDU_RR) |
@@ -740,7 +811,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
740 | else if (ptype == LLCP_PDU_RNR) | 811 | else if (ptype == LLCP_PDU_RNR) |
741 | llcp_sock->remote_ready = false; | 812 | llcp_sock->remote_ready = false; |
742 | 813 | ||
743 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0) | 814 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I) |
744 | nfc_llcp_send_rr(llcp_sock); | 815 | nfc_llcp_send_rr(llcp_sock); |
745 | 816 | ||
746 | release_sock(sk); | 817 | release_sock(sk); |
@@ -791,11 +862,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
791 | dsap = nfc_llcp_dsap(skb); | 862 | dsap = nfc_llcp_dsap(skb); |
792 | ssap = nfc_llcp_ssap(skb); | 863 | ssap = nfc_llcp_ssap(skb); |
793 | 864 | ||
794 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | 865 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); |
795 | |||
796 | if (llcp_sock == NULL) | ||
797 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
798 | |||
799 | if (llcp_sock == NULL) { | 866 | if (llcp_sock == NULL) { |
800 | pr_err("Invalid CC\n"); | 867 | pr_err("Invalid CC\n"); |
801 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | 868 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); |
@@ -803,11 +870,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
803 | return; | 870 | return; |
804 | } | 871 | } |
805 | 872 | ||
806 | llcp_sock->dsap = ssap; | ||
807 | sk = &llcp_sock->sk; | 873 | sk = &llcp_sock->sk; |
808 | 874 | ||
809 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 875 | /* Unlink from connecting and link to the client array */ |
810 | skb->len - LLCP_HEADER_SIZE); | 876 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
877 | nfc_llcp_sock_link(&local->sockets, sk); | ||
878 | llcp_sock->dsap = ssap; | ||
879 | |||
880 | nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE], | ||
881 | skb->len - LLCP_HEADER_SIZE); | ||
811 | 882 | ||
812 | sk->sk_state = LLCP_CONNECTED; | 883 | sk->sk_state = LLCP_CONNECTED; |
813 | sk->sk_state_change(sk); | 884 | sk->sk_state_change(sk); |
@@ -891,6 +962,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
891 | return; | 962 | return; |
892 | } | 963 | } |
893 | 964 | ||
965 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
966 | { | ||
967 | struct nfc_llcp_local *local; | ||
968 | |||
969 | local = nfc_llcp_find_local(dev); | ||
970 | if (local == NULL) | ||
971 | return -ENODEV; | ||
972 | |||
973 | local->rx_pending = skb_get(skb); | ||
974 | del_timer(&local->link_timer); | ||
975 | queue_work(local->rx_wq, &local->rx_work); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
894 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | 980 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) |
895 | { | 981 | { |
896 | struct nfc_llcp_local *local; | 982 | struct nfc_llcp_local *local; |
@@ -943,8 +1029,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
943 | 1029 | ||
944 | local->dev = ndev; | 1030 | local->dev = ndev; |
945 | INIT_LIST_HEAD(&local->list); | 1031 | INIT_LIST_HEAD(&local->list); |
1032 | kref_init(&local->ref); | ||
946 | mutex_init(&local->sdp_lock); | 1033 | mutex_init(&local->sdp_lock); |
947 | mutex_init(&local->socket_lock); | ||
948 | init_timer(&local->link_timer); | 1034 | init_timer(&local->link_timer); |
949 | local->link_timer.data = (unsigned long) local; | 1035 | local->link_timer.data = (unsigned long) local; |
950 | local->link_timer.function = nfc_llcp_symm_timer; | 1036 | local->link_timer.function = nfc_llcp_symm_timer; |
@@ -984,11 +1070,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
984 | goto err_rx_wq; | 1070 | goto err_rx_wq; |
985 | } | 1071 | } |
986 | 1072 | ||
1073 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | ||
1074 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | ||
1075 | |||
987 | nfc_llcp_build_gb(local); | 1076 | nfc_llcp_build_gb(local); |
988 | 1077 | ||
989 | local->remote_miu = LLCP_DEFAULT_MIU; | 1078 | local->remote_miu = LLCP_DEFAULT_MIU; |
990 | local->remote_lto = LLCP_DEFAULT_LTO; | 1079 | local->remote_lto = LLCP_DEFAULT_LTO; |
991 | local->remote_rw = LLCP_DEFAULT_RW; | ||
992 | 1080 | ||
993 | list_add(&llcp_devices, &local->list); | 1081 | list_add(&llcp_devices, &local->list); |
994 | 1082 | ||
@@ -1015,14 +1103,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1015 | return; | 1103 | return; |
1016 | } | 1104 | } |
1017 | 1105 | ||
1018 | list_del(&local->list); | 1106 | nfc_llcp_local_put(local); |
1019 | nfc_llcp_socket_release(local); | ||
1020 | del_timer_sync(&local->link_timer); | ||
1021 | skb_queue_purge(&local->tx_queue); | ||
1022 | destroy_workqueue(local->tx_wq); | ||
1023 | destroy_workqueue(local->rx_wq); | ||
1024 | kfree_skb(local->rx_pending); | ||
1025 | kfree(local); | ||
1026 | } | 1107 | } |
1027 | 1108 | ||
1028 | int __init nfc_llcp_init(void) | 1109 | int __init nfc_llcp_init(void) |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 50680ce5ae43..7286c86982ff 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -40,12 +40,18 @@ enum llcp_state { | |||
40 | 40 | ||
41 | struct nfc_llcp_sock; | 41 | struct nfc_llcp_sock; |
42 | 42 | ||
43 | struct llcp_sock_list { | ||
44 | struct hlist_head head; | ||
45 | rwlock_t lock; | ||
46 | }; | ||
47 | |||
43 | struct nfc_llcp_local { | 48 | struct nfc_llcp_local { |
44 | struct list_head list; | 49 | struct list_head list; |
45 | struct nfc_dev *dev; | 50 | struct nfc_dev *dev; |
46 | 51 | ||
52 | struct kref ref; | ||
53 | |||
47 | struct mutex sdp_lock; | 54 | struct mutex sdp_lock; |
48 | struct mutex socket_lock; | ||
49 | 55 | ||
50 | struct timer_list link_timer; | 56 | struct timer_list link_timer; |
51 | struct sk_buff_head tx_queue; | 57 | struct sk_buff_head tx_queue; |
@@ -77,24 +83,26 @@ struct nfc_llcp_local { | |||
77 | u16 remote_lto; | 83 | u16 remote_lto; |
78 | u8 remote_opt; | 84 | u8 remote_opt; |
79 | u16 remote_wks; | 85 | u16 remote_wks; |
80 | u8 remote_rw; | ||
81 | 86 | ||
82 | /* sockets array */ | 87 | /* sockets array */ |
83 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | 88 | struct llcp_sock_list sockets; |
89 | struct llcp_sock_list connecting_sockets; | ||
84 | }; | 90 | }; |
85 | 91 | ||
86 | struct nfc_llcp_sock { | 92 | struct nfc_llcp_sock { |
87 | struct sock sk; | 93 | struct sock sk; |
88 | struct list_head list; | ||
89 | struct nfc_dev *dev; | 94 | struct nfc_dev *dev; |
90 | struct nfc_llcp_local *local; | 95 | struct nfc_llcp_local *local; |
91 | u32 target_idx; | 96 | u32 target_idx; |
92 | u32 nfc_protocol; | 97 | u32 nfc_protocol; |
93 | 98 | ||
99 | /* Link parameters */ | ||
94 | u8 ssap; | 100 | u8 ssap; |
95 | u8 dsap; | 101 | u8 dsap; |
96 | char *service_name; | 102 | char *service_name; |
97 | size_t service_name_len; | 103 | size_t service_name_len; |
104 | u8 rw; | ||
105 | u16 miu; | ||
98 | 106 | ||
99 | /* Link variables */ | 107 | /* Link variables */ |
100 | u8 send_n; | 108 | u8 send_n; |
@@ -164,7 +172,11 @@ struct nfc_llcp_sock { | |||
164 | #define LLCP_DM_REJ 0x03 | 172 | #define LLCP_DM_REJ 0x03 |
165 | 173 | ||
166 | 174 | ||
175 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); | ||
176 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); | ||
167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 177 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
178 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | ||
179 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | ||
168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 180 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
169 | struct nfc_llcp_sock *sock); | 181 | struct nfc_llcp_sock *sock); |
170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 182 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); |
@@ -179,8 +191,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); | |||
179 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | 191 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); |
180 | 192 | ||
181 | /* TLV API */ | 193 | /* TLV API */ |
182 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 194 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
183 | u8 *tlv_array, u16 tlv_array_len); | 195 | u8 *tlv_array, u16 tlv_array_len); |
196 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
197 | u8 *tlv_array, u16 tlv_array_len); | ||
184 | 198 | ||
185 | /* Commands API */ | 199 | /* Commands API */ |
186 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 200 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 3f339b19d140..30e3cc71be7a 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | llcp_sock->dev = dev; | 113 | llcp_sock->dev = dev; |
114 | llcp_sock->local = local; | 114 | llcp_sock->local = nfc_llcp_local_get(local); |
115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | 115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
116 | llcp_sock->service_name_len = min_t(unsigned int, | 116 | llcp_sock->service_name_len = min_t(unsigned int, |
117 | llcp_addr.service_name_len, | 117 | llcp_addr.service_name_len, |
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
125 | goto put_dev; | 125 | goto put_dev; |
126 | 126 | ||
127 | local->sockets[llcp_sock->ssap] = llcp_sock; | 127 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 128 | ||
129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | 129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); |
130 | 130 | ||
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock) | |||
379 | goto out; | 379 | goto out; |
380 | } | 380 | } |
381 | 381 | ||
382 | mutex_lock(&local->socket_lock); | ||
383 | |||
384 | if (llcp_sock == local->sockets[llcp_sock->ssap]) | ||
385 | local->sockets[llcp_sock->ssap] = NULL; | ||
386 | else | ||
387 | list_del_init(&llcp_sock->list); | ||
388 | |||
389 | mutex_unlock(&local->socket_lock); | ||
390 | |||
391 | lock_sock(sk); | 382 | lock_sock(sk); |
392 | 383 | ||
393 | /* Send a DISC */ | 384 | /* Send a DISC */ |
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock) | |||
412 | } | 403 | } |
413 | } | 404 | } |
414 | 405 | ||
415 | /* Freeing the SAP */ | 406 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
416 | if ((sk->sk_state == LLCP_CONNECTED | ||
417 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
418 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) | ||
419 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
420 | 407 | ||
421 | release_sock(sk); | 408 | release_sock(sk); |
422 | 409 | ||
410 | nfc_llcp_sock_unlink(&local->sockets, sk); | ||
411 | |||
423 | out: | 412 | out: |
424 | sock_orphan(sk); | 413 | sock_orphan(sk); |
425 | sock_put(sk); | 414 | sock_put(sk); |
@@ -487,7 +476,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
487 | } | 476 | } |
488 | 477 | ||
489 | llcp_sock->dev = dev; | 478 | llcp_sock->dev = dev; |
490 | llcp_sock->local = local; | 479 | llcp_sock->local = nfc_llcp_local_get(local); |
480 | llcp_sock->miu = llcp_sock->local->remote_miu; | ||
491 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 481 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
492 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 482 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
493 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
@@ -505,21 +495,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
505 | llcp_sock->service_name_len, | 495 | llcp_sock->service_name_len, |
506 | GFP_KERNEL); | 496 | GFP_KERNEL); |
507 | 497 | ||
508 | local->sockets[llcp_sock->ssap] = llcp_sock; | 498 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
509 | 499 | ||
510 | ret = nfc_llcp_send_connect(llcp_sock); | 500 | ret = nfc_llcp_send_connect(llcp_sock); |
511 | if (ret) | 501 | if (ret) |
512 | goto put_dev; | 502 | goto sock_unlink; |
513 | 503 | ||
514 | ret = sock_wait_state(sk, LLCP_CONNECTED, | 504 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 505 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
516 | if (ret) | 506 | if (ret) |
517 | goto put_dev; | 507 | goto sock_unlink; |
518 | 508 | ||
519 | release_sock(sk); | 509 | release_sock(sk); |
520 | 510 | ||
521 | return 0; | 511 | return 0; |
522 | 512 | ||
513 | sock_unlink: | ||
514 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
515 | |||
516 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
517 | |||
523 | put_dev: | 518 | put_dev: |
524 | nfc_put_device(dev); | 519 | nfc_put_device(dev); |
525 | 520 | ||
@@ -684,13 +679,14 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
684 | 679 | ||
685 | llcp_sock->ssap = 0; | 680 | llcp_sock->ssap = 0; |
686 | llcp_sock->dsap = LLCP_SAP_SDP; | 681 | llcp_sock->dsap = LLCP_SAP_SDP; |
682 | llcp_sock->rw = LLCP_DEFAULT_RW; | ||
683 | llcp_sock->miu = LLCP_DEFAULT_MIU; | ||
687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 684 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 685 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
689 | llcp_sock->remote_ready = 1; | 686 | llcp_sock->remote_ready = 1; |
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 687 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 688 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 689 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
693 | INIT_LIST_HEAD(&llcp_sock->list); | ||
694 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 690 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
695 | 691 | ||
696 | if (sock != NULL) | 692 | if (sock != NULL) |
@@ -701,8 +697,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
701 | 697 | ||
702 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 698 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) |
703 | { | 699 | { |
704 | struct nfc_llcp_local *local = sock->local; | ||
705 | |||
706 | kfree(sock->service_name); | 700 | kfree(sock->service_name); |
707 | 701 | ||
708 | skb_queue_purge(&sock->tx_queue); | 702 | skb_queue_purge(&sock->tx_queue); |
@@ -711,12 +705,9 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
711 | 705 | ||
712 | list_del_init(&sock->accept_queue); | 706 | list_del_init(&sock->accept_queue); |
713 | 707 | ||
714 | if (local != NULL && sock == local->sockets[sock->ssap]) | ||
715 | local->sockets[sock->ssap] = NULL; | ||
716 | else | ||
717 | list_del_init(&sock->list); | ||
718 | |||
719 | sock->parent = NULL; | 708 | sock->parent = NULL; |
709 | |||
710 | nfc_llcp_local_put(sock->local); | ||
720 | } | 711 | } |
721 | 712 | ||
722 | static int llcp_sock_create(struct net *net, struct socket *sock, | 713 | static int llcp_sock_create(struct net *net, struct socket *sock, |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index d560e6f13072..766a02b1dfa1 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) | |||
387 | return nci_close_device(ndev); | 387 | return nci_close_device(ndev); |
388 | } | 388 | } |
389 | 389 | ||
390 | static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | 390 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
391 | __u32 im_protocols, __u32 tm_protocols) | ||
391 | { | 392 | { |
392 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 393 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
393 | int rc; | 394 | int rc; |
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
413 | return -EBUSY; | 414 | return -EBUSY; |
414 | } | 415 | } |
415 | 416 | ||
416 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | 417 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, |
417 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 418 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
418 | 419 | ||
419 | if (!rc) | 420 | if (!rc) |
420 | ndev->poll_prots = protocols; | 421 | ndev->poll_prots = im_protocols; |
421 | 422 | ||
422 | return rc; | 423 | return rc; |
423 | } | 424 | } |
@@ -521,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
521 | } | 522 | } |
522 | } | 523 | } |
523 | 524 | ||
524 | static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 525 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
525 | struct sk_buff *skb, | 526 | struct sk_buff *skb, |
526 | data_exchange_cb_t cb, void *cb_context) | 527 | data_exchange_cb_t cb, void *cb_context) |
527 | { | 528 | { |
528 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 529 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
529 | int rc; | 530 | int rc; |
@@ -556,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
556 | .stop_poll = nci_stop_poll, | 557 | .stop_poll = nci_stop_poll, |
557 | .activate_target = nci_activate_target, | 558 | .activate_target = nci_activate_target, |
558 | .deactivate_target = nci_deactivate_target, | 559 | .deactivate_target = nci_deactivate_target, |
559 | .data_exchange = nci_data_exchange, | 560 | .im_transceive = nci_transceive, |
560 | }; | 561 | }; |
561 | 562 | ||
562 | /* ---- Interface to NCI drivers ---- */ | 563 | /* ---- Interface to NCI drivers ---- */ |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 581d419083aa..03c31db38f12 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | 49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, |
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | 50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, |
51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
52 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | ||
53 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 56 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -219,6 +221,68 @@ free_msg: | |||
219 | return -EMSGSIZE; | 221 | return -EMSGSIZE; |
220 | } | 222 | } |
221 | 223 | ||
224 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) | ||
225 | { | ||
226 | struct sk_buff *msg; | ||
227 | void *hdr; | ||
228 | |||
229 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
230 | if (!msg) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
234 | NFC_EVENT_TM_ACTIVATED); | ||
235 | if (!hdr) | ||
236 | goto free_msg; | ||
237 | |||
238 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
239 | goto nla_put_failure; | ||
240 | if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) | ||
241 | goto nla_put_failure; | ||
242 | |||
243 | genlmsg_end(msg, hdr); | ||
244 | |||
245 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | nla_put_failure: | ||
250 | genlmsg_cancel(msg, hdr); | ||
251 | free_msg: | ||
252 | nlmsg_free(msg); | ||
253 | return -EMSGSIZE; | ||
254 | } | ||
255 | |||
256 | int nfc_genl_tm_deactivated(struct nfc_dev *dev) | ||
257 | { | ||
258 | struct sk_buff *msg; | ||
259 | void *hdr; | ||
260 | |||
261 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
262 | if (!msg) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
266 | NFC_EVENT_TM_DEACTIVATED); | ||
267 | if (!hdr) | ||
268 | goto free_msg; | ||
269 | |||
270 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
271 | goto nla_put_failure; | ||
272 | |||
273 | genlmsg_end(msg, hdr); | ||
274 | |||
275 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | nla_put_failure: | ||
280 | genlmsg_cancel(msg, hdr); | ||
281 | free_msg: | ||
282 | nlmsg_free(msg); | ||
283 | return -EMSGSIZE; | ||
284 | } | ||
285 | |||
222 | int nfc_genl_device_added(struct nfc_dev *dev) | 286 | int nfc_genl_device_added(struct nfc_dev *dev) |
223 | { | 287 | { |
224 | struct sk_buff *msg; | 288 | struct sk_buff *msg; |
@@ -519,16 +583,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
519 | struct nfc_dev *dev; | 583 | struct nfc_dev *dev; |
520 | int rc; | 584 | int rc; |
521 | u32 idx; | 585 | u32 idx; |
522 | u32 protocols; | 586 | u32 im_protocols = 0, tm_protocols = 0; |
523 | 587 | ||
524 | pr_debug("Poll start\n"); | 588 | pr_debug("Poll start\n"); |
525 | 589 | ||
526 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 590 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
527 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 591 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && |
592 | !info->attrs[NFC_ATTR_PROTOCOLS]) && | ||
593 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) | ||
528 | return -EINVAL; | 594 | return -EINVAL; |
529 | 595 | ||
530 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 596 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
531 | protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | 597 | |
598 | if (info->attrs[NFC_ATTR_TM_PROTOCOLS]) | ||
599 | tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]); | ||
600 | |||
601 | if (info->attrs[NFC_ATTR_IM_PROTOCOLS]) | ||
602 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]); | ||
603 | else if (info->attrs[NFC_ATTR_PROTOCOLS]) | ||
604 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | ||
532 | 605 | ||
533 | dev = nfc_get_device(idx); | 606 | dev = nfc_get_device(idx); |
534 | if (!dev) | 607 | if (!dev) |
@@ -536,7 +609,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
536 | 609 | ||
537 | mutex_lock(&dev->genl_data.genl_data_mutex); | 610 | mutex_lock(&dev->genl_data.genl_data_mutex); |
538 | 611 | ||
539 | rc = nfc_start_poll(dev, protocols); | 612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); |
540 | if (!rc) | 613 | if (!rc) |
541 | dev->genl_data.poll_req_pid = info->snd_pid; | 614 | dev->genl_data.poll_req_pid = info->snd_pid; |
542 | 615 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 3dd4232ae664..c5e42b79a418 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev); | |||
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | 55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); |
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | ||
58 | int __init nfc_llcp_init(void); | 59 | int __init nfc_llcp_init(void); |
59 | void nfc_llcp_exit(void); | 60 | void nfc_llcp_exit(void); |
60 | 61 | ||
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len) | |||
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
92 | 93 | ||
94 | static inline int nfc_llcp_data_received(struct nfc_dev *dev, | ||
95 | struct sk_buff *skb) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
93 | static inline int nfc_llcp_init(void) | 100 | static inline int nfc_llcp_init(void) |
94 | { | 101 | { |
95 | return 0; | 102 | return 0; |
@@ -128,6 +135,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | |||
128 | u8 comm_mode, u8 rf_mode); | 135 | u8 comm_mode, u8 rf_mode); |
129 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | 136 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); |
130 | 137 | ||
138 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | ||
139 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | ||
140 | |||
131 | struct nfc_dev *nfc_get_device(unsigned int idx); | 141 | struct nfc_dev *nfc_get_device(unsigned int idx); |
132 | 142 | ||
133 | static inline void nfc_put_device(struct nfc_dev *dev) | 143 | static inline void nfc_put_device(struct nfc_dev *dev) |
@@ -158,7 +168,7 @@ int nfc_dev_up(struct nfc_dev *dev); | |||
158 | 168 | ||
159 | int nfc_dev_down(struct nfc_dev *dev); | 169 | int nfc_dev_down(struct nfc_dev *dev); |
160 | 170 | ||
161 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 171 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols); |
162 | 172 | ||
163 | int nfc_stop_poll(struct nfc_dev *dev); | 173 | int nfc_stop_poll(struct nfc_dev *dev); |
164 | 174 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index f974961754ca..752b72360ebc 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -325,7 +325,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked) | |||
325 | 325 | ||
326 | rfkill_global_states[type].cur = blocked; | 326 | rfkill_global_states[type].cur = blocked; |
327 | list_for_each_entry(rfkill, &rfkill_list, node) { | 327 | list_for_each_entry(rfkill, &rfkill_list, node) { |
328 | if (rfkill->type != type) | 328 | if (rfkill->type != type && type != RFKILL_TYPE_ALL) |
329 | continue; | 329 | continue; |
330 | 330 | ||
331 | rfkill_set_block(rfkill, blocked); | 331 | rfkill_set_block(rfkill, blocked); |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 2e4444fedbe0..4d2b1ec6516f 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -114,24 +114,10 @@ config CFG80211_WEXT | |||
114 | bool "cfg80211 wireless extensions compatibility" | 114 | bool "cfg80211 wireless extensions compatibility" |
115 | depends on CFG80211 | 115 | depends on CFG80211 |
116 | select WEXT_CORE | 116 | select WEXT_CORE |
117 | default y | ||
118 | help | 117 | help |
119 | Enable this option if you need old userspace for wireless | 118 | Enable this option if you need old userspace for wireless |
120 | extensions with cfg80211-based drivers. | 119 | extensions with cfg80211-based drivers. |
121 | 120 | ||
122 | config WIRELESS_EXT_SYSFS | ||
123 | bool "Wireless extensions sysfs files" | ||
124 | depends on WEXT_CORE && SYSFS | ||
125 | help | ||
126 | This option enables the deprecated wireless statistics | ||
127 | files in /sys/class/net/*/wireless/. The same information | ||
128 | is available via the ioctls as well. | ||
129 | |||
130 | Say N. If you know you have ancient tools requiring it, | ||
131 | like very old versions of hal (prior to 0.5.12 release), | ||
132 | say Y and update the tools as soon as possible as this | ||
133 | option will be removed soon. | ||
134 | |||
135 | config LIB80211 | 121 | config LIB80211 |
136 | tristate "Common routines for IEEE802.11 drivers" | 122 | tristate "Common routines for IEEE802.11 drivers" |
137 | default n | 123 | default n |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 884801ac4dd0..c1999e45a07c 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -60,7 +60,7 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | |||
60 | diff = -20; | 60 | diff = -20; |
61 | break; | 61 | break; |
62 | default: | 62 | default: |
63 | return false; | 63 | return true; |
64 | } | 64 | } |
65 | 65 | ||
66 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); | 66 | sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff); |
@@ -78,60 +78,17 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | |||
78 | } | 78 | } |
79 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); | 79 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); |
80 | 80 | ||
81 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 81 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
82 | struct wireless_dev *wdev, int freq, | 82 | int freq, enum nl80211_channel_type chantype) |
83 | enum nl80211_channel_type channel_type) | ||
84 | { | 83 | { |
85 | struct ieee80211_channel *chan; | 84 | struct ieee80211_channel *chan; |
86 | int result; | ||
87 | |||
88 | if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
89 | wdev = NULL; | ||
90 | |||
91 | if (wdev) { | ||
92 | ASSERT_WDEV_LOCK(wdev); | ||
93 | |||
94 | if (!netif_running(wdev->netdev)) | ||
95 | return -ENETDOWN; | ||
96 | } | ||
97 | 85 | ||
98 | if (!rdev->ops->set_channel) | 86 | if (!rdev->ops->set_monitor_channel) |
99 | return -EOPNOTSUPP; | 87 | return -EOPNOTSUPP; |
100 | 88 | ||
101 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 89 | chan = rdev_freq_to_chan(rdev, freq, chantype); |
102 | if (!chan) | 90 | if (!chan) |
103 | return -EINVAL; | 91 | return -EINVAL; |
104 | 92 | ||
105 | /* Both channels should be able to initiate communication */ | 93 | return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); |
106 | if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC || | ||
107 | wdev->iftype == NL80211_IFTYPE_AP || | ||
108 | wdev->iftype == NL80211_IFTYPE_AP_VLAN || | ||
109 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | ||
110 | wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
111 | switch (channel_type) { | ||
112 | case NL80211_CHAN_HT40PLUS: | ||
113 | case NL80211_CHAN_HT40MINUS: | ||
114 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan, | ||
115 | channel_type)) { | ||
116 | printk(KERN_DEBUG | ||
117 | "cfg80211: Secondary channel not " | ||
118 | "allowed to initiate communication\n"); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | break; | ||
122 | default: | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | result = rdev->ops->set_channel(&rdev->wiphy, | ||
128 | wdev ? wdev->netdev : NULL, | ||
129 | chan, channel_type); | ||
130 | if (result) | ||
131 | return result; | ||
132 | |||
133 | if (wdev) | ||
134 | wdev->channel = chan; | ||
135 | |||
136 | return 0; | ||
137 | } | 94 | } |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 8523f3878677..9348a47562a4 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -303,14 +303,17 @@ extern const struct mesh_config default_mesh_config; | |||
303 | extern const struct mesh_setup default_mesh_setup; | 303 | extern const struct mesh_setup default_mesh_setup; |
304 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 304 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
305 | struct net_device *dev, | 305 | struct net_device *dev, |
306 | const struct mesh_setup *setup, | 306 | struct mesh_setup *setup, |
307 | const struct mesh_config *conf); | 307 | const struct mesh_config *conf); |
308 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 308 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
309 | struct net_device *dev, | 309 | struct net_device *dev, |
310 | const struct mesh_setup *setup, | 310 | struct mesh_setup *setup, |
311 | const struct mesh_config *conf); | 311 | const struct mesh_config *conf); |
312 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 312 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
313 | struct net_device *dev); | 313 | struct net_device *dev); |
314 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | ||
315 | struct wireless_dev *wdev, int freq, | ||
316 | enum nl80211_channel_type channel_type); | ||
314 | 317 | ||
315 | /* MLME */ | 318 | /* MLME */ |
316 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 319 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
@@ -441,9 +444,8 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, | |||
441 | struct ieee80211_channel * | 444 | struct ieee80211_channel * |
442 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 445 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
443 | int freq, enum nl80211_channel_type channel_type); | 446 | int freq, enum nl80211_channel_type channel_type); |
444 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 447 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
445 | struct wireless_dev *wdev, int freq, | 448 | int freq, enum nl80211_channel_type chantype); |
446 | enum nl80211_channel_type channel_type); | ||
447 | 449 | ||
448 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 450 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |
449 | const u8 *rates, unsigned int n_rates, | 451 | const u8 *rates, unsigned int n_rates, |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 2749cb86b462..b44c736bf9cf 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -65,6 +65,9 @@ const struct mesh_config default_mesh_config = { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | const struct mesh_setup default_mesh_setup = { | 67 | const struct mesh_setup default_mesh_setup = { |
68 | /* cfg80211_join_mesh() will pick a channel if needed */ | ||
69 | .channel = NULL, | ||
70 | .channel_type = NL80211_CHAN_NO_HT, | ||
68 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | 71 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, |
69 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 72 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
70 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 73 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
@@ -75,7 +78,7 @@ const struct mesh_setup default_mesh_setup = { | |||
75 | 78 | ||
76 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 79 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
77 | struct net_device *dev, | 80 | struct net_device *dev, |
78 | const struct mesh_setup *setup, | 81 | struct mesh_setup *setup, |
79 | const struct mesh_config *conf) | 82 | const struct mesh_config *conf) |
80 | { | 83 | { |
81 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 84 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -101,6 +104,51 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
101 | if (!rdev->ops->join_mesh) | 104 | if (!rdev->ops->join_mesh) |
102 | return -EOPNOTSUPP; | 105 | return -EOPNOTSUPP; |
103 | 106 | ||
107 | if (!setup->channel) { | ||
108 | /* if no channel explicitly given, use preset channel */ | ||
109 | setup->channel = wdev->preset_chan; | ||
110 | setup->channel_type = wdev->preset_chantype; | ||
111 | } | ||
112 | |||
113 | if (!setup->channel) { | ||
114 | /* if we don't have that either, use the first usable channel */ | ||
115 | enum ieee80211_band band; | ||
116 | |||
117 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
118 | struct ieee80211_supported_band *sband; | ||
119 | struct ieee80211_channel *chan; | ||
120 | int i; | ||
121 | |||
122 | sband = rdev->wiphy.bands[band]; | ||
123 | if (!sband) | ||
124 | continue; | ||
125 | |||
126 | for (i = 0; i < sband->n_channels; i++) { | ||
127 | chan = &sband->channels[i]; | ||
128 | if (chan->flags & (IEEE80211_CHAN_NO_IBSS | | ||
129 | IEEE80211_CHAN_PASSIVE_SCAN | | ||
130 | IEEE80211_CHAN_DISABLED | | ||
131 | IEEE80211_CHAN_RADAR)) | ||
132 | continue; | ||
133 | setup->channel = chan; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | if (setup->channel) | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | /* no usable channel ... */ | ||
142 | if (!setup->channel) | ||
143 | return -EINVAL; | ||
144 | |||
145 | setup->channel_type = NL80211_CHAN_NO_HT; | ||
146 | } | ||
147 | |||
148 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel, | ||
149 | setup->channel_type)) | ||
150 | return -EINVAL; | ||
151 | |||
104 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); | 152 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); |
105 | if (!err) { | 153 | if (!err) { |
106 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 154 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
@@ -112,7 +160,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
112 | 160 | ||
113 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 161 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
114 | struct net_device *dev, | 162 | struct net_device *dev, |
115 | const struct mesh_setup *setup, | 163 | struct mesh_setup *setup, |
116 | const struct mesh_config *conf) | 164 | const struct mesh_config *conf) |
117 | { | 165 | { |
118 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 166 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -125,6 +173,45 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
125 | return err; | 173 | return err; |
126 | } | 174 | } |
127 | 175 | ||
176 | int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | ||
177 | struct wireless_dev *wdev, int freq, | ||
178 | enum nl80211_channel_type channel_type) | ||
179 | { | ||
180 | struct ieee80211_channel *channel; | ||
181 | |||
182 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
183 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
184 | channel, | ||
185 | channel_type)) { | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Workaround for libertas (only!), it puts the interface | ||
191 | * into mesh mode but doesn't implement join_mesh. Instead, | ||
192 | * it is configured via sysfs and then joins the mesh when | ||
193 | * you set the channel. Note that the libertas mesh isn't | ||
194 | * compatible with 802.11 mesh. | ||
195 | */ | ||
196 | if (rdev->ops->libertas_set_mesh_channel) { | ||
197 | if (channel_type != NL80211_CHAN_NO_HT) | ||
198 | return -EINVAL; | ||
199 | |||
200 | if (!netif_running(wdev->netdev)) | ||
201 | return -ENETDOWN; | ||
202 | return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, | ||
203 | wdev->netdev, | ||
204 | channel); | ||
205 | } | ||
206 | |||
207 | if (wdev->mesh_id_len) | ||
208 | return -EBUSY; | ||
209 | |||
210 | wdev->preset_chan = channel; | ||
211 | wdev->preset_chantype = channel_type; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
128 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | 215 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, |
129 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) | 216 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) |
130 | { | 217 | { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index eb90988bbd36..da4406f11929 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -947,8 +947,6 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | |||
947 | if (WARN_ON(!chan)) | 947 | if (WARN_ON(!chan)) |
948 | goto out; | 948 | goto out; |
949 | 949 | ||
950 | wdev->channel = chan; | ||
951 | |||
952 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); | 950 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); |
953 | out: | 951 | out: |
954 | wdev_unlock(wdev); | 952 | wdev_unlock(wdev); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 206465dc0cab..7ae54b82291f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -921,7 +921,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | 921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) |
922 | goto nla_put_failure; | 922 | goto nla_put_failure; |
923 | } | 923 | } |
924 | CMD(set_channel, SET_CHANNEL); | 924 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || |
925 | dev->ops->join_mesh) { | ||
926 | i++; | ||
927 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
928 | goto nla_put_failure; | ||
929 | } | ||
925 | CMD(set_wds_peer, SET_WDS_PEER); | 930 | CMD(set_wds_peer, SET_WDS_PEER); |
926 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 931 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
927 | CMD(tdls_mgmt, TDLS_MGMT); | 932 | CMD(tdls_mgmt, TDLS_MGMT); |
@@ -1162,18 +1167,22 @@ static int parse_txq_params(struct nlattr *tb[], | |||
1162 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | 1167 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) |
1163 | { | 1168 | { |
1164 | /* | 1169 | /* |
1165 | * You can only set the channel explicitly for AP, mesh | 1170 | * You can only set the channel explicitly for WDS interfaces, |
1166 | * and WDS type interfaces; all others have their channel | 1171 | * all others have their channel managed via their respective |
1167 | * managed via their respective "establish a connection" | 1172 | * "establish a connection" command (connect, join, ...) |
1168 | * command (connect, join, ...) | 1173 | * |
1174 | * For AP/GO and mesh mode, the channel can be set with the | ||
1175 | * channel userspace API, but is only stored and passed to the | ||
1176 | * low-level driver when the AP starts or the mesh is joined. | ||
1177 | * This is for backward compatibility, userspace can also give | ||
1178 | * the channel in the start-ap or join-mesh commands instead. | ||
1169 | * | 1179 | * |
1170 | * Monitors are special as they are normally slaved to | 1180 | * Monitors are special as they are normally slaved to |
1171 | * whatever else is going on, so they behave as though | 1181 | * whatever else is going on, so they have their own special |
1172 | * you tried setting the wiphy channel itself. | 1182 | * operation to set the monitor channel if possible. |
1173 | */ | 1183 | */ |
1174 | return !wdev || | 1184 | return !wdev || |
1175 | wdev->iftype == NL80211_IFTYPE_AP || | 1185 | wdev->iftype == NL80211_IFTYPE_AP || |
1176 | wdev->iftype == NL80211_IFTYPE_WDS || | ||
1177 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | 1186 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || |
1178 | wdev->iftype == NL80211_IFTYPE_MONITOR || | 1187 | wdev->iftype == NL80211_IFTYPE_MONITOR || |
1179 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | 1188 | wdev->iftype == NL80211_IFTYPE_P2P_GO; |
@@ -1204,9 +1213,14 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1204 | struct wireless_dev *wdev, | 1213 | struct wireless_dev *wdev, |
1205 | struct genl_info *info) | 1214 | struct genl_info *info) |
1206 | { | 1215 | { |
1216 | struct ieee80211_channel *channel; | ||
1207 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 1217 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
1208 | u32 freq; | 1218 | u32 freq; |
1209 | int result; | 1219 | int result; |
1220 | enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; | ||
1221 | |||
1222 | if (wdev) | ||
1223 | iftype = wdev->iftype; | ||
1210 | 1224 | ||
1211 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 1225 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
1212 | return -EINVAL; | 1226 | return -EINVAL; |
@@ -1221,12 +1235,32 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1221 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 1235 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
1222 | 1236 | ||
1223 | mutex_lock(&rdev->devlist_mtx); | 1237 | mutex_lock(&rdev->devlist_mtx); |
1224 | if (wdev) { | 1238 | switch (iftype) { |
1225 | wdev_lock(wdev); | 1239 | case NL80211_IFTYPE_AP: |
1226 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); | 1240 | case NL80211_IFTYPE_P2P_GO: |
1227 | wdev_unlock(wdev); | 1241 | if (wdev->beacon_interval) { |
1228 | } else { | 1242 | result = -EBUSY; |
1229 | result = cfg80211_set_freq(rdev, NULL, freq, channel_type); | 1243 | break; |
1244 | } | ||
1245 | channel = rdev_freq_to_chan(rdev, freq, channel_type); | ||
1246 | if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, | ||
1247 | channel, | ||
1248 | channel_type)) { | ||
1249 | result = -EINVAL; | ||
1250 | break; | ||
1251 | } | ||
1252 | wdev->preset_chan = channel; | ||
1253 | wdev->preset_chantype = channel_type; | ||
1254 | result = 0; | ||
1255 | break; | ||
1256 | case NL80211_IFTYPE_MESH_POINT: | ||
1257 | result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); | ||
1258 | break; | ||
1259 | case NL80211_IFTYPE_MONITOR: | ||
1260 | result = cfg80211_set_monitor_channel(rdev, freq, channel_type); | ||
1261 | break; | ||
1262 | default: | ||
1263 | result = -EINVAL; | ||
1230 | } | 1264 | } |
1231 | mutex_unlock(&rdev->devlist_mtx); | 1265 | mutex_unlock(&rdev->devlist_mtx); |
1232 | 1266 | ||
@@ -1310,8 +1344,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1310 | result = 0; | 1344 | result = 0; |
1311 | 1345 | ||
1312 | mutex_lock(&rdev->mtx); | 1346 | mutex_lock(&rdev->mtx); |
1313 | } else if (netif_running(netdev) && | 1347 | } else if (nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) |
1314 | nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | ||
1315 | wdev = netdev->ieee80211_ptr; | 1348 | wdev = netdev->ieee80211_ptr; |
1316 | else | 1349 | else |
1317 | wdev = NULL; | 1350 | wdev = NULL; |
@@ -2299,6 +2332,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2299 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); | 2332 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); |
2300 | } | 2333 | } |
2301 | 2334 | ||
2335 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
2336 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
2337 | |||
2338 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
2339 | !nl80211_valid_channel_type(info, &channel_type)) | ||
2340 | return -EINVAL; | ||
2341 | |||
2342 | params.channel = rdev_freq_to_chan(rdev, | ||
2343 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
2344 | channel_type); | ||
2345 | if (!params.channel) | ||
2346 | return -EINVAL; | ||
2347 | params.channel_type = channel_type; | ||
2348 | } else if (wdev->preset_chan) { | ||
2349 | params.channel = wdev->preset_chan; | ||
2350 | params.channel_type = wdev->preset_chantype; | ||
2351 | } else | ||
2352 | return -EINVAL; | ||
2353 | |||
2354 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, | ||
2355 | params.channel_type)) | ||
2356 | return -EINVAL; | ||
2357 | |||
2302 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); | 2358 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); |
2303 | if (!err) | 2359 | if (!err) |
2304 | wdev->beacon_interval = params.beacon_interval; | 2360 | wdev->beacon_interval = params.beacon_interval; |
@@ -5489,18 +5545,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
5489 | 5545 | ||
5490 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 5546 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
5491 | 5547 | ||
5548 | if (!rdev->ops->remain_on_channel || | ||
5549 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) | ||
5550 | return -EOPNOTSUPP; | ||
5551 | |||
5492 | /* | 5552 | /* |
5493 | * We should be on that channel for at least one jiffie, | 5553 | * We should be on that channel for at least a minimum amount of |
5494 | * and more than 5 seconds seems excessive. | 5554 | * time (10ms) but no longer than the driver supports. |
5495 | */ | 5555 | */ |
5496 | if (!duration || !msecs_to_jiffies(duration) || | 5556 | if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || |
5497 | duration > rdev->wiphy.max_remain_on_channel_duration) | 5557 | duration > rdev->wiphy.max_remain_on_channel_duration) |
5498 | return -EINVAL; | 5558 | return -EINVAL; |
5499 | 5559 | ||
5500 | if (!rdev->ops->remain_on_channel || | ||
5501 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) | ||
5502 | return -EOPNOTSUPP; | ||
5503 | |||
5504 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | 5560 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && |
5505 | !nl80211_valid_channel_type(info, &channel_type)) | 5561 | !nl80211_valid_channel_type(info, &channel_type)) |
5506 | return -EINVAL; | 5562 | return -EINVAL; |
@@ -5771,6 +5827,15 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
5771 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) | 5827 | if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) |
5772 | return -EINVAL; | 5828 | return -EINVAL; |
5773 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | 5829 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); |
5830 | |||
5831 | /* | ||
5832 | * We should wait on the channel for at least a minimum amount | ||
5833 | * of time (10ms) but no longer than the driver supports. | ||
5834 | */ | ||
5835 | if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || | ||
5836 | wait > rdev->wiphy.max_remain_on_channel_duration) | ||
5837 | return -EINVAL; | ||
5838 | |||
5774 | } | 5839 | } |
5775 | 5840 | ||
5776 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 5841 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
@@ -6032,6 +6097,24 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6032 | return err; | 6097 | return err; |
6033 | } | 6098 | } |
6034 | 6099 | ||
6100 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
6101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
6102 | |||
6103 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
6104 | !nl80211_valid_channel_type(info, &channel_type)) | ||
6105 | return -EINVAL; | ||
6106 | |||
6107 | setup.channel = rdev_freq_to_chan(rdev, | ||
6108 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
6109 | channel_type); | ||
6110 | if (!setup.channel) | ||
6111 | return -EINVAL; | ||
6112 | setup.channel_type = channel_type; | ||
6113 | } else { | ||
6114 | /* cfg80211_join_mesh() will sort it out */ | ||
6115 | setup.channel = NULL; | ||
6116 | } | ||
6117 | |||
6035 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 6118 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
6036 | } | 6119 | } |
6037 | 6120 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6a6181a673ca..bc879833b21f 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -796,7 +796,15 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
796 | case NL80211_IFTYPE_ADHOC: | 796 | case NL80211_IFTYPE_ADHOC: |
797 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); | 797 | return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); |
798 | case NL80211_IFTYPE_MONITOR: | 798 | case NL80211_IFTYPE_MONITOR: |
799 | case NL80211_IFTYPE_WDS: | 799 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
800 | if (freq < 0) | ||
801 | return freq; | ||
802 | if (freq == 0) | ||
803 | return -EINVAL; | ||
804 | mutex_lock(&rdev->devlist_mtx); | ||
805 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); | ||
806 | mutex_unlock(&rdev->devlist_mtx); | ||
807 | return err; | ||
800 | case NL80211_IFTYPE_MESH_POINT: | 808 | case NL80211_IFTYPE_MESH_POINT: |
801 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); | 809 | freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); |
802 | if (freq < 0) | 810 | if (freq < 0) |
@@ -804,9 +812,8 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, | |||
804 | if (freq == 0) | 812 | if (freq == 0) |
805 | return -EINVAL; | 813 | return -EINVAL; |
806 | mutex_lock(&rdev->devlist_mtx); | 814 | mutex_lock(&rdev->devlist_mtx); |
807 | wdev_lock(wdev); | 815 | err = cfg80211_set_mesh_freq(rdev, wdev, freq, |
808 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | 816 | NL80211_CHAN_NO_HT); |
809 | wdev_unlock(wdev); | ||
810 | mutex_unlock(&rdev->devlist_mtx); | 817 | mutex_unlock(&rdev->devlist_mtx); |
811 | return err; | 818 | return err; |
812 | default: | 819 | default: |
@@ -839,11 +846,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, | |||
839 | freq->e = 6; | 846 | freq->e = 6; |
840 | return 0; | 847 | return 0; |
841 | default: | 848 | default: |
842 | if (!wdev->channel) | 849 | return -EINVAL; |
843 | return -EINVAL; | ||
844 | freq->m = wdev->channel->center_freq; | ||
845 | freq->e = 6; | ||
846 | return 0; | ||
847 | } | 850 | } |
848 | } | 851 | } |
849 | 852 | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 7decbd357d51..1f773f668d1a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -111,9 +111,15 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
111 | 111 | ||
112 | wdev->wext.connect.channel = chan; | 112 | wdev->wext.connect.channel = chan; |
113 | 113 | ||
114 | /* SSID is not set, we just want to switch channel */ | 114 | /* |
115 | * SSID is not set, we just want to switch monitor channel, | ||
116 | * this is really just backward compatibility, if the SSID | ||
117 | * is set then we use the channel to select the BSS to use | ||
118 | * to connect to instead. If we were connected on another | ||
119 | * channel we disconnected above and reconnect below. | ||
120 | */ | ||
115 | if (chan && !wdev->wext.connect.ssid_len) { | 121 | if (chan && !wdev->wext.connect.ssid_len) { |
116 | err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); | 122 | err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); |
117 | goto out; | 123 | goto out; |
118 | } | 124 | } |
119 | 125 | ||