diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-04-18 14:17:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-18 14:27:48 -0400 |
commit | 59ef43e681d103a51c3727dad0315e093f07ec61 (patch) | |
tree | 87f6320f1440ce3ce6c0c15ad3cef8bc98186f88 /drivers/net/wireless | |
parent | 91fbe33034c184c6a60e31c2207a2f7ec2f180dc (diff) | |
parent | b5abcf0219263f4e961dca71cbe26e06c5b0ee68 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-testmode.c
include/net/nfc/nfc.h
net/nfc/netlink.c
net/wireless/nl80211.c
Diffstat (limited to 'drivers/net/wireless')
244 files changed, 11021 insertions, 7053 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index abd3b71cd4ab..5f58fa53238c 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -282,8 +282,7 @@ source "drivers/net/wireless/orinoco/Kconfig" | |||
282 | source "drivers/net/wireless/p54/Kconfig" | 282 | source "drivers/net/wireless/p54/Kconfig" |
283 | source "drivers/net/wireless/rt2x00/Kconfig" | 283 | source "drivers/net/wireless/rt2x00/Kconfig" |
284 | source "drivers/net/wireless/rtlwifi/Kconfig" | 284 | source "drivers/net/wireless/rtlwifi/Kconfig" |
285 | source "drivers/net/wireless/wl1251/Kconfig" | 285 | source "drivers/net/wireless/ti/Kconfig" |
286 | source "drivers/net/wireless/wl12xx/Kconfig" | ||
287 | source "drivers/net/wireless/zd1211rw/Kconfig" | 286 | source "drivers/net/wireless/zd1211rw/Kconfig" |
288 | source "drivers/net/wireless/mwifiex/Kconfig" | 287 | source "drivers/net/wireless/mwifiex/Kconfig" |
289 | 288 | ||
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 98db76196b59..0ce218b931d4 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -51,9 +51,7 @@ obj-$(CONFIG_ATH_COMMON) += ath/ | |||
51 | 51 | ||
52 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o | 52 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o |
53 | 53 | ||
54 | obj-$(CONFIG_WL1251) += wl1251/ | 54 | obj-$(CONFIG_WL_TI) += ti/ |
55 | obj-$(CONFIG_WL12XX) += wl12xx/ | ||
56 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/ | ||
57 | 55 | ||
58 | obj-$(CONFIG_IWM) += iwmc3200wifi/ | 56 | obj-$(CONFIG_IWM) += iwmc3200wifi/ |
59 | 57 | ||
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f5ce5623da99..0ac09a2bd144 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1991,19 +1991,4 @@ static struct pci_driver adm8211_driver = { | |||
1991 | #endif /* CONFIG_PM */ | 1991 | #endif /* CONFIG_PM */ |
1992 | }; | 1992 | }; |
1993 | 1993 | ||
1994 | 1994 | module_pci_driver(adm8211_driver); | |
1995 | |||
1996 | static int __init adm8211_init(void) | ||
1997 | { | ||
1998 | return pci_register_driver(&adm8211_driver); | ||
1999 | } | ||
2000 | |||
2001 | |||
2002 | static void __exit adm8211_exit(void) | ||
2003 | { | ||
2004 | pci_unregister_driver(&adm8211_driver); | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | module_init(adm8211_init); | ||
2009 | module_exit(adm8211_exit); | ||
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 4045e5ab0555..faa8bcb4aac1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -2512,10 +2512,8 @@ static void __exit at76_mod_exit(void) | |||
2512 | 2512 | ||
2513 | printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n"); | 2513 | printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n"); |
2514 | usb_deregister(&at76_driver); | 2514 | usb_deregister(&at76_driver); |
2515 | for (i = 0; i < ARRAY_SIZE(firmwares); i++) { | 2515 | for (i = 0; i < ARRAY_SIZE(firmwares); i++) |
2516 | if (firmwares[i].fw) | 2516 | release_firmware(firmwares[i].fw); |
2517 | release_firmware(firmwares[i].fw); | ||
2518 | } | ||
2519 | led_trigger_unregister_simple(ledtrig_tx); | 2517 | led_trigger_unregister_simple(ledtrig_tx); |
2520 | } | 2518 | } |
2521 | 2519 | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 55ef93dd7438..64a453a6dfe4 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1527,7 +1527,7 @@ void ath5k_eeprom_detach(struct ath5k_hw *ah); | |||
1527 | 1527 | ||
1528 | /* Protocol Control Unit Functions */ | 1528 | /* Protocol Control Unit Functions */ |
1529 | /* Helpers */ | 1529 | /* Helpers */ |
1530 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | 1530 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum ieee80211_band band, |
1531 | int len, struct ieee80211_rate *rate, bool shortpre); | 1531 | int len, struct ieee80211_rate *rate, bool shortpre); |
1532 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); | 1532 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); |
1533 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); | 1533 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3007bba12d94..49e3b19cf781 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1170,7 +1170,7 @@ ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb, | |||
1170 | 1170 | ||
1171 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1171 | if (ieee80211_is_beacon(mgmt->frame_control) && |
1172 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1172 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1173 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) == 0) { | 1173 | compare_ether_addr(mgmt->bssid, common->curbssid) == 0) { |
1174 | /* | 1174 | /* |
1175 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1175 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1176 | * have updated the local TSF. We have to work around various | 1176 | * have updated the local TSF. We have to work around various |
@@ -1234,7 +1234,7 @@ ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi) | |||
1234 | 1234 | ||
1235 | /* only beacons from our BSSID */ | 1235 | /* only beacons from our BSSID */ |
1236 | if (!ieee80211_is_beacon(mgmt->frame_control) || | 1236 | if (!ieee80211_is_beacon(mgmt->frame_control) || |
1237 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | 1237 | compare_ether_addr(mgmt->bssid, common->curbssid) != 0) |
1238 | return; | 1238 | return; |
1239 | 1239 | ||
1240 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); | 1240 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); |
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 53424e8e6d82..dff48fbc63bf 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -47,6 +47,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | |||
47 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ | 47 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ |
48 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ | 48 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ |
49 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ | 49 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ |
50 | { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ | ||
50 | { 0 } | 51 | { 0 } |
51 | }; | 52 | }; |
52 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | 53 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); |
@@ -339,28 +340,4 @@ static struct pci_driver ath5k_pci_driver = { | |||
339 | .driver.pm = ATH5K_PM_OPS, | 340 | .driver.pm = ATH5K_PM_OPS, |
340 | }; | 341 | }; |
341 | 342 | ||
342 | /* | 343 | module_pci_driver(ath5k_pci_driver); |
343 | * Module init/exit functions | ||
344 | */ | ||
345 | static int __init | ||
346 | init_ath5k_pci(void) | ||
347 | { | ||
348 | int ret; | ||
349 | |||
350 | ret = pci_register_driver(&ath5k_pci_driver); | ||
351 | if (ret) { | ||
352 | pr_err("pci: can't register pci driver\n"); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static void __exit | ||
360 | exit_ath5k_pci(void) | ||
361 | { | ||
362 | pci_unregister_driver(&ath5k_pci_driver); | ||
363 | } | ||
364 | |||
365 | module_init(init_ath5k_pci); | ||
366 | module_exit(exit_ath5k_pci); | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index cebfd6fd31d3..1f16b4227d8f 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -110,7 +110,7 @@ static const unsigned int ack_rates_high[] = | |||
110 | * bwmodes. | 110 | * bwmodes. |
111 | */ | 111 | */ |
112 | int | 112 | int |
113 | ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | 113 | ath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum ieee80211_band band, |
114 | int len, struct ieee80211_rate *rate, bool shortpre) | 114 | int len, struct ieee80211_rate *rate, bool shortpre) |
115 | { | 115 | { |
116 | int sifs, preamble, plcp_bits, sym_time; | 116 | int sifs, preamble, plcp_bits, sym_time; |
@@ -120,7 +120,7 @@ ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | |||
120 | /* Fallback */ | 120 | /* Fallback */ |
121 | if (!ah->ah_bwmode) { | 121 | if (!ah->ah_bwmode) { |
122 | __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw, | 122 | __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw, |
123 | NULL, len, rate); | 123 | NULL, band, len, rate); |
124 | 124 | ||
125 | /* subtract difference between long and short preamble */ | 125 | /* subtract difference between long and short preamble */ |
126 | dur = le16_to_cpu(raw_dur); | 126 | dur = le16_to_cpu(raw_dur); |
@@ -302,14 +302,15 @@ ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | |||
302 | * actual rate for this rate. See mac80211 tx.c | 302 | * actual rate for this rate. See mac80211 tx.c |
303 | * ieee80211_duration() for a brief description of | 303 | * ieee80211_duration() for a brief description of |
304 | * what rate we should choose to TX ACKs. */ | 304 | * what rate we should choose to TX ACKs. */ |
305 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); | 305 | tx_time = ath5k_hw_get_frame_duration(ah, band, 10, |
306 | rate, false); | ||
306 | 307 | ||
307 | ath5k_hw_reg_write(ah, tx_time, reg); | 308 | ath5k_hw_reg_write(ah, tx_time, reg); |
308 | 309 | ||
309 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | 310 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) |
310 | continue; | 311 | continue; |
311 | 312 | ||
312 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); | 313 | tx_time = ath5k_hw_get_frame_duration(ah, band, 10, rate, true); |
313 | ath5k_hw_reg_write(ah, tx_time, | 314 | ath5k_hw_reg_write(ah, tx_time, |
314 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | 315 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); |
315 | } | 316 | } |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index a6de200538c3..65fe929529a8 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -565,6 +565,7 @@ ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
565 | int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) | 565 | int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) |
566 | { | 566 | { |
567 | struct ieee80211_channel *channel = ah->ah_current_channel; | 567 | struct ieee80211_channel *channel = ah->ah_current_channel; |
568 | enum ieee80211_band band; | ||
568 | struct ieee80211_rate *rate; | 569 | struct ieee80211_rate *rate; |
569 | u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; | 570 | u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; |
570 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | 571 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); |
@@ -600,11 +601,12 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) | |||
600 | * Also we have different lowest rate for 802.11a | 601 | * Also we have different lowest rate for 802.11a |
601 | */ | 602 | */ |
602 | if (channel->band == IEEE80211_BAND_5GHZ) | 603 | if (channel->band == IEEE80211_BAND_5GHZ) |
603 | rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; | 604 | band = IEEE80211_BAND_5GHZ; |
604 | else | 605 | else |
605 | rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; | 606 | band = IEEE80211_BAND_2GHZ; |
606 | 607 | ||
607 | ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); | 608 | rate = &ah->sbands[band].bitrates[0]; |
609 | ack_tx_time = ath5k_hw_get_frame_duration(ah, band, 10, rate, false); | ||
608 | 610 | ||
609 | /* ack_tx_time includes an SIFS already */ | 611 | /* ack_tx_time includes an SIFS already */ |
610 | eifs = ack_tx_time + sifs + 2 * slot_time; | 612 | eifs = ack_tx_time + sifs + 2 * slot_time; |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 85746c3eb027..8cae8886f17d 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -25,7 +25,8 @@ | |||
25 | obj-$(CONFIG_ATH6KL) += ath6kl_core.o | 25 | obj-$(CONFIG_ATH6KL) += ath6kl_core.o |
26 | ath6kl_core-y += debug.o | 26 | ath6kl_core-y += debug.o |
27 | ath6kl_core-y += hif.o | 27 | ath6kl_core-y += hif.o |
28 | ath6kl_core-y += htc.o | 28 | ath6kl_core-y += htc_mbox.o |
29 | ath6kl_core-y += htc_pipe.o | ||
29 | ath6kl_core-y += bmi.o | 30 | ath6kl_core-y += bmi.o |
30 | ath6kl_core-y += cfg80211.o | 31 | ath6kl_core-y += cfg80211.o |
31 | ath6kl_core-y += init.o | 32 | ath6kl_core-y += init.o |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index bdcc68fb1e37..28a65d3a03d0 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -51,6 +51,8 @@ | |||
51 | .max_power = 30, \ | 51 | .max_power = 30, \ |
52 | } | 52 | } |
53 | 53 | ||
54 | #define DEFAULT_BG_SCAN_PERIOD 60 | ||
55 | |||
54 | static struct ieee80211_rate ath6kl_rates[] = { | 56 | static struct ieee80211_rate ath6kl_rates[] = { |
55 | RATETAB_ENT(10, 0x1, 0), | 57 | RATETAB_ENT(10, 0x1, 0), |
56 | RATETAB_ENT(20, 0x2, 0), | 58 | RATETAB_ENT(20, 0x2, 0), |
@@ -71,7 +73,8 @@ static struct ieee80211_rate ath6kl_rates[] = { | |||
71 | #define ath6kl_g_rates (ath6kl_rates + 0) | 73 | #define ath6kl_g_rates (ath6kl_rates + 0) |
72 | #define ath6kl_g_rates_size 12 | 74 | #define ath6kl_g_rates_size 12 |
73 | 75 | ||
74 | #define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | 76 | #define ath6kl_g_htcap IEEE80211_HT_CAP_SGI_20 |
77 | #define ath6kl_a_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | ||
75 | IEEE80211_HT_CAP_SGI_20 | \ | 78 | IEEE80211_HT_CAP_SGI_20 | \ |
76 | IEEE80211_HT_CAP_SGI_40) | 79 | IEEE80211_HT_CAP_SGI_40) |
77 | 80 | ||
@@ -128,7 +131,7 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = { | |||
128 | .channels = ath6kl_5ghz_a_channels, | 131 | .channels = ath6kl_5ghz_a_channels, |
129 | .n_bitrates = ath6kl_a_rates_size, | 132 | .n_bitrates = ath6kl_a_rates_size, |
130 | .bitrates = ath6kl_a_rates, | 133 | .bitrates = ath6kl_a_rates, |
131 | .ht_cap.cap = ath6kl_g_htcap, | 134 | .ht_cap.cap = ath6kl_a_htcap, |
132 | .ht_cap.ht_supported = true, | 135 | .ht_cap.ht_supported = true, |
133 | }; | 136 | }; |
134 | 137 | ||
@@ -609,6 +612,17 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
609 | vif->req_bssid, vif->ch_hint, | 612 | vif->req_bssid, vif->ch_hint, |
610 | ar->connect_ctrl_flags, nw_subtype); | 613 | ar->connect_ctrl_flags, nw_subtype); |
611 | 614 | ||
615 | /* disable background scan if period is 0 */ | ||
616 | if (sme->bg_scan_period == 0) | ||
617 | sme->bg_scan_period = 0xffff; | ||
618 | |||
619 | /* configure default value if not specified */ | ||
620 | if (sme->bg_scan_period == -1) | ||
621 | sme->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; | ||
622 | |||
623 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0, 0, | ||
624 | sme->bg_scan_period, 0, 0, 0, 3, 0, 0, 0); | ||
625 | |||
612 | up(&ar->sem); | 626 | up(&ar->sem); |
613 | 627 | ||
614 | if (status == -EINVAL) { | 628 | if (status == -EINVAL) { |
@@ -943,6 +957,8 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
943 | if (test_bit(CONNECTED, &vif->flags)) | 957 | if (test_bit(CONNECTED, &vif->flags)) |
944 | force_fg_scan = 1; | 958 | force_fg_scan = 1; |
945 | 959 | ||
960 | vif->scan_req = request; | ||
961 | |||
946 | if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, | 962 | if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, |
947 | ar->fw_capabilities)) { | 963 | ar->fw_capabilities)) { |
948 | /* | 964 | /* |
@@ -965,10 +981,10 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
965 | ATH6KL_FG_SCAN_INTERVAL, | 981 | ATH6KL_FG_SCAN_INTERVAL, |
966 | n_channels, channels); | 982 | n_channels, channels); |
967 | } | 983 | } |
968 | if (ret) | 984 | if (ret) { |
969 | ath6kl_err("wmi_startscan_cmd failed\n"); | 985 | ath6kl_err("wmi_startscan_cmd failed\n"); |
970 | else | 986 | vif->scan_req = NULL; |
971 | vif->scan_req = request; | 987 | } |
972 | 988 | ||
973 | kfree(channels); | 989 | kfree(channels); |
974 | 990 | ||
@@ -1438,9 +1454,38 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | |||
1438 | struct vif_params *params) | 1454 | struct vif_params *params) |
1439 | { | 1455 | { |
1440 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1456 | struct ath6kl_vif *vif = netdev_priv(ndev); |
1457 | int i; | ||
1441 | 1458 | ||
1442 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); | 1459 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); |
1443 | 1460 | ||
1461 | /* | ||
1462 | * Don't bring up p2p on an interface which is not initialized | ||
1463 | * for p2p operation where fw does not have capability to switch | ||
1464 | * dynamically between non-p2p and p2p type interface. | ||
1465 | */ | ||
1466 | if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, | ||
1467 | vif->ar->fw_capabilities) && | ||
1468 | (type == NL80211_IFTYPE_P2P_CLIENT || | ||
1469 | type == NL80211_IFTYPE_P2P_GO)) { | ||
1470 | if (vif->ar->vif_max == 1) { | ||
1471 | if (vif->fw_vif_idx != 0) | ||
1472 | return -EINVAL; | ||
1473 | else | ||
1474 | goto set_iface_type; | ||
1475 | } | ||
1476 | |||
1477 | for (i = vif->ar->max_norm_iface; i < vif->ar->vif_max; i++) { | ||
1478 | if (i == vif->fw_vif_idx) | ||
1479 | break; | ||
1480 | } | ||
1481 | |||
1482 | if (i == vif->ar->vif_max) { | ||
1483 | ath6kl_err("Invalid interface to bring up P2P\n"); | ||
1484 | return -EINVAL; | ||
1485 | } | ||
1486 | } | ||
1487 | |||
1488 | set_iface_type: | ||
1444 | switch (type) { | 1489 | switch (type) { |
1445 | case NL80211_IFTYPE_STATION: | 1490 | case NL80211_IFTYPE_STATION: |
1446 | vif->next_mode = INFRA_NETWORK; | 1491 | vif->next_mode = INFRA_NETWORK; |
@@ -1926,12 +1971,61 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) | |||
1926 | return 0; | 1971 | return 0; |
1927 | } | 1972 | } |
1928 | 1973 | ||
1974 | static int is_hsleep_mode_procsed(struct ath6kl_vif *vif) | ||
1975 | { | ||
1976 | return test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); | ||
1977 | } | ||
1978 | |||
1979 | static bool is_ctrl_ep_empty(struct ath6kl *ar) | ||
1980 | { | ||
1981 | return !ar->tx_pending[ar->ctrl_ep]; | ||
1982 | } | ||
1983 | |||
1984 | static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif) | ||
1985 | { | ||
1986 | int ret, left; | ||
1987 | |||
1988 | clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); | ||
1989 | |||
1990 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
1991 | ATH6KL_HOST_MODE_ASLEEP); | ||
1992 | if (ret) | ||
1993 | return ret; | ||
1994 | |||
1995 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
1996 | is_hsleep_mode_procsed(vif), | ||
1997 | WMI_TIMEOUT); | ||
1998 | if (left == 0) { | ||
1999 | ath6kl_warn("timeout, didn't get host sleep cmd processed event\n"); | ||
2000 | ret = -ETIMEDOUT; | ||
2001 | } else if (left < 0) { | ||
2002 | ath6kl_warn("error while waiting for host sleep cmd processed event %d\n", | ||
2003 | left); | ||
2004 | ret = left; | ||
2005 | } | ||
2006 | |||
2007 | if (ar->tx_pending[ar->ctrl_ep]) { | ||
2008 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
2009 | is_ctrl_ep_empty(ar), | ||
2010 | WMI_TIMEOUT); | ||
2011 | if (left == 0) { | ||
2012 | ath6kl_warn("clear wmi ctrl data timeout\n"); | ||
2013 | ret = -ETIMEDOUT; | ||
2014 | } else if (left < 0) { | ||
2015 | ath6kl_warn("clear wmi ctrl data failed: %d\n", left); | ||
2016 | ret = left; | ||
2017 | } | ||
2018 | } | ||
2019 | |||
2020 | return ret; | ||
2021 | } | ||
2022 | |||
1929 | static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | 2023 | static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) |
1930 | { | 2024 | { |
1931 | struct in_device *in_dev; | 2025 | struct in_device *in_dev; |
1932 | struct in_ifaddr *ifa; | 2026 | struct in_ifaddr *ifa; |
1933 | struct ath6kl_vif *vif; | 2027 | struct ath6kl_vif *vif; |
1934 | int ret, left; | 2028 | int ret; |
1935 | u32 filter = 0; | 2029 | u32 filter = 0; |
1936 | u16 i, bmiss_time; | 2030 | u16 i, bmiss_time; |
1937 | u8 index = 0; | 2031 | u8 index = 0; |
@@ -2032,39 +2126,11 @@ skip_arp: | |||
2032 | if (ret) | 2126 | if (ret) |
2033 | return ret; | 2127 | return ret; |
2034 | 2128 | ||
2035 | clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); | 2129 | ret = ath6kl_cfg80211_host_sleep(ar, vif); |
2036 | |||
2037 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2038 | ATH6KL_HOST_MODE_ASLEEP); | ||
2039 | if (ret) | 2130 | if (ret) |
2040 | return ret; | 2131 | return ret; |
2041 | 2132 | ||
2042 | left = wait_event_interruptible_timeout(ar->event_wq, | 2133 | return 0; |
2043 | test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags), | ||
2044 | WMI_TIMEOUT); | ||
2045 | if (left == 0) { | ||
2046 | ath6kl_warn("timeout, didn't get host sleep cmd " | ||
2047 | "processed event\n"); | ||
2048 | ret = -ETIMEDOUT; | ||
2049 | } else if (left < 0) { | ||
2050 | ath6kl_warn("error while waiting for host sleep cmd " | ||
2051 | "processed event %d\n", left); | ||
2052 | ret = left; | ||
2053 | } | ||
2054 | |||
2055 | if (ar->tx_pending[ar->ctrl_ep]) { | ||
2056 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
2057 | ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT); | ||
2058 | if (left == 0) { | ||
2059 | ath6kl_warn("clear wmi ctrl data timeout\n"); | ||
2060 | ret = -ETIMEDOUT; | ||
2061 | } else if (left < 0) { | ||
2062 | ath6kl_warn("clear wmi ctrl data failed: %d\n", left); | ||
2063 | ret = left; | ||
2064 | } | ||
2065 | } | ||
2066 | |||
2067 | return ret; | ||
2068 | } | 2134 | } |
2069 | 2135 | ||
2070 | static int ath6kl_wow_resume(struct ath6kl *ar) | 2136 | static int ath6kl_wow_resume(struct ath6kl *ar) |
@@ -2111,10 +2177,82 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2111 | return 0; | 2177 | return 0; |
2112 | } | 2178 | } |
2113 | 2179 | ||
2180 | static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) | ||
2181 | { | ||
2182 | struct ath6kl_vif *vif; | ||
2183 | int ret; | ||
2184 | |||
2185 | vif = ath6kl_vif_first(ar); | ||
2186 | if (!vif) | ||
2187 | return -EIO; | ||
2188 | |||
2189 | if (!ath6kl_cfg80211_ready(vif)) | ||
2190 | return -EIO; | ||
2191 | |||
2192 | ath6kl_cfg80211_stop_all(ar); | ||
2193 | |||
2194 | /* Save the current power mode before enabling power save */ | ||
2195 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2196 | |||
2197 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER); | ||
2198 | if (ret) | ||
2199 | return ret; | ||
2200 | |||
2201 | /* Disable WOW mode */ | ||
2202 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2203 | ATH6KL_WOW_MODE_DISABLE, | ||
2204 | 0, 0); | ||
2205 | if (ret) | ||
2206 | return ret; | ||
2207 | |||
2208 | /* Flush all non control pkts in TX path */ | ||
2209 | ath6kl_tx_data_cleanup(ar); | ||
2210 | |||
2211 | ret = ath6kl_cfg80211_host_sleep(ar, vif); | ||
2212 | if (ret) | ||
2213 | return ret; | ||
2214 | |||
2215 | return 0; | ||
2216 | } | ||
2217 | |||
2218 | static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar) | ||
2219 | { | ||
2220 | struct ath6kl_vif *vif; | ||
2221 | int ret; | ||
2222 | |||
2223 | vif = ath6kl_vif_first(ar); | ||
2224 | |||
2225 | if (!vif) | ||
2226 | return -EIO; | ||
2227 | |||
2228 | if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) { | ||
2229 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, | ||
2230 | ar->wmi->saved_pwr_mode); | ||
2231 | if (ret) | ||
2232 | return ret; | ||
2233 | } | ||
2234 | |||
2235 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2236 | ATH6KL_HOST_MODE_AWAKE); | ||
2237 | if (ret) | ||
2238 | return ret; | ||
2239 | |||
2240 | ar->state = ATH6KL_STATE_ON; | ||
2241 | |||
2242 | /* Reset scan parameter to default values */ | ||
2243 | ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | ||
2244 | 0, 0, 0, 0, 0, 0, 3, 0, 0, 0); | ||
2245 | if (ret) | ||
2246 | return ret; | ||
2247 | |||
2248 | return 0; | ||
2249 | } | ||
2250 | |||
2114 | int ath6kl_cfg80211_suspend(struct ath6kl *ar, | 2251 | int ath6kl_cfg80211_suspend(struct ath6kl *ar, |
2115 | enum ath6kl_cfg_suspend_mode mode, | 2252 | enum ath6kl_cfg_suspend_mode mode, |
2116 | struct cfg80211_wowlan *wow) | 2253 | struct cfg80211_wowlan *wow) |
2117 | { | 2254 | { |
2255 | struct ath6kl_vif *vif; | ||
2118 | enum ath6kl_state prev_state; | 2256 | enum ath6kl_state prev_state; |
2119 | int ret; | 2257 | int ret; |
2120 | 2258 | ||
@@ -2139,15 +2277,12 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
2139 | 2277 | ||
2140 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: | 2278 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: |
2141 | 2279 | ||
2142 | ath6kl_cfg80211_stop_all(ar); | 2280 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n"); |
2143 | |||
2144 | /* save the current power mode before enabling power save */ | ||
2145 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2146 | 2281 | ||
2147 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER); | 2282 | ret = ath6kl_cfg80211_deepsleep_suspend(ar); |
2148 | if (ret) { | 2283 | if (ret) { |
2149 | ath6kl_warn("wmi powermode command failed during suspend: %d\n", | 2284 | ath6kl_err("deepsleep suspend failed: %d\n", ret); |
2150 | ret); | 2285 | return ret; |
2151 | } | 2286 | } |
2152 | 2287 | ||
2153 | ar->state = ATH6KL_STATE_DEEPSLEEP; | 2288 | ar->state = ATH6KL_STATE_DEEPSLEEP; |
@@ -2187,6 +2322,9 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
2187 | break; | 2322 | break; |
2188 | } | 2323 | } |
2189 | 2324 | ||
2325 | list_for_each_entry(vif, &ar->vif_list, list) | ||
2326 | ath6kl_cfg80211_scan_complete_event(vif, true); | ||
2327 | |||
2190 | return 0; | 2328 | return 0; |
2191 | } | 2329 | } |
2192 | EXPORT_SYMBOL(ath6kl_cfg80211_suspend); | 2330 | EXPORT_SYMBOL(ath6kl_cfg80211_suspend); |
@@ -2208,17 +2346,13 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) | |||
2208 | break; | 2346 | break; |
2209 | 2347 | ||
2210 | case ATH6KL_STATE_DEEPSLEEP: | 2348 | case ATH6KL_STATE_DEEPSLEEP: |
2211 | if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) { | 2349 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n"); |
2212 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, | ||
2213 | ar->wmi->saved_pwr_mode); | ||
2214 | if (ret) { | ||
2215 | ath6kl_warn("wmi powermode command failed during resume: %d\n", | ||
2216 | ret); | ||
2217 | } | ||
2218 | } | ||
2219 | |||
2220 | ar->state = ATH6KL_STATE_ON; | ||
2221 | 2350 | ||
2351 | ret = ath6kl_cfg80211_deepsleep_resume(ar); | ||
2352 | if (ret) { | ||
2353 | ath6kl_warn("deep sleep resume failed: %d\n", ret); | ||
2354 | return ret; | ||
2355 | } | ||
2222 | break; | 2356 | break; |
2223 | 2357 | ||
2224 | case ATH6KL_STATE_CUTPOWER: | 2358 | case ATH6KL_STATE_CUTPOWER: |
@@ -2292,31 +2426,25 @@ void ath6kl_check_wow_status(struct ath6kl *ar) | |||
2292 | } | 2426 | } |
2293 | #endif | 2427 | #endif |
2294 | 2428 | ||
2295 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | 2429 | static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, |
2296 | struct ieee80211_channel *chan, | 2430 | bool ht_enable) |
2297 | enum nl80211_channel_type channel_type) | ||
2298 | { | 2431 | { |
2299 | struct ath6kl_vif *vif; | 2432 | struct ath6kl_htcap *htcap = &vif->htcap; |
2300 | |||
2301 | /* | ||
2302 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2303 | * device itself, instead of a particular VIF. | ||
2304 | * | ||
2305 | * FIXME: To be handled properly when monitor mode is supported. | ||
2306 | */ | ||
2307 | if (!dev) | ||
2308 | return -EBUSY; | ||
2309 | |||
2310 | vif = netdev_priv(dev); | ||
2311 | 2433 | ||
2312 | if (!ath6kl_cfg80211_ready(vif)) | 2434 | if (htcap->ht_enable == ht_enable) |
2313 | return -EIO; | 2435 | return 0; |
2314 | 2436 | ||
2315 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | 2437 | if (ht_enable) { |
2316 | __func__, chan->center_freq, chan->hw_value); | 2438 | /* Set default ht capabilities */ |
2317 | vif->next_chan = chan->center_freq; | 2439 | htcap->ht_enable = true; |
2440 | htcap->cap_info = (band == IEEE80211_BAND_2GHZ) ? | ||
2441 | ath6kl_g_htcap : ath6kl_a_htcap; | ||
2442 | htcap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; | ||
2443 | } else /* Disable ht */ | ||
2444 | memset(htcap, 0, sizeof(*htcap)); | ||
2318 | 2445 | ||
2319 | return 0; | 2446 | return ath6kl_wmi_set_htcap_cmd(vif->ar->wmi, vif->fw_vif_idx, |
2447 | band, htcap); | ||
2320 | } | 2448 | } |
2321 | 2449 | ||
2322 | static bool ath6kl_is_p2p_ie(const u8 *pos) | 2450 | static bool ath6kl_is_p2p_ie(const u8 *pos) |
@@ -2393,6 +2521,81 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, | |||
2393 | return 0; | 2521 | return 0; |
2394 | } | 2522 | } |
2395 | 2523 | ||
2524 | static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
2525 | struct ieee80211_channel *chan, | ||
2526 | enum nl80211_channel_type channel_type) | ||
2527 | { | ||
2528 | struct ath6kl_vif *vif; | ||
2529 | |||
2530 | /* | ||
2531 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2532 | * device itself, instead of a particular VIF. | ||
2533 | * | ||
2534 | * FIXME: To be handled properly when monitor mode is supported. | ||
2535 | */ | ||
2536 | if (!dev) | ||
2537 | return -EBUSY; | ||
2538 | |||
2539 | vif = netdev_priv(dev); | ||
2540 | |||
2541 | if (!ath6kl_cfg80211_ready(vif)) | ||
2542 | return -EIO; | ||
2543 | |||
2544 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n", | ||
2545 | __func__, chan->center_freq, chan->hw_value); | ||
2546 | vif->next_chan = chan->center_freq; | ||
2547 | vif->next_ch_type = channel_type; | ||
2548 | vif->next_ch_band = chan->band; | ||
2549 | |||
2550 | return 0; | ||
2551 | } | ||
2552 | |||
2553 | static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | ||
2554 | u8 *rsn_capab) | ||
2555 | { | ||
2556 | const u8 *rsn_ie; | ||
2557 | size_t rsn_ie_len; | ||
2558 | u16 cnt; | ||
2559 | |||
2560 | if (!beacon->tail) | ||
2561 | return -EINVAL; | ||
2562 | |||
2563 | rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, beacon->tail, beacon->tail_len); | ||
2564 | if (!rsn_ie) | ||
2565 | return -EINVAL; | ||
2566 | |||
2567 | rsn_ie_len = *(rsn_ie + 1); | ||
2568 | /* skip element id and length */ | ||
2569 | rsn_ie += 2; | ||
2570 | |||
2571 | /* skip version, group cipher */ | ||
2572 | if (rsn_ie_len < 6) | ||
2573 | return -EINVAL; | ||
2574 | rsn_ie += 6; | ||
2575 | rsn_ie_len -= 6; | ||
2576 | |||
2577 | /* skip pairwise cipher suite */ | ||
2578 | if (rsn_ie_len < 2) | ||
2579 | return -EINVAL; | ||
2580 | cnt = *((u16 *) rsn_ie); | ||
2581 | rsn_ie += (2 + cnt * 4); | ||
2582 | rsn_ie_len -= (2 + cnt * 4); | ||
2583 | |||
2584 | /* skip akm suite */ | ||
2585 | if (rsn_ie_len < 2) | ||
2586 | return -EINVAL; | ||
2587 | cnt = *((u16 *) rsn_ie); | ||
2588 | rsn_ie += (2 + cnt * 4); | ||
2589 | rsn_ie_len -= (2 + cnt * 4); | ||
2590 | |||
2591 | if (rsn_ie_len < 2) | ||
2592 | return -EINVAL; | ||
2593 | |||
2594 | memcpy(rsn_capab, rsn_ie, 2); | ||
2595 | |||
2596 | return 0; | ||
2597 | } | ||
2598 | |||
2396 | static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | 2599 | static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, |
2397 | struct cfg80211_ap_settings *info) | 2600 | struct cfg80211_ap_settings *info) |
2398 | { | 2601 | { |
@@ -2405,6 +2608,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2405 | struct wmi_connect_cmd p; | 2608 | struct wmi_connect_cmd p; |
2406 | int res; | 2609 | int res; |
2407 | int i, ret; | 2610 | int i, ret; |
2611 | u16 rsn_capab = 0; | ||
2408 | 2612 | ||
2409 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__); | 2613 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__); |
2410 | 2614 | ||
@@ -2534,6 +2738,34 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2534 | p.nw_subtype = SUBTYPE_NONE; | 2738 | p.nw_subtype = SUBTYPE_NONE; |
2535 | } | 2739 | } |
2536 | 2740 | ||
2741 | if (info->inactivity_timeout) { | ||
2742 | res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx, | ||
2743 | info->inactivity_timeout); | ||
2744 | if (res < 0) | ||
2745 | return res; | ||
2746 | } | ||
2747 | |||
2748 | if (ath6kl_set_htcap(vif, vif->next_ch_band, | ||
2749 | vif->next_ch_type != NL80211_CHAN_NO_HT)) | ||
2750 | return -EIO; | ||
2751 | |||
2752 | /* | ||
2753 | * Get the PTKSA replay counter in the RSN IE. Supplicant | ||
2754 | * will use the RSN IE in M3 message and firmware has to | ||
2755 | * advertise the same in beacon/probe response. Send | ||
2756 | * the complete RSN IE capability field to firmware | ||
2757 | */ | ||
2758 | if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) && | ||
2759 | test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | ||
2760 | ar->fw_capabilities)) { | ||
2761 | res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx, | ||
2762 | WLAN_EID_RSN, WMI_RSN_IE_CAPB, | ||
2763 | (const u8 *) &rsn_capab, | ||
2764 | sizeof(rsn_capab)); | ||
2765 | if (res < 0) | ||
2766 | return res; | ||
2767 | } | ||
2768 | |||
2537 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2769 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
2538 | if (res < 0) | 2770 | if (res < 0) |
2539 | return res; | 2771 | return res; |
@@ -2568,6 +2800,13 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
2568 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | 2800 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); |
2569 | clear_bit(CONNECTED, &vif->flags); | 2801 | clear_bit(CONNECTED, &vif->flags); |
2570 | 2802 | ||
2803 | /* Restore ht setting in firmware */ | ||
2804 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) | ||
2805 | return -EIO; | ||
2806 | |||
2807 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) | ||
2808 | return -EIO; | ||
2809 | |||
2571 | return 0; | 2810 | return 0; |
2572 | } | 2811 | } |
2573 | 2812 | ||
@@ -2749,6 +2988,21 @@ static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif, | |||
2749 | return false; | 2988 | return false; |
2750 | } | 2989 | } |
2751 | 2990 | ||
2991 | /* Check if SSID length is greater than DIRECT- */ | ||
2992 | static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len) | ||
2993 | { | ||
2994 | const struct ieee80211_mgmt *mgmt; | ||
2995 | mgmt = (const struct ieee80211_mgmt *) buf; | ||
2996 | |||
2997 | /* variable[1] contains the SSID tag length */ | ||
2998 | if (buf + len >= &mgmt->u.probe_resp.variable[1] && | ||
2999 | (mgmt->u.probe_resp.variable[1] > P2P_WILDCARD_SSID_LEN)) { | ||
3000 | return true; | ||
3001 | } | ||
3002 | |||
3003 | return false; | ||
3004 | } | ||
3005 | |||
2752 | static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 3006 | static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
2753 | struct ieee80211_channel *chan, bool offchan, | 3007 | struct ieee80211_channel *chan, bool offchan, |
2754 | enum nl80211_channel_type channel_type, | 3008 | enum nl80211_channel_type channel_type, |
@@ -2763,11 +3017,11 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2763 | bool more_data, queued; | 3017 | bool more_data, queued; |
2764 | 3018 | ||
2765 | mgmt = (const struct ieee80211_mgmt *) buf; | 3019 | mgmt = (const struct ieee80211_mgmt *) buf; |
2766 | if (buf + len >= mgmt->u.probe_resp.variable && | 3020 | if (vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) && |
2767 | vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) && | 3021 | ieee80211_is_probe_resp(mgmt->frame_control) && |
2768 | ieee80211_is_probe_resp(mgmt->frame_control)) { | 3022 | ath6kl_is_p2p_go_ssid(buf, len)) { |
2769 | /* | 3023 | /* |
2770 | * Send Probe Response frame in AP mode using a separate WMI | 3024 | * Send Probe Response frame in GO mode using a separate WMI |
2771 | * command to allow the target to fill in the generic IEs. | 3025 | * command to allow the target to fill in the generic IEs. |
2772 | */ | 3026 | */ |
2773 | *cookie = 0; /* TX status not supported */ | 3027 | *cookie = 0; /* TX status not supported */ |
@@ -2835,6 +3089,8 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
2835 | if (vif->sme_state != SME_DISCONNECTED) | 3089 | if (vif->sme_state != SME_DISCONNECTED) |
2836 | return -EBUSY; | 3090 | return -EBUSY; |
2837 | 3091 | ||
3092 | ath6kl_cfg80211_scan_complete_event(vif, true); | ||
3093 | |||
2838 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { | 3094 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { |
2839 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | 3095 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, |
2840 | i, DISABLE_SSID_FLAG, | 3096 | i, DISABLE_SSID_FLAG, |
@@ -3096,6 +3352,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3096 | vif->next_mode = nw_type; | 3352 | vif->next_mode = nw_type; |
3097 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3353 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3098 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3354 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3355 | vif->htcap.ht_enable = true; | ||
3099 | 3356 | ||
3100 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3357 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
3101 | if (fw_vif_idx != 0) | 3358 | if (fw_vif_idx != 0) |
@@ -3183,6 +3440,10 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3183 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | 3440 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) |
3184 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 3441 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
3185 | 3442 | ||
3443 | if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, | ||
3444 | ar->fw_capabilities)) | ||
3445 | ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER; | ||
3446 | |||
3186 | ar->wiphy->probe_resp_offload = | 3447 | ar->wiphy->probe_resp_offload = |
3187 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 3448 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
3188 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 3449 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index a60e78c0472f..98a886154d9c 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -22,7 +22,8 @@ | |||
22 | 22 | ||
23 | #define ATH6KL_MAX_IE 256 | 23 | #define ATH6KL_MAX_IE 256 |
24 | 24 | ||
25 | extern int ath6kl_printk(const char *level, const char *fmt, ...); | 25 | extern __printf(2, 3) |
26 | int ath6kl_printk(const char *level, const char *fmt, ...); | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * Reflects the version of binary interface exposed by ATH6KL target | 29 | * Reflects the version of binary interface exposed by ATH6KL target |
@@ -77,6 +78,7 @@ enum crypto_type { | |||
77 | 78 | ||
78 | struct htc_endpoint_credit_dist; | 79 | struct htc_endpoint_credit_dist; |
79 | struct ath6kl; | 80 | struct ath6kl; |
81 | struct ath6kl_htcap; | ||
80 | enum htc_credit_dist_reason; | 82 | enum htc_credit_dist_reason; |
81 | struct ath6kl_htc_credit_info; | 83 | struct ath6kl_htc_credit_info; |
82 | 84 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 45e641f3a41b..fdb3b1decc76 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c | |||
@@ -20,9 +20,11 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/vmalloc.h> | ||
23 | 24 | ||
24 | #include "debug.h" | 25 | #include "debug.h" |
25 | #include "hif-ops.h" | 26 | #include "hif-ops.h" |
27 | #include "htc-ops.h" | ||
26 | #include "cfg80211.h" | 28 | #include "cfg80211.h" |
27 | 29 | ||
28 | unsigned int debug_mask; | 30 | unsigned int debug_mask; |
@@ -39,12 +41,36 @@ module_param(uart_debug, uint, 0644); | |||
39 | module_param(ath6kl_p2p, uint, 0644); | 41 | module_param(ath6kl_p2p, uint, 0644); |
40 | module_param(testmode, uint, 0644); | 42 | module_param(testmode, uint, 0644); |
41 | 43 | ||
42 | int ath6kl_core_init(struct ath6kl *ar) | 44 | void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb) |
45 | { | ||
46 | ath6kl_htc_tx_complete(ar, skb); | ||
47 | } | ||
48 | EXPORT_SYMBOL(ath6kl_core_tx_complete); | ||
49 | |||
50 | void ath6kl_core_rx_complete(struct ath6kl *ar, struct sk_buff *skb, u8 pipe) | ||
51 | { | ||
52 | ath6kl_htc_rx_complete(ar, skb, pipe); | ||
53 | } | ||
54 | EXPORT_SYMBOL(ath6kl_core_rx_complete); | ||
55 | |||
56 | int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) | ||
43 | { | 57 | { |
44 | struct ath6kl_bmi_target_info targ_info; | 58 | struct ath6kl_bmi_target_info targ_info; |
45 | struct net_device *ndev; | 59 | struct net_device *ndev; |
46 | int ret = 0, i; | 60 | int ret = 0, i; |
47 | 61 | ||
62 | switch (htc_type) { | ||
63 | case ATH6KL_HTC_TYPE_MBOX: | ||
64 | ath6kl_htc_mbox_attach(ar); | ||
65 | break; | ||
66 | case ATH6KL_HTC_TYPE_PIPE: | ||
67 | ath6kl_htc_pipe_attach(ar); | ||
68 | break; | ||
69 | default: | ||
70 | WARN_ON(1); | ||
71 | return -ENOMEM; | ||
72 | } | ||
73 | |||
48 | ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); | 74 | ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); |
49 | if (!ar->ath6kl_wq) | 75 | if (!ar->ath6kl_wq) |
50 | return -ENOMEM; | 76 | return -ENOMEM; |
@@ -280,7 +306,7 @@ void ath6kl_core_cleanup(struct ath6kl *ar) | |||
280 | 306 | ||
281 | kfree(ar->fw_board); | 307 | kfree(ar->fw_board); |
282 | kfree(ar->fw_otp); | 308 | kfree(ar->fw_otp); |
283 | kfree(ar->fw); | 309 | vfree(ar->fw); |
284 | kfree(ar->fw_patch); | 310 | kfree(ar->fw_patch); |
285 | kfree(ar->fw_testscript); | 311 | kfree(ar->fw_testscript); |
286 | 312 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index f1dd8906be45..9d67964a51dd 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -91,6 +91,15 @@ enum ath6kl_fw_capability { | |||
91 | */ | 91 | */ |
92 | ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, | 92 | ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, |
93 | 93 | ||
94 | /* | ||
95 | * Firmware has support to cleanup inactive stations | ||
96 | * in AP mode. | ||
97 | */ | ||
98 | ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, | ||
99 | |||
100 | /* Firmware has support to override rsn cap of rsn ie */ | ||
101 | ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | ||
102 | |||
94 | /* this needs to be last */ | 103 | /* this needs to be last */ |
95 | ATH6KL_FW_CAPABILITY_MAX, | 104 | ATH6KL_FW_CAPABILITY_MAX, |
96 | }; | 105 | }; |
@@ -205,6 +214,8 @@ struct ath6kl_fw_ie { | |||
205 | #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) | 214 | #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) |
206 | #define ATH6KL_CONF_UART_DEBUG BIT(4) | 215 | #define ATH6KL_CONF_UART_DEBUG BIT(4) |
207 | 216 | ||
217 | #define P2P_WILDCARD_SSID_LEN 7 /* DIRECT- */ | ||
218 | |||
208 | enum wlan_low_pwr_state { | 219 | enum wlan_low_pwr_state { |
209 | WLAN_POWER_STATE_ON, | 220 | WLAN_POWER_STATE_ON, |
210 | WLAN_POWER_STATE_CUT_PWR, | 221 | WLAN_POWER_STATE_CUT_PWR, |
@@ -454,6 +465,11 @@ enum ath6kl_hif_type { | |||
454 | ATH6KL_HIF_TYPE_USB, | 465 | ATH6KL_HIF_TYPE_USB, |
455 | }; | 466 | }; |
456 | 467 | ||
468 | enum ath6kl_htc_type { | ||
469 | ATH6KL_HTC_TYPE_MBOX, | ||
470 | ATH6KL_HTC_TYPE_PIPE, | ||
471 | }; | ||
472 | |||
457 | /* Max number of filters that hw supports */ | 473 | /* Max number of filters that hw supports */ |
458 | #define ATH6K_MAX_MC_FILTERS_PER_LIST 7 | 474 | #define ATH6K_MAX_MC_FILTERS_PER_LIST 7 |
459 | struct ath6kl_mc_filter { | 475 | struct ath6kl_mc_filter { |
@@ -461,6 +477,12 @@ struct ath6kl_mc_filter { | |||
461 | char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | 477 | char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; |
462 | }; | 478 | }; |
463 | 479 | ||
480 | struct ath6kl_htcap { | ||
481 | bool ht_enable; | ||
482 | u8 ampdu_factor; | ||
483 | unsigned short cap_info; | ||
484 | }; | ||
485 | |||
464 | /* | 486 | /* |
465 | * Driver's maximum limit, note that some firmwares support only one vif | 487 | * Driver's maximum limit, note that some firmwares support only one vif |
466 | * and the runtime (current) limit must be checked from ar->vif_max. | 488 | * and the runtime (current) limit must be checked from ar->vif_max. |
@@ -509,6 +531,7 @@ struct ath6kl_vif { | |||
509 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 531 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
510 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; | 532 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; |
511 | struct aggr_info *aggr_cntxt; | 533 | struct aggr_info *aggr_cntxt; |
534 | struct ath6kl_htcap htcap; | ||
512 | 535 | ||
513 | struct timer_list disconnect_timer; | 536 | struct timer_list disconnect_timer; |
514 | struct timer_list sched_scan_timer; | 537 | struct timer_list sched_scan_timer; |
@@ -521,6 +544,8 @@ struct ath6kl_vif { | |||
521 | u32 send_action_id; | 544 | u32 send_action_id; |
522 | bool probe_req_report; | 545 | bool probe_req_report; |
523 | u16 next_chan; | 546 | u16 next_chan; |
547 | enum nl80211_channel_type next_ch_type; | ||
548 | enum ieee80211_band next_ch_band; | ||
524 | u16 assoc_bss_beacon_int; | 549 | u16 assoc_bss_beacon_int; |
525 | u16 listen_intvl_t; | 550 | u16 listen_intvl_t; |
526 | u16 bmiss_time_t; | 551 | u16 bmiss_time_t; |
@@ -568,6 +593,7 @@ struct ath6kl { | |||
568 | 593 | ||
569 | struct ath6kl_bmi bmi; | 594 | struct ath6kl_bmi bmi; |
570 | const struct ath6kl_hif_ops *hif_ops; | 595 | const struct ath6kl_hif_ops *hif_ops; |
596 | const struct ath6kl_htc_ops *htc_ops; | ||
571 | struct wmi *wmi; | 597 | struct wmi *wmi; |
572 | int tx_pending[ENDPOINT_MAX]; | 598 | int tx_pending[ENDPOINT_MAX]; |
573 | int total_tx_data_pend; | 599 | int total_tx_data_pend; |
@@ -746,7 +772,8 @@ void init_netdev(struct net_device *dev); | |||
746 | void ath6kl_cookie_init(struct ath6kl *ar); | 772 | void ath6kl_cookie_init(struct ath6kl *ar); |
747 | void ath6kl_cookie_cleanup(struct ath6kl *ar); | 773 | void ath6kl_cookie_cleanup(struct ath6kl *ar); |
748 | void ath6kl_rx(struct htc_target *target, struct htc_packet *packet); | 774 | void ath6kl_rx(struct htc_target *target, struct htc_packet *packet); |
749 | void ath6kl_tx_complete(void *context, struct list_head *packet_queue); | 775 | void ath6kl_tx_complete(struct htc_target *context, |
776 | struct list_head *packet_queue); | ||
750 | enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | 777 | enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, |
751 | struct htc_packet *packet); | 778 | struct htc_packet *packet); |
752 | void ath6kl_stop_txrx(struct ath6kl *ar); | 779 | void ath6kl_stop_txrx(struct ath6kl *ar); |
@@ -821,8 +848,11 @@ int ath6kl_init_hw_params(struct ath6kl *ar); | |||
821 | 848 | ||
822 | void ath6kl_check_wow_status(struct ath6kl *ar); | 849 | void ath6kl_check_wow_status(struct ath6kl *ar); |
823 | 850 | ||
851 | void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb); | ||
852 | void ath6kl_core_rx_complete(struct ath6kl *ar, struct sk_buff *skb, u8 pipe); | ||
853 | |||
824 | struct ath6kl *ath6kl_core_create(struct device *dev); | 854 | struct ath6kl *ath6kl_core_create(struct device *dev); |
825 | int ath6kl_core_init(struct ath6kl *ar); | 855 | int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type); |
826 | void ath6kl_core_cleanup(struct ath6kl *ar); | 856 | void ath6kl_core_cleanup(struct ath6kl *ar); |
827 | void ath6kl_core_destroy(struct ath6kl *ar); | 857 | void ath6kl_core_destroy(struct ath6kl *ar); |
828 | 858 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index d01403a263ff..1b76aff78508 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -616,6 +616,12 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | |||
616 | "Num disconnects", tgt_stats->cs_discon_cnt); | 616 | "Num disconnects", tgt_stats->cs_discon_cnt); |
617 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | 617 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", |
618 | "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); | 618 | "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); |
619 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | ||
620 | "ARP pkt received", tgt_stats->arp_received); | ||
621 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | ||
622 | "ARP pkt matched", tgt_stats->arp_matched); | ||
623 | len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", | ||
624 | "ARP pkt replied", tgt_stats->arp_replied); | ||
619 | 625 | ||
620 | if (len > buf_len) | 626 | if (len > buf_len) |
621 | len = buf_len; | 627 | len = buf_len; |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 1803a0baae82..49639d8266c2 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -43,6 +43,7 @@ enum ATH6K_DEBUG_MASK { | |||
43 | ATH6KL_DBG_WMI_DUMP = BIT(19), | 43 | ATH6KL_DBG_WMI_DUMP = BIT(19), |
44 | ATH6KL_DBG_SUSPEND = BIT(20), | 44 | ATH6KL_DBG_SUSPEND = BIT(20), |
45 | ATH6KL_DBG_USB = BIT(21), | 45 | ATH6KL_DBG_USB = BIT(21), |
46 | ATH6KL_DBG_USB_BULK = BIT(22), | ||
46 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ | 47 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ |
47 | }; | 48 | }; |
48 | 49 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h index fd84086638e3..8c9e72d5250d 100644 --- a/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h | |||
@@ -150,4 +150,38 @@ static inline void ath6kl_hif_stop(struct ath6kl *ar) | |||
150 | ar->hif_ops->stop(ar); | 150 | ar->hif_ops->stop(ar); |
151 | } | 151 | } |
152 | 152 | ||
153 | static inline int ath6kl_hif_pipe_send(struct ath6kl *ar, | ||
154 | u8 pipe, struct sk_buff *hdr_buf, | ||
155 | struct sk_buff *buf) | ||
156 | { | ||
157 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif pipe send\n"); | ||
158 | |||
159 | return ar->hif_ops->pipe_send(ar, pipe, hdr_buf, buf); | ||
160 | } | ||
161 | |||
162 | static inline void ath6kl_hif_pipe_get_default(struct ath6kl *ar, | ||
163 | u8 *ul_pipe, u8 *dl_pipe) | ||
164 | { | ||
165 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif pipe get default\n"); | ||
166 | |||
167 | ar->hif_ops->pipe_get_default(ar, ul_pipe, dl_pipe); | ||
168 | } | ||
169 | |||
170 | static inline int ath6kl_hif_pipe_map_service(struct ath6kl *ar, | ||
171 | u16 service_id, u8 *ul_pipe, | ||
172 | u8 *dl_pipe) | ||
173 | { | ||
174 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif pipe get default\n"); | ||
175 | |||
176 | return ar->hif_ops->pipe_map_service(ar, service_id, ul_pipe, dl_pipe); | ||
177 | } | ||
178 | |||
179 | static inline u16 ath6kl_hif_pipe_get_free_queue_number(struct ath6kl *ar, | ||
180 | u8 pipe) | ||
181 | { | ||
182 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif pipe get free queue number\n"); | ||
183 | |||
184 | return ar->hif_ops->pipe_get_free_queue_number(ar, pipe); | ||
185 | } | ||
186 | |||
153 | #endif | 187 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h index 20ed6b73517b..61f6b21fb0ae 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.h +++ b/drivers/net/wireless/ath/ath6kl/hif.h | |||
@@ -256,6 +256,12 @@ struct ath6kl_hif_ops { | |||
256 | int (*power_on)(struct ath6kl *ar); | 256 | int (*power_on)(struct ath6kl *ar); |
257 | int (*power_off)(struct ath6kl *ar); | 257 | int (*power_off)(struct ath6kl *ar); |
258 | void (*stop)(struct ath6kl *ar); | 258 | void (*stop)(struct ath6kl *ar); |
259 | int (*pipe_send)(struct ath6kl *ar, u8 pipe, struct sk_buff *hdr_buf, | ||
260 | struct sk_buff *buf); | ||
261 | void (*pipe_get_default)(struct ath6kl *ar, u8 *pipe_ul, u8 *pipe_dl); | ||
262 | int (*pipe_map_service)(struct ath6kl *ar, u16 service_id, u8 *pipe_ul, | ||
263 | u8 *pipe_dl); | ||
264 | u16 (*pipe_get_free_queue_number)(struct ath6kl *ar, u8 pipe); | ||
259 | }; | 265 | }; |
260 | 266 | ||
261 | int ath6kl_hif_setup(struct ath6kl_device *dev); | 267 | int ath6kl_hif_setup(struct ath6kl_device *dev); |
diff --git a/drivers/net/wireless/ath/ath6kl/htc-ops.h b/drivers/net/wireless/ath/ath6kl/htc-ops.h new file mode 100644 index 000000000000..2d4eed55cfd1 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc-ops.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2011 Atheros Communications 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 | #ifndef HTC_OPS_H | ||
18 | #define HTC_OPS_H | ||
19 | |||
20 | #include "htc.h" | ||
21 | #include "debug.h" | ||
22 | |||
23 | static inline void *ath6kl_htc_create(struct ath6kl *ar) | ||
24 | { | ||
25 | return ar->htc_ops->create(ar); | ||
26 | } | ||
27 | |||
28 | static inline int ath6kl_htc_wait_target(struct htc_target *target) | ||
29 | { | ||
30 | return target->dev->ar->htc_ops->wait_target(target); | ||
31 | } | ||
32 | |||
33 | static inline int ath6kl_htc_start(struct htc_target *target) | ||
34 | { | ||
35 | return target->dev->ar->htc_ops->start(target); | ||
36 | } | ||
37 | |||
38 | static inline int ath6kl_htc_conn_service(struct htc_target *target, | ||
39 | struct htc_service_connect_req *req, | ||
40 | struct htc_service_connect_resp *resp) | ||
41 | { | ||
42 | return target->dev->ar->htc_ops->conn_service(target, req, resp); | ||
43 | } | ||
44 | |||
45 | static inline int ath6kl_htc_tx(struct htc_target *target, | ||
46 | struct htc_packet *packet) | ||
47 | { | ||
48 | return target->dev->ar->htc_ops->tx(target, packet); | ||
49 | } | ||
50 | |||
51 | static inline void ath6kl_htc_stop(struct htc_target *target) | ||
52 | { | ||
53 | return target->dev->ar->htc_ops->stop(target); | ||
54 | } | ||
55 | |||
56 | static inline void ath6kl_htc_cleanup(struct htc_target *target) | ||
57 | { | ||
58 | return target->dev->ar->htc_ops->cleanup(target); | ||
59 | } | ||
60 | |||
61 | static inline void ath6kl_htc_flush_txep(struct htc_target *target, | ||
62 | enum htc_endpoint_id endpoint, | ||
63 | u16 tag) | ||
64 | { | ||
65 | return target->dev->ar->htc_ops->flush_txep(target, endpoint, tag); | ||
66 | } | ||
67 | |||
68 | static inline void ath6kl_htc_flush_rx_buf(struct htc_target *target) | ||
69 | { | ||
70 | return target->dev->ar->htc_ops->flush_rx_buf(target); | ||
71 | } | ||
72 | |||
73 | static inline void ath6kl_htc_activity_changed(struct htc_target *target, | ||
74 | enum htc_endpoint_id endpoint, | ||
75 | bool active) | ||
76 | { | ||
77 | return target->dev->ar->htc_ops->activity_changed(target, endpoint, | ||
78 | active); | ||
79 | } | ||
80 | |||
81 | static inline int ath6kl_htc_get_rxbuf_num(struct htc_target *target, | ||
82 | enum htc_endpoint_id endpoint) | ||
83 | { | ||
84 | return target->dev->ar->htc_ops->get_rxbuf_num(target, endpoint); | ||
85 | } | ||
86 | |||
87 | static inline int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | ||
88 | struct list_head *pktq) | ||
89 | { | ||
90 | return target->dev->ar->htc_ops->add_rxbuf_multiple(target, pktq); | ||
91 | } | ||
92 | |||
93 | static inline int ath6kl_htc_credit_setup(struct htc_target *target, | ||
94 | struct ath6kl_htc_credit_info *info) | ||
95 | { | ||
96 | return target->dev->ar->htc_ops->credit_setup(target, info); | ||
97 | } | ||
98 | |||
99 | static inline void ath6kl_htc_tx_complete(struct ath6kl *ar, | ||
100 | struct sk_buff *skb) | ||
101 | { | ||
102 | ar->htc_ops->tx_complete(ar, skb); | ||
103 | } | ||
104 | |||
105 | |||
106 | static inline void ath6kl_htc_rx_complete(struct ath6kl *ar, | ||
107 | struct sk_buff *skb, u8 pipe) | ||
108 | { | ||
109 | ar->htc_ops->rx_complete(ar, skb, pipe); | ||
110 | } | ||
111 | |||
112 | |||
113 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h index 5027ccc36b62..a2c8ff809793 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.h +++ b/drivers/net/wireless/ath/ath6kl/htc.h | |||
@@ -25,6 +25,7 @@ | |||
25 | /* send direction */ | 25 | /* send direction */ |
26 | #define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) | 26 | #define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) |
27 | #define HTC_FLAGS_SEND_BUNDLE (1 << 1) | 27 | #define HTC_FLAGS_SEND_BUNDLE (1 << 1) |
28 | #define HTC_FLAGS_TX_FIXUP_NETBUF (1 << 2) | ||
28 | 29 | ||
29 | /* receive direction */ | 30 | /* receive direction */ |
30 | #define HTC_FLG_RX_UNUSED (1 << 0) | 31 | #define HTC_FLG_RX_UNUSED (1 << 0) |
@@ -56,6 +57,10 @@ | |||
56 | #define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2 | 57 | #define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2 |
57 | #define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4 | 58 | #define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4 |
58 | #define HTC_CONN_FLGS_THRESH_MASK 0x3 | 59 | #define HTC_CONN_FLGS_THRESH_MASK 0x3 |
60 | /* disable credit flow control on a specific service */ | ||
61 | #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) | ||
62 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 | ||
63 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00 | ||
59 | 64 | ||
60 | /* connect response status codes */ | 65 | /* connect response status codes */ |
61 | #define HTC_SERVICE_SUCCESS 0 | 66 | #define HTC_SERVICE_SUCCESS 0 |
@@ -75,6 +80,7 @@ | |||
75 | #define HTC_RECORD_LOOKAHEAD_BUNDLE 3 | 80 | #define HTC_RECORD_LOOKAHEAD_BUNDLE 3 |
76 | 81 | ||
77 | #define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0) | 82 | #define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0) |
83 | #define HTC_SETUP_COMP_FLG_DISABLE_TX_CREDIT_FLOW (1 << 1) | ||
78 | 84 | ||
79 | #define MAKE_SERVICE_ID(group, index) \ | 85 | #define MAKE_SERVICE_ID(group, index) \ |
80 | (int)(((int)group << 8) | (int)(index)) | 86 | (int)(((int)group << 8) | (int)(index)) |
@@ -109,6 +115,8 @@ | |||
109 | 115 | ||
110 | /* HTC operational parameters */ | 116 | /* HTC operational parameters */ |
111 | #define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ | 117 | #define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ |
118 | #define HTC_TARGET_RESPONSE_POLL_WAIT 10 | ||
119 | #define HTC_TARGET_RESPONSE_POLL_COUNT 200 | ||
112 | #define HTC_TARGET_DEBUG_INTR_MASK 0x01 | 120 | #define HTC_TARGET_DEBUG_INTR_MASK 0x01 |
113 | #define HTC_TARGET_CREDIT_INTR_MASK 0xF0 | 121 | #define HTC_TARGET_CREDIT_INTR_MASK 0xF0 |
114 | 122 | ||
@@ -128,6 +136,7 @@ | |||
128 | 136 | ||
129 | #define HTC_RECV_WAIT_BUFFERS (1 << 0) | 137 | #define HTC_RECV_WAIT_BUFFERS (1 << 0) |
130 | #define HTC_OP_STATE_STOPPING (1 << 0) | 138 | #define HTC_OP_STATE_STOPPING (1 << 0) |
139 | #define HTC_OP_STATE_SETUP_COMPLETE (1 << 1) | ||
131 | 140 | ||
132 | /* | 141 | /* |
133 | * The frame header length and message formats defined herein were selected | 142 | * The frame header length and message formats defined herein were selected |
@@ -311,6 +320,14 @@ struct htc_packet { | |||
311 | 320 | ||
312 | void (*completion) (struct htc_target *, struct htc_packet *); | 321 | void (*completion) (struct htc_target *, struct htc_packet *); |
313 | struct htc_target *context; | 322 | struct htc_target *context; |
323 | |||
324 | /* | ||
325 | * optimization for network-oriented data, the HTC packet | ||
326 | * can pass the network buffer corresponding to the HTC packet | ||
327 | * lower layers may optimized the transfer knowing this is | ||
328 | * a network buffer | ||
329 | */ | ||
330 | struct sk_buff *skb; | ||
314 | }; | 331 | }; |
315 | 332 | ||
316 | enum htc_send_full_action { | 333 | enum htc_send_full_action { |
@@ -319,12 +336,14 @@ enum htc_send_full_action { | |||
319 | }; | 336 | }; |
320 | 337 | ||
321 | struct htc_ep_callbacks { | 338 | struct htc_ep_callbacks { |
339 | void (*tx_complete) (struct htc_target *, struct htc_packet *); | ||
322 | void (*rx) (struct htc_target *, struct htc_packet *); | 340 | void (*rx) (struct htc_target *, struct htc_packet *); |
323 | void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint); | 341 | void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint); |
324 | enum htc_send_full_action (*tx_full) (struct htc_target *, | 342 | enum htc_send_full_action (*tx_full) (struct htc_target *, |
325 | struct htc_packet *); | 343 | struct htc_packet *); |
326 | struct htc_packet *(*rx_allocthresh) (struct htc_target *, | 344 | struct htc_packet *(*rx_allocthresh) (struct htc_target *, |
327 | enum htc_endpoint_id, int); | 345 | enum htc_endpoint_id, int); |
346 | void (*tx_comp_multi) (struct htc_target *, struct list_head *); | ||
328 | int rx_alloc_thresh; | 347 | int rx_alloc_thresh; |
329 | int rx_refill_thresh; | 348 | int rx_refill_thresh; |
330 | }; | 349 | }; |
@@ -502,6 +521,13 @@ struct htc_endpoint { | |||
502 | u32 conn_flags; | 521 | u32 conn_flags; |
503 | struct htc_endpoint_stats ep_st; | 522 | struct htc_endpoint_stats ep_st; |
504 | u16 tx_drop_packet_threshold; | 523 | u16 tx_drop_packet_threshold; |
524 | |||
525 | struct { | ||
526 | u8 pipeid_ul; | ||
527 | u8 pipeid_dl; | ||
528 | struct list_head tx_lookup_queue; | ||
529 | bool tx_credit_flow_enabled; | ||
530 | } pipe; | ||
505 | }; | 531 | }; |
506 | 532 | ||
507 | struct htc_control_buffer { | 533 | struct htc_control_buffer { |
@@ -509,6 +535,42 @@ struct htc_control_buffer { | |||
509 | u8 *buf; | 535 | u8 *buf; |
510 | }; | 536 | }; |
511 | 537 | ||
538 | struct htc_pipe_txcredit_alloc { | ||
539 | u16 service_id; | ||
540 | u8 credit_alloc; | ||
541 | }; | ||
542 | |||
543 | enum htc_send_queue_result { | ||
544 | HTC_SEND_QUEUE_OK = 0, /* packet was queued */ | ||
545 | HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */ | ||
546 | }; | ||
547 | |||
548 | struct ath6kl_htc_ops { | ||
549 | void* (*create)(struct ath6kl *ar); | ||
550 | int (*wait_target)(struct htc_target *target); | ||
551 | int (*start)(struct htc_target *target); | ||
552 | int (*conn_service)(struct htc_target *target, | ||
553 | struct htc_service_connect_req *req, | ||
554 | struct htc_service_connect_resp *resp); | ||
555 | int (*tx)(struct htc_target *target, struct htc_packet *packet); | ||
556 | void (*stop)(struct htc_target *target); | ||
557 | void (*cleanup)(struct htc_target *target); | ||
558 | void (*flush_txep)(struct htc_target *target, | ||
559 | enum htc_endpoint_id endpoint, u16 tag); | ||
560 | void (*flush_rx_buf)(struct htc_target *target); | ||
561 | void (*activity_changed)(struct htc_target *target, | ||
562 | enum htc_endpoint_id endpoint, | ||
563 | bool active); | ||
564 | int (*get_rxbuf_num)(struct htc_target *target, | ||
565 | enum htc_endpoint_id endpoint); | ||
566 | int (*add_rxbuf_multiple)(struct htc_target *target, | ||
567 | struct list_head *pktq); | ||
568 | int (*credit_setup)(struct htc_target *target, | ||
569 | struct ath6kl_htc_credit_info *cred_info); | ||
570 | int (*tx_complete)(struct ath6kl *ar, struct sk_buff *skb); | ||
571 | int (*rx_complete)(struct ath6kl *ar, struct sk_buff *skb, u8 pipe); | ||
572 | }; | ||
573 | |||
512 | struct ath6kl_device; | 574 | struct ath6kl_device; |
513 | 575 | ||
514 | /* our HTC target state */ | 576 | /* our HTC target state */ |
@@ -557,36 +619,19 @@ struct htc_target { | |||
557 | 619 | ||
558 | /* counts the number of Tx without bundling continously per AC */ | 620 | /* counts the number of Tx without bundling continously per AC */ |
559 | u32 ac_tx_count[WMM_NUM_AC]; | 621 | u32 ac_tx_count[WMM_NUM_AC]; |
622 | |||
623 | struct { | ||
624 | struct htc_packet *htc_packet_pool; | ||
625 | u8 ctrl_response_buf[HTC_MAX_CTRL_MSG_LEN]; | ||
626 | int ctrl_response_len; | ||
627 | bool ctrl_response_valid; | ||
628 | struct htc_pipe_txcredit_alloc txcredit_alloc[ENDPOINT_MAX]; | ||
629 | } pipe; | ||
560 | }; | 630 | }; |
561 | 631 | ||
562 | void *ath6kl_htc_create(struct ath6kl *ar); | ||
563 | void ath6kl_htc_set_credit_dist(struct htc_target *target, | ||
564 | struct ath6kl_htc_credit_info *cred_info, | ||
565 | u16 svc_pri_order[], int len); | ||
566 | int ath6kl_htc_wait_target(struct htc_target *target); | ||
567 | int ath6kl_htc_start(struct htc_target *target); | ||
568 | int ath6kl_htc_conn_service(struct htc_target *target, | ||
569 | struct htc_service_connect_req *req, | ||
570 | struct htc_service_connect_resp *resp); | ||
571 | int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet); | ||
572 | void ath6kl_htc_stop(struct htc_target *target); | ||
573 | void ath6kl_htc_cleanup(struct htc_target *target); | ||
574 | void ath6kl_htc_flush_txep(struct htc_target *target, | ||
575 | enum htc_endpoint_id endpoint, u16 tag); | ||
576 | void ath6kl_htc_flush_rx_buf(struct htc_target *target); | ||
577 | void ath6kl_htc_indicate_activity_change(struct htc_target *target, | ||
578 | enum htc_endpoint_id endpoint, | ||
579 | bool active); | ||
580 | int ath6kl_htc_get_rxbuf_num(struct htc_target *target, | ||
581 | enum htc_endpoint_id endpoint); | ||
582 | int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | ||
583 | struct list_head *pktq); | ||
584 | int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, | 632 | int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, |
585 | u32 msg_look_ahead, int *n_pkts); | 633 | u32 msg_look_ahead, int *n_pkts); |
586 | 634 | ||
587 | int ath6kl_credit_setup(void *htc_handle, | ||
588 | struct ath6kl_htc_credit_info *cred_info); | ||
589 | |||
590 | static inline void set_htc_pkt_info(struct htc_packet *packet, void *context, | 635 | static inline void set_htc_pkt_info(struct htc_packet *packet, void *context, |
591 | u8 *buf, unsigned int len, | 636 | u8 *buf, unsigned int len, |
592 | enum htc_endpoint_id eid, u16 tag) | 637 | enum htc_endpoint_id eid, u16 tag) |
@@ -626,4 +671,7 @@ static inline int get_queue_depth(struct list_head *queue) | |||
626 | return depth; | 671 | return depth; |
627 | } | 672 | } |
628 | 673 | ||
674 | void ath6kl_htc_pipe_attach(struct ath6kl *ar); | ||
675 | void ath6kl_htc_mbox_attach(struct ath6kl *ar); | ||
676 | |||
629 | #endif | 677 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 4849d99cce77..065e61516d7a 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -23,6 +23,14 @@ | |||
23 | 23 | ||
24 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) | 24 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) |
25 | 25 | ||
26 | static void ath6kl_htc_mbox_cleanup(struct htc_target *target); | ||
27 | static void ath6kl_htc_mbox_stop(struct htc_target *target); | ||
28 | static int ath6kl_htc_mbox_add_rxbuf_multiple(struct htc_target *target, | ||
29 | struct list_head *pkt_queue); | ||
30 | static void ath6kl_htc_set_credit_dist(struct htc_target *target, | ||
31 | struct ath6kl_htc_credit_info *cred_info, | ||
32 | u16 svc_pri_order[], int len); | ||
33 | |||
26 | /* threshold to re-enable Tx bundling for an AC*/ | 34 | /* threshold to re-enable Tx bundling for an AC*/ |
27 | #define TX_RESUME_BUNDLE_THRESHOLD 1500 | 35 | #define TX_RESUME_BUNDLE_THRESHOLD 1500 |
28 | 36 | ||
@@ -130,8 +138,8 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info, | |||
130 | } | 138 | } |
131 | 139 | ||
132 | /* initialize and setup credit distribution */ | 140 | /* initialize and setup credit distribution */ |
133 | int ath6kl_credit_setup(void *htc_handle, | 141 | static int ath6kl_htc_mbox_credit_setup(struct htc_target *htc_target, |
134 | struct ath6kl_htc_credit_info *cred_info) | 142 | struct ath6kl_htc_credit_info *cred_info) |
135 | { | 143 | { |
136 | u16 servicepriority[5]; | 144 | u16 servicepriority[5]; |
137 | 145 | ||
@@ -144,7 +152,7 @@ int ath6kl_credit_setup(void *htc_handle, | |||
144 | servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ | 152 | servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ |
145 | 153 | ||
146 | /* set priority list */ | 154 | /* set priority list */ |
147 | ath6kl_htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5); | 155 | ath6kl_htc_set_credit_dist(htc_target, cred_info, servicepriority, 5); |
148 | 156 | ||
149 | return 0; | 157 | return 0; |
150 | } | 158 | } |
@@ -432,7 +440,7 @@ static void htc_tx_complete(struct htc_endpoint *endpoint, | |||
432 | "htc tx complete ep %d pkts %d\n", | 440 | "htc tx complete ep %d pkts %d\n", |
433 | endpoint->eid, get_queue_depth(txq)); | 441 | endpoint->eid, get_queue_depth(txq)); |
434 | 442 | ||
435 | ath6kl_tx_complete(endpoint->target->dev->ar, txq); | 443 | ath6kl_tx_complete(endpoint->target, txq); |
436 | } | 444 | } |
437 | 445 | ||
438 | static void htc_tx_comp_handler(struct htc_target *target, | 446 | static void htc_tx_comp_handler(struct htc_target *target, |
@@ -1065,7 +1073,7 @@ static int htc_setup_tx_complete(struct htc_target *target) | |||
1065 | return status; | 1073 | return status; |
1066 | } | 1074 | } |
1067 | 1075 | ||
1068 | void ath6kl_htc_set_credit_dist(struct htc_target *target, | 1076 | static void ath6kl_htc_set_credit_dist(struct htc_target *target, |
1069 | struct ath6kl_htc_credit_info *credit_info, | 1077 | struct ath6kl_htc_credit_info *credit_info, |
1070 | u16 srvc_pri_order[], int list_len) | 1078 | u16 srvc_pri_order[], int list_len) |
1071 | { | 1079 | { |
@@ -1093,7 +1101,8 @@ void ath6kl_htc_set_credit_dist(struct htc_target *target, | |||
1093 | } | 1101 | } |
1094 | } | 1102 | } |
1095 | 1103 | ||
1096 | int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet) | 1104 | static int ath6kl_htc_mbox_tx(struct htc_target *target, |
1105 | struct htc_packet *packet) | ||
1097 | { | 1106 | { |
1098 | struct htc_endpoint *endpoint; | 1107 | struct htc_endpoint *endpoint; |
1099 | struct list_head queue; | 1108 | struct list_head queue; |
@@ -1121,7 +1130,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet) | |||
1121 | } | 1130 | } |
1122 | 1131 | ||
1123 | /* flush endpoint TX queue */ | 1132 | /* flush endpoint TX queue */ |
1124 | void ath6kl_htc_flush_txep(struct htc_target *target, | 1133 | static void ath6kl_htc_mbox_flush_txep(struct htc_target *target, |
1125 | enum htc_endpoint_id eid, u16 tag) | 1134 | enum htc_endpoint_id eid, u16 tag) |
1126 | { | 1135 | { |
1127 | struct htc_packet *packet, *tmp_pkt; | 1136 | struct htc_packet *packet, *tmp_pkt; |
@@ -1173,12 +1182,13 @@ static void ath6kl_htc_flush_txep_all(struct htc_target *target) | |||
1173 | if (endpoint->svc_id == 0) | 1182 | if (endpoint->svc_id == 0) |
1174 | /* not in use.. */ | 1183 | /* not in use.. */ |
1175 | continue; | 1184 | continue; |
1176 | ath6kl_htc_flush_txep(target, i, HTC_TX_PACKET_TAG_ALL); | 1185 | ath6kl_htc_mbox_flush_txep(target, i, HTC_TX_PACKET_TAG_ALL); |
1177 | } | 1186 | } |
1178 | } | 1187 | } |
1179 | 1188 | ||
1180 | void ath6kl_htc_indicate_activity_change(struct htc_target *target, | 1189 | static void ath6kl_htc_mbox_activity_changed(struct htc_target *target, |
1181 | enum htc_endpoint_id eid, bool active) | 1190 | enum htc_endpoint_id eid, |
1191 | bool active) | ||
1182 | { | 1192 | { |
1183 | struct htc_endpoint *endpoint = &target->endpoint[eid]; | 1193 | struct htc_endpoint *endpoint = &target->endpoint[eid]; |
1184 | bool dist = false; | 1194 | bool dist = false; |
@@ -1246,7 +1256,7 @@ static int htc_add_rxbuf(struct htc_target *target, struct htc_packet *packet) | |||
1246 | 1256 | ||
1247 | INIT_LIST_HEAD(&queue); | 1257 | INIT_LIST_HEAD(&queue); |
1248 | list_add_tail(&packet->list, &queue); | 1258 | list_add_tail(&packet->list, &queue); |
1249 | return ath6kl_htc_add_rxbuf_multiple(target, &queue); | 1259 | return ath6kl_htc_mbox_add_rxbuf_multiple(target, &queue); |
1250 | } | 1260 | } |
1251 | 1261 | ||
1252 | static void htc_reclaim_rxbuf(struct htc_target *target, | 1262 | static void htc_reclaim_rxbuf(struct htc_target *target, |
@@ -1353,7 +1363,9 @@ static int ath6kl_htc_rx_setup(struct htc_target *target, | |||
1353 | sizeof(*htc_hdr)); | 1363 | sizeof(*htc_hdr)); |
1354 | 1364 | ||
1355 | if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) { | 1365 | if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) { |
1356 | ath6kl_warn("Rx buffer requested with invalid length\n"); | 1366 | ath6kl_warn("Rx buffer requested with invalid length htc_hdr:eid %d, flags 0x%x, len %d\n", |
1367 | htc_hdr->eid, htc_hdr->flags, | ||
1368 | le16_to_cpu(htc_hdr->payld_len)); | ||
1357 | return -EINVAL; | 1369 | return -EINVAL; |
1358 | } | 1370 | } |
1359 | 1371 | ||
@@ -2288,7 +2300,7 @@ fail_ctrl_rx: | |||
2288 | return NULL; | 2300 | return NULL; |
2289 | } | 2301 | } |
2290 | 2302 | ||
2291 | int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | 2303 | static int ath6kl_htc_mbox_add_rxbuf_multiple(struct htc_target *target, |
2292 | struct list_head *pkt_queue) | 2304 | struct list_head *pkt_queue) |
2293 | { | 2305 | { |
2294 | struct htc_endpoint *endpoint; | 2306 | struct htc_endpoint *endpoint; |
@@ -2350,7 +2362,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, | |||
2350 | return status; | 2362 | return status; |
2351 | } | 2363 | } |
2352 | 2364 | ||
2353 | void ath6kl_htc_flush_rx_buf(struct htc_target *target) | 2365 | static void ath6kl_htc_mbox_flush_rx_buf(struct htc_target *target) |
2354 | { | 2366 | { |
2355 | struct htc_endpoint *endpoint; | 2367 | struct htc_endpoint *endpoint; |
2356 | struct htc_packet *packet, *tmp_pkt; | 2368 | struct htc_packet *packet, *tmp_pkt; |
@@ -2392,7 +2404,7 @@ void ath6kl_htc_flush_rx_buf(struct htc_target *target) | |||
2392 | } | 2404 | } |
2393 | } | 2405 | } |
2394 | 2406 | ||
2395 | int ath6kl_htc_conn_service(struct htc_target *target, | 2407 | static int ath6kl_htc_mbox_conn_service(struct htc_target *target, |
2396 | struct htc_service_connect_req *conn_req, | 2408 | struct htc_service_connect_req *conn_req, |
2397 | struct htc_service_connect_resp *conn_resp) | 2409 | struct htc_service_connect_resp *conn_resp) |
2398 | { | 2410 | { |
@@ -2564,7 +2576,7 @@ static void reset_ep_state(struct htc_target *target) | |||
2564 | INIT_LIST_HEAD(&target->cred_dist_list); | 2576 | INIT_LIST_HEAD(&target->cred_dist_list); |
2565 | } | 2577 | } |
2566 | 2578 | ||
2567 | int ath6kl_htc_get_rxbuf_num(struct htc_target *target, | 2579 | static int ath6kl_htc_mbox_get_rxbuf_num(struct htc_target *target, |
2568 | enum htc_endpoint_id endpoint) | 2580 | enum htc_endpoint_id endpoint) |
2569 | { | 2581 | { |
2570 | int num; | 2582 | int num; |
@@ -2624,7 +2636,7 @@ static void htc_setup_msg_bndl(struct htc_target *target) | |||
2624 | } | 2636 | } |
2625 | } | 2637 | } |
2626 | 2638 | ||
2627 | int ath6kl_htc_wait_target(struct htc_target *target) | 2639 | static int ath6kl_htc_mbox_wait_target(struct htc_target *target) |
2628 | { | 2640 | { |
2629 | struct htc_packet *packet = NULL; | 2641 | struct htc_packet *packet = NULL; |
2630 | struct htc_ready_ext_msg *rdy_msg; | 2642 | struct htc_ready_ext_msg *rdy_msg; |
@@ -2693,12 +2705,12 @@ int ath6kl_htc_wait_target(struct htc_target *target) | |||
2693 | connect.svc_id = HTC_CTRL_RSVD_SVC; | 2705 | connect.svc_id = HTC_CTRL_RSVD_SVC; |
2694 | 2706 | ||
2695 | /* connect fake service */ | 2707 | /* connect fake service */ |
2696 | status = ath6kl_htc_conn_service((void *)target, &connect, &resp); | 2708 | status = ath6kl_htc_mbox_conn_service((void *)target, &connect, &resp); |
2697 | 2709 | ||
2698 | if (status) | 2710 | if (status) |
2699 | /* | 2711 | /* |
2700 | * FIXME: this call doesn't make sense, the caller should | 2712 | * FIXME: this call doesn't make sense, the caller should |
2701 | * call ath6kl_htc_cleanup() when it wants remove htc | 2713 | * call ath6kl_htc_mbox_cleanup() when it wants remove htc |
2702 | */ | 2714 | */ |
2703 | ath6kl_hif_cleanup_scatter(target->dev->ar); | 2715 | ath6kl_hif_cleanup_scatter(target->dev->ar); |
2704 | 2716 | ||
@@ -2715,7 +2727,7 @@ fail_wait_target: | |||
2715 | * Start HTC, enable interrupts and let the target know | 2727 | * Start HTC, enable interrupts and let the target know |
2716 | * host has finished setup. | 2728 | * host has finished setup. |
2717 | */ | 2729 | */ |
2718 | int ath6kl_htc_start(struct htc_target *target) | 2730 | static int ath6kl_htc_mbox_start(struct htc_target *target) |
2719 | { | 2731 | { |
2720 | struct htc_packet *packet; | 2732 | struct htc_packet *packet; |
2721 | int status; | 2733 | int status; |
@@ -2752,7 +2764,7 @@ int ath6kl_htc_start(struct htc_target *target) | |||
2752 | status = ath6kl_hif_unmask_intrs(target->dev); | 2764 | status = ath6kl_hif_unmask_intrs(target->dev); |
2753 | 2765 | ||
2754 | if (status) | 2766 | if (status) |
2755 | ath6kl_htc_stop(target); | 2767 | ath6kl_htc_mbox_stop(target); |
2756 | 2768 | ||
2757 | return status; | 2769 | return status; |
2758 | } | 2770 | } |
@@ -2796,7 +2808,7 @@ static int ath6kl_htc_reset(struct htc_target *target) | |||
2796 | } | 2808 | } |
2797 | 2809 | ||
2798 | /* htc_stop: stop interrupt reception, and flush all queued buffers */ | 2810 | /* htc_stop: stop interrupt reception, and flush all queued buffers */ |
2799 | void ath6kl_htc_stop(struct htc_target *target) | 2811 | static void ath6kl_htc_mbox_stop(struct htc_target *target) |
2800 | { | 2812 | { |
2801 | spin_lock_bh(&target->htc_lock); | 2813 | spin_lock_bh(&target->htc_lock); |
2802 | target->htc_flags |= HTC_OP_STATE_STOPPING; | 2814 | target->htc_flags |= HTC_OP_STATE_STOPPING; |
@@ -2811,12 +2823,12 @@ void ath6kl_htc_stop(struct htc_target *target) | |||
2811 | 2823 | ||
2812 | ath6kl_htc_flush_txep_all(target); | 2824 | ath6kl_htc_flush_txep_all(target); |
2813 | 2825 | ||
2814 | ath6kl_htc_flush_rx_buf(target); | 2826 | ath6kl_htc_mbox_flush_rx_buf(target); |
2815 | 2827 | ||
2816 | ath6kl_htc_reset(target); | 2828 | ath6kl_htc_reset(target); |
2817 | } | 2829 | } |
2818 | 2830 | ||
2819 | void *ath6kl_htc_create(struct ath6kl *ar) | 2831 | static void *ath6kl_htc_mbox_create(struct ath6kl *ar) |
2820 | { | 2832 | { |
2821 | struct htc_target *target = NULL; | 2833 | struct htc_target *target = NULL; |
2822 | int status = 0; | 2834 | int status = 0; |
@@ -2857,13 +2869,13 @@ void *ath6kl_htc_create(struct ath6kl *ar) | |||
2857 | return target; | 2869 | return target; |
2858 | 2870 | ||
2859 | err_htc_cleanup: | 2871 | err_htc_cleanup: |
2860 | ath6kl_htc_cleanup(target); | 2872 | ath6kl_htc_mbox_cleanup(target); |
2861 | 2873 | ||
2862 | return NULL; | 2874 | return NULL; |
2863 | } | 2875 | } |
2864 | 2876 | ||
2865 | /* cleanup the HTC instance */ | 2877 | /* cleanup the HTC instance */ |
2866 | void ath6kl_htc_cleanup(struct htc_target *target) | 2878 | static void ath6kl_htc_mbox_cleanup(struct htc_target *target) |
2867 | { | 2879 | { |
2868 | struct htc_packet *packet, *tmp_packet; | 2880 | struct htc_packet *packet, *tmp_packet; |
2869 | 2881 | ||
@@ -2888,3 +2900,24 @@ void ath6kl_htc_cleanup(struct htc_target *target) | |||
2888 | kfree(target->dev); | 2900 | kfree(target->dev); |
2889 | kfree(target); | 2901 | kfree(target); |
2890 | } | 2902 | } |
2903 | |||
2904 | static const struct ath6kl_htc_ops ath6kl_htc_mbox_ops = { | ||
2905 | .create = ath6kl_htc_mbox_create, | ||
2906 | .wait_target = ath6kl_htc_mbox_wait_target, | ||
2907 | .start = ath6kl_htc_mbox_start, | ||
2908 | .conn_service = ath6kl_htc_mbox_conn_service, | ||
2909 | .tx = ath6kl_htc_mbox_tx, | ||
2910 | .stop = ath6kl_htc_mbox_stop, | ||
2911 | .cleanup = ath6kl_htc_mbox_cleanup, | ||
2912 | .flush_txep = ath6kl_htc_mbox_flush_txep, | ||
2913 | .flush_rx_buf = ath6kl_htc_mbox_flush_rx_buf, | ||
2914 | .activity_changed = ath6kl_htc_mbox_activity_changed, | ||
2915 | .get_rxbuf_num = ath6kl_htc_mbox_get_rxbuf_num, | ||
2916 | .add_rxbuf_multiple = ath6kl_htc_mbox_add_rxbuf_multiple, | ||
2917 | .credit_setup = ath6kl_htc_mbox_credit_setup, | ||
2918 | }; | ||
2919 | |||
2920 | void ath6kl_htc_mbox_attach(struct ath6kl *ar) | ||
2921 | { | ||
2922 | ar->htc_ops = &ath6kl_htc_mbox_ops; | ||
2923 | } | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c new file mode 100644 index 000000000000..b277b3446882 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
@@ -0,0 +1,1713 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2011 Atheros Communications 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 "core.h" | ||
18 | #include "debug.h" | ||
19 | #include "hif-ops.h" | ||
20 | |||
21 | #define HTC_PACKET_CONTAINER_ALLOCATION 32 | ||
22 | #define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH) | ||
23 | |||
24 | static int ath6kl_htc_pipe_tx(struct htc_target *handle, | ||
25 | struct htc_packet *packet); | ||
26 | static void ath6kl_htc_pipe_cleanup(struct htc_target *handle); | ||
27 | |||
28 | /* htc pipe tx path */ | ||
29 | static inline void restore_tx_packet(struct htc_packet *packet) | ||
30 | { | ||
31 | if (packet->info.tx.flags & HTC_FLAGS_TX_FIXUP_NETBUF) { | ||
32 | skb_pull(packet->skb, sizeof(struct htc_frame_hdr)); | ||
33 | packet->info.tx.flags &= ~HTC_FLAGS_TX_FIXUP_NETBUF; | ||
34 | } | ||
35 | } | ||
36 | |||
37 | static void do_send_completion(struct htc_endpoint *ep, | ||
38 | struct list_head *queue_to_indicate) | ||
39 | { | ||
40 | struct htc_packet *packet; | ||
41 | |||
42 | if (list_empty(queue_to_indicate)) { | ||
43 | /* nothing to indicate */ | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | if (ep->ep_cb.tx_comp_multi != NULL) { | ||
48 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
49 | "%s: calling ep %d, send complete multiple callback (%d pkts)\n", | ||
50 | __func__, ep->eid, | ||
51 | get_queue_depth(queue_to_indicate)); | ||
52 | /* | ||
53 | * a multiple send complete handler is being used, | ||
54 | * pass the queue to the handler | ||
55 | */ | ||
56 | ep->ep_cb.tx_comp_multi(ep->target, queue_to_indicate); | ||
57 | /* | ||
58 | * all packets are now owned by the callback, | ||
59 | * reset queue to be safe | ||
60 | */ | ||
61 | INIT_LIST_HEAD(queue_to_indicate); | ||
62 | } else { | ||
63 | /* using legacy EpTxComplete */ | ||
64 | do { | ||
65 | packet = list_first_entry(queue_to_indicate, | ||
66 | struct htc_packet, list); | ||
67 | |||
68 | list_del(&packet->list); | ||
69 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
70 | "%s: calling ep %d send complete callback on packet 0x%p\n", | ||
71 | __func__, ep->eid, packet); | ||
72 | ep->ep_cb.tx_complete(ep->target, packet); | ||
73 | } while (!list_empty(queue_to_indicate)); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static void send_packet_completion(struct htc_target *target, | ||
78 | struct htc_packet *packet) | ||
79 | { | ||
80 | struct htc_endpoint *ep = &target->endpoint[packet->endpoint]; | ||
81 | struct list_head container; | ||
82 | |||
83 | restore_tx_packet(packet); | ||
84 | INIT_LIST_HEAD(&container); | ||
85 | list_add_tail(&packet->list, &container); | ||
86 | |||
87 | /* do completion */ | ||
88 | do_send_completion(ep, &container); | ||
89 | } | ||
90 | |||
91 | static void get_htc_packet_credit_based(struct htc_target *target, | ||
92 | struct htc_endpoint *ep, | ||
93 | struct list_head *queue) | ||
94 | { | ||
95 | int credits_required; | ||
96 | int remainder; | ||
97 | u8 send_flags; | ||
98 | struct htc_packet *packet; | ||
99 | unsigned int transfer_len; | ||
100 | |||
101 | /* NOTE : the TX lock is held when this function is called */ | ||
102 | |||
103 | /* loop until we can grab as many packets out of the queue as we can */ | ||
104 | while (true) { | ||
105 | send_flags = 0; | ||
106 | if (list_empty(&ep->txq)) | ||
107 | break; | ||
108 | |||
109 | /* get packet at head, but don't remove it */ | ||
110 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | ||
111 | if (packet == NULL) | ||
112 | break; | ||
113 | |||
114 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
115 | "%s: got head packet:0x%p , queue depth: %d\n", | ||
116 | __func__, packet, get_queue_depth(&ep->txq)); | ||
117 | |||
118 | transfer_len = packet->act_len + HTC_HDR_LENGTH; | ||
119 | |||
120 | if (transfer_len <= target->tgt_cred_sz) { | ||
121 | credits_required = 1; | ||
122 | } else { | ||
123 | /* figure out how many credits this message requires */ | ||
124 | credits_required = transfer_len / target->tgt_cred_sz; | ||
125 | remainder = transfer_len % target->tgt_cred_sz; | ||
126 | |||
127 | if (remainder) | ||
128 | credits_required++; | ||
129 | } | ||
130 | |||
131 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: creds required:%d got:%d\n", | ||
132 | __func__, credits_required, ep->cred_dist.credits); | ||
133 | |||
134 | if (ep->eid == ENDPOINT_0) { | ||
135 | /* | ||
136 | * endpoint 0 is special, it always has a credit and | ||
137 | * does not require credit based flow control | ||
138 | */ | ||
139 | credits_required = 0; | ||
140 | |||
141 | } else { | ||
142 | |||
143 | if (ep->cred_dist.credits < credits_required) | ||
144 | break; | ||
145 | |||
146 | ep->cred_dist.credits -= credits_required; | ||
147 | ep->ep_st.cred_cosumd += credits_required; | ||
148 | |||
149 | /* check if we need credits back from the target */ | ||
150 | if (ep->cred_dist.credits < | ||
151 | ep->cred_dist.cred_per_msg) { | ||
152 | /* tell the target we need credits ASAP! */ | ||
153 | send_flags |= HTC_FLAGS_NEED_CREDIT_UPDATE; | ||
154 | ep->ep_st.cred_low_indicate += 1; | ||
155 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
156 | "%s: host needs credits\n", | ||
157 | __func__); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* now we can fully dequeue */ | ||
162 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | ||
163 | |||
164 | list_del(&packet->list); | ||
165 | /* save the number of credits this packet consumed */ | ||
166 | packet->info.tx.cred_used = credits_required; | ||
167 | /* save send flags */ | ||
168 | packet->info.tx.flags = send_flags; | ||
169 | packet->info.tx.seqno = ep->seqno; | ||
170 | ep->seqno++; | ||
171 | /* queue this packet into the caller's queue */ | ||
172 | list_add_tail(&packet->list, queue); | ||
173 | } | ||
174 | |||
175 | } | ||
176 | |||
177 | static void get_htc_packet(struct htc_target *target, | ||
178 | struct htc_endpoint *ep, | ||
179 | struct list_head *queue, int resources) | ||
180 | { | ||
181 | struct htc_packet *packet; | ||
182 | |||
183 | /* NOTE : the TX lock is held when this function is called */ | ||
184 | |||
185 | /* loop until we can grab as many packets out of the queue as we can */ | ||
186 | while (resources) { | ||
187 | if (list_empty(&ep->txq)) | ||
188 | break; | ||
189 | |||
190 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | ||
191 | list_del(&packet->list); | ||
192 | |||
193 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
194 | "%s: got packet:0x%p , new queue depth: %d\n", | ||
195 | __func__, packet, get_queue_depth(&ep->txq)); | ||
196 | packet->info.tx.seqno = ep->seqno; | ||
197 | packet->info.tx.flags = 0; | ||
198 | packet->info.tx.cred_used = 0; | ||
199 | ep->seqno++; | ||
200 | |||
201 | /* queue this packet into the caller's queue */ | ||
202 | list_add_tail(&packet->list, queue); | ||
203 | resources--; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static int htc_issue_packets(struct htc_target *target, | ||
208 | struct htc_endpoint *ep, | ||
209 | struct list_head *pkt_queue) | ||
210 | { | ||
211 | int status = 0; | ||
212 | u16 payload_len; | ||
213 | struct sk_buff *skb; | ||
214 | struct htc_frame_hdr *htc_hdr; | ||
215 | struct htc_packet *packet; | ||
216 | |||
217 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
218 | "%s: queue: 0x%p, pkts %d\n", __func__, | ||
219 | pkt_queue, get_queue_depth(pkt_queue)); | ||
220 | |||
221 | while (!list_empty(pkt_queue)) { | ||
222 | packet = list_first_entry(pkt_queue, struct htc_packet, list); | ||
223 | list_del(&packet->list); | ||
224 | |||
225 | skb = packet->skb; | ||
226 | if (!skb) { | ||
227 | WARN_ON_ONCE(1); | ||
228 | status = -EINVAL; | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | payload_len = packet->act_len; | ||
233 | |||
234 | /* setup HTC frame header */ | ||
235 | htc_hdr = (struct htc_frame_hdr *) skb_push(skb, | ||
236 | sizeof(*htc_hdr)); | ||
237 | if (!htc_hdr) { | ||
238 | WARN_ON_ONCE(1); | ||
239 | status = -EINVAL; | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | packet->info.tx.flags |= HTC_FLAGS_TX_FIXUP_NETBUF; | ||
244 | |||
245 | /* Endianess? */ | ||
246 | put_unaligned((u16) payload_len, &htc_hdr->payld_len); | ||
247 | htc_hdr->flags = packet->info.tx.flags; | ||
248 | htc_hdr->eid = (u8) packet->endpoint; | ||
249 | htc_hdr->ctrl[0] = 0; | ||
250 | htc_hdr->ctrl[1] = (u8) packet->info.tx.seqno; | ||
251 | |||
252 | spin_lock_bh(&target->tx_lock); | ||
253 | |||
254 | /* store in look up queue to match completions */ | ||
255 | list_add_tail(&packet->list, &ep->pipe.tx_lookup_queue); | ||
256 | ep->ep_st.tx_issued += 1; | ||
257 | spin_unlock_bh(&target->tx_lock); | ||
258 | |||
259 | status = ath6kl_hif_pipe_send(target->dev->ar, | ||
260 | ep->pipe.pipeid_ul, NULL, skb); | ||
261 | |||
262 | if (status != 0) { | ||
263 | if (status != -ENOMEM) { | ||
264 | /* TODO: if more than 1 endpoint maps to the | ||
265 | * same PipeID, it is possible to run out of | ||
266 | * resources in the HIF layer. | ||
267 | * Don't emit the error | ||
268 | */ | ||
269 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
270 | "%s: failed status:%d\n", | ||
271 | __func__, status); | ||
272 | } | ||
273 | spin_lock_bh(&target->tx_lock); | ||
274 | list_del(&packet->list); | ||
275 | |||
276 | /* reclaim credits */ | ||
277 | ep->cred_dist.credits += packet->info.tx.cred_used; | ||
278 | spin_unlock_bh(&target->tx_lock); | ||
279 | |||
280 | /* put it back into the callers queue */ | ||
281 | list_add(&packet->list, pkt_queue); | ||
282 | break; | ||
283 | } | ||
284 | |||
285 | } | ||
286 | |||
287 | if (status != 0) { | ||
288 | while (!list_empty(pkt_queue)) { | ||
289 | if (status != -ENOMEM) { | ||
290 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
291 | "%s: failed pkt:0x%p status:%d\n", | ||
292 | __func__, packet, status); | ||
293 | } | ||
294 | |||
295 | packet = list_first_entry(pkt_queue, | ||
296 | struct htc_packet, list); | ||
297 | list_del(&packet->list); | ||
298 | packet->status = status; | ||
299 | send_packet_completion(target, packet); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | return status; | ||
304 | } | ||
305 | |||
306 | static enum htc_send_queue_result htc_try_send(struct htc_target *target, | ||
307 | struct htc_endpoint *ep, | ||
308 | struct list_head *txq) | ||
309 | { | ||
310 | struct list_head send_queue; /* temp queue to hold packets */ | ||
311 | struct htc_packet *packet, *tmp_pkt; | ||
312 | struct ath6kl *ar = target->dev->ar; | ||
313 | enum htc_send_full_action action; | ||
314 | int tx_resources, overflow, txqueue_depth, i, good_pkts; | ||
315 | u8 pipeid; | ||
316 | |||
317 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: (queue:0x%p depth:%d)\n", | ||
318 | __func__, txq, | ||
319 | (txq == NULL) ? 0 : get_queue_depth(txq)); | ||
320 | |||
321 | /* init the local send queue */ | ||
322 | INIT_LIST_HEAD(&send_queue); | ||
323 | |||
324 | /* | ||
325 | * txq equals to NULL means | ||
326 | * caller didn't provide a queue, just wants us to | ||
327 | * check queues and send | ||
328 | */ | ||
329 | if (txq != NULL) { | ||
330 | if (list_empty(txq)) { | ||
331 | /* empty queue */ | ||
332 | return HTC_SEND_QUEUE_DROP; | ||
333 | } | ||
334 | |||
335 | spin_lock_bh(&target->tx_lock); | ||
336 | txqueue_depth = get_queue_depth(&ep->txq); | ||
337 | spin_unlock_bh(&target->tx_lock); | ||
338 | |||
339 | if (txqueue_depth >= ep->max_txq_depth) { | ||
340 | /* we've already overflowed */ | ||
341 | overflow = get_queue_depth(txq); | ||
342 | } else { | ||
343 | /* get how much we will overflow by */ | ||
344 | overflow = txqueue_depth; | ||
345 | overflow += get_queue_depth(txq); | ||
346 | /* get how much we will overflow the TX queue by */ | ||
347 | overflow -= ep->max_txq_depth; | ||
348 | } | ||
349 | |||
350 | /* if overflow is negative or zero, we are okay */ | ||
351 | if (overflow > 0) { | ||
352 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
353 | "%s: Endpoint %d, TX queue will overflow :%d, Tx Depth:%d, Max:%d\n", | ||
354 | __func__, ep->eid, overflow, txqueue_depth, | ||
355 | ep->max_txq_depth); | ||
356 | } | ||
357 | if ((overflow <= 0) || | ||
358 | (ep->ep_cb.tx_full == NULL)) { | ||
359 | /* | ||
360 | * all packets will fit or caller did not provide send | ||
361 | * full indication handler -- just move all of them | ||
362 | * to the local send_queue object | ||
363 | */ | ||
364 | list_splice_tail_init(txq, &send_queue); | ||
365 | } else { | ||
366 | good_pkts = get_queue_depth(txq) - overflow; | ||
367 | if (good_pkts < 0) { | ||
368 | WARN_ON_ONCE(1); | ||
369 | return HTC_SEND_QUEUE_DROP; | ||
370 | } | ||
371 | |||
372 | /* we have overflowed, and a callback is provided */ | ||
373 | /* dequeue all non-overflow packets to the sendqueue */ | ||
374 | for (i = 0; i < good_pkts; i++) { | ||
375 | /* pop off caller's queue */ | ||
376 | packet = list_first_entry(txq, | ||
377 | struct htc_packet, | ||
378 | list); | ||
379 | list_del(&packet->list); | ||
380 | /* insert into local queue */ | ||
381 | list_add_tail(&packet->list, &send_queue); | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * the caller's queue has all the packets that won't fit | ||
386 | * walk through the caller's queue and indicate each to | ||
387 | * the send full handler | ||
388 | */ | ||
389 | list_for_each_entry_safe(packet, tmp_pkt, | ||
390 | txq, list) { | ||
391 | |||
392 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
393 | "%s: Indicat overflowed TX pkts: %p\n", | ||
394 | __func__, packet); | ||
395 | action = ep->ep_cb.tx_full(ep->target, packet); | ||
396 | if (action == HTC_SEND_FULL_DROP) { | ||
397 | /* callback wants the packet dropped */ | ||
398 | ep->ep_st.tx_dropped += 1; | ||
399 | |||
400 | /* leave this one in the caller's queue | ||
401 | * for cleanup */ | ||
402 | } else { | ||
403 | /* callback wants to keep this packet, | ||
404 | * remove from caller's queue */ | ||
405 | list_del(&packet->list); | ||
406 | /* put it in the send queue */ | ||
407 | list_add_tail(&packet->list, | ||
408 | &send_queue); | ||
409 | } | ||
410 | |||
411 | } | ||
412 | |||
413 | if (list_empty(&send_queue)) { | ||
414 | /* no packets made it in, caller will cleanup */ | ||
415 | return HTC_SEND_QUEUE_DROP; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | |||
420 | if (!ep->pipe.tx_credit_flow_enabled) { | ||
421 | tx_resources = | ||
422 | ath6kl_hif_pipe_get_free_queue_number(ar, | ||
423 | ep->pipe.pipeid_ul); | ||
424 | } else { | ||
425 | tx_resources = 0; | ||
426 | } | ||
427 | |||
428 | spin_lock_bh(&target->tx_lock); | ||
429 | if (!list_empty(&send_queue)) { | ||
430 | /* transfer packets to tail */ | ||
431 | list_splice_tail_init(&send_queue, &ep->txq); | ||
432 | if (!list_empty(&send_queue)) { | ||
433 | WARN_ON_ONCE(1); | ||
434 | spin_unlock_bh(&target->tx_lock); | ||
435 | return HTC_SEND_QUEUE_DROP; | ||
436 | } | ||
437 | INIT_LIST_HEAD(&send_queue); | ||
438 | } | ||
439 | |||
440 | /* increment tx processing count on entry */ | ||
441 | ep->tx_proc_cnt++; | ||
442 | |||
443 | if (ep->tx_proc_cnt > 1) { | ||
444 | /* | ||
445 | * Another thread or task is draining the TX queues on this | ||
446 | * endpoint that thread will reset the tx processing count | ||
447 | * when the queue is drained. | ||
448 | */ | ||
449 | ep->tx_proc_cnt--; | ||
450 | spin_unlock_bh(&target->tx_lock); | ||
451 | return HTC_SEND_QUEUE_OK; | ||
452 | } | ||
453 | |||
454 | /***** beyond this point only 1 thread may enter ******/ | ||
455 | |||
456 | /* | ||
457 | * Now drain the endpoint TX queue for transmission as long as we have | ||
458 | * enough transmit resources. | ||
459 | */ | ||
460 | while (true) { | ||
461 | |||
462 | if (get_queue_depth(&ep->txq) == 0) | ||
463 | break; | ||
464 | |||
465 | if (ep->pipe.tx_credit_flow_enabled) { | ||
466 | /* | ||
467 | * Credit based mechanism provides flow control | ||
468 | * based on target transmit resource availability, | ||
469 | * we assume that the HIF layer will always have | ||
470 | * bus resources greater than target transmit | ||
471 | * resources. | ||
472 | */ | ||
473 | get_htc_packet_credit_based(target, ep, &send_queue); | ||
474 | } else { | ||
475 | /* | ||
476 | * Get all packets for this endpoint that we can | ||
477 | * for this pass. | ||
478 | */ | ||
479 | get_htc_packet(target, ep, &send_queue, tx_resources); | ||
480 | } | ||
481 | |||
482 | if (get_queue_depth(&send_queue) == 0) { | ||
483 | /* | ||
484 | * Didn't get packets due to out of resources or TX | ||
485 | * queue was drained. | ||
486 | */ | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | spin_unlock_bh(&target->tx_lock); | ||
491 | |||
492 | /* send what we can */ | ||
493 | htc_issue_packets(target, ep, &send_queue); | ||
494 | |||
495 | if (!ep->pipe.tx_credit_flow_enabled) { | ||
496 | pipeid = ep->pipe.pipeid_ul; | ||
497 | tx_resources = | ||
498 | ath6kl_hif_pipe_get_free_queue_number(ar, pipeid); | ||
499 | } | ||
500 | |||
501 | spin_lock_bh(&target->tx_lock); | ||
502 | |||
503 | } | ||
504 | /* done with this endpoint, we can clear the count */ | ||
505 | ep->tx_proc_cnt = 0; | ||
506 | spin_unlock_bh(&target->tx_lock); | ||
507 | |||
508 | return HTC_SEND_QUEUE_OK; | ||
509 | } | ||
510 | |||
511 | /* htc control packet manipulation */ | ||
512 | static void destroy_htc_txctrl_packet(struct htc_packet *packet) | ||
513 | { | ||
514 | struct sk_buff *skb; | ||
515 | skb = packet->skb; | ||
516 | if (skb != NULL) | ||
517 | dev_kfree_skb(skb); | ||
518 | |||
519 | kfree(packet); | ||
520 | } | ||
521 | |||
522 | static struct htc_packet *build_htc_txctrl_packet(void) | ||
523 | { | ||
524 | struct htc_packet *packet = NULL; | ||
525 | struct sk_buff *skb; | ||
526 | |||
527 | packet = kzalloc(sizeof(struct htc_packet), GFP_KERNEL); | ||
528 | if (packet == NULL) | ||
529 | return NULL; | ||
530 | |||
531 | skb = __dev_alloc_skb(HTC_CONTROL_BUFFER_SIZE, GFP_KERNEL); | ||
532 | |||
533 | if (skb == NULL) { | ||
534 | kfree(packet); | ||
535 | return NULL; | ||
536 | } | ||
537 | packet->skb = skb; | ||
538 | |||
539 | return packet; | ||
540 | } | ||
541 | |||
542 | static void htc_free_txctrl_packet(struct htc_target *target, | ||
543 | struct htc_packet *packet) | ||
544 | { | ||
545 | destroy_htc_txctrl_packet(packet); | ||
546 | } | ||
547 | |||
548 | static struct htc_packet *htc_alloc_txctrl_packet(struct htc_target *target) | ||
549 | { | ||
550 | return build_htc_txctrl_packet(); | ||
551 | } | ||
552 | |||
553 | static void htc_txctrl_complete(struct htc_target *target, | ||
554 | struct htc_packet *packet) | ||
555 | { | ||
556 | htc_free_txctrl_packet(target, packet); | ||
557 | } | ||
558 | |||
559 | #define MAX_MESSAGE_SIZE 1536 | ||
560 | |||
561 | static int htc_setup_target_buffer_assignments(struct htc_target *target) | ||
562 | { | ||
563 | int status, credits, credit_per_maxmsg, i; | ||
564 | struct htc_pipe_txcredit_alloc *entry; | ||
565 | unsigned int hif_usbaudioclass = 0; | ||
566 | |||
567 | credit_per_maxmsg = MAX_MESSAGE_SIZE / target->tgt_cred_sz; | ||
568 | if (MAX_MESSAGE_SIZE % target->tgt_cred_sz) | ||
569 | credit_per_maxmsg++; | ||
570 | |||
571 | /* TODO, this should be configured by the caller! */ | ||
572 | |||
573 | credits = target->tgt_creds; | ||
574 | entry = &target->pipe.txcredit_alloc[0]; | ||
575 | |||
576 | status = -ENOMEM; | ||
577 | |||
578 | /* FIXME: hif_usbaudioclass is always zero */ | ||
579 | if (hif_usbaudioclass) { | ||
580 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
581 | "%s: For USB Audio Class- Total:%d\n", | ||
582 | __func__, credits); | ||
583 | entry++; | ||
584 | entry++; | ||
585 | /* Setup VO Service To have Max Credits */ | ||
586 | entry->service_id = WMI_DATA_VO_SVC; | ||
587 | entry->credit_alloc = (credits - 6); | ||
588 | if (entry->credit_alloc == 0) | ||
589 | entry->credit_alloc++; | ||
590 | |||
591 | credits -= (int) entry->credit_alloc; | ||
592 | if (credits <= 0) | ||
593 | return status; | ||
594 | |||
595 | entry++; | ||
596 | entry->service_id = WMI_CONTROL_SVC; | ||
597 | entry->credit_alloc = credit_per_maxmsg; | ||
598 | credits -= (int) entry->credit_alloc; | ||
599 | if (credits <= 0) | ||
600 | return status; | ||
601 | |||
602 | /* leftovers go to best effort */ | ||
603 | entry++; | ||
604 | entry++; | ||
605 | entry->service_id = WMI_DATA_BE_SVC; | ||
606 | entry->credit_alloc = (u8) credits; | ||
607 | status = 0; | ||
608 | } else { | ||
609 | entry++; | ||
610 | entry->service_id = WMI_DATA_VI_SVC; | ||
611 | entry->credit_alloc = credits / 4; | ||
612 | if (entry->credit_alloc == 0) | ||
613 | entry->credit_alloc++; | ||
614 | |||
615 | credits -= (int) entry->credit_alloc; | ||
616 | if (credits <= 0) | ||
617 | return status; | ||
618 | |||
619 | entry++; | ||
620 | entry->service_id = WMI_DATA_VO_SVC; | ||
621 | entry->credit_alloc = credits / 4; | ||
622 | if (entry->credit_alloc == 0) | ||
623 | entry->credit_alloc++; | ||
624 | |||
625 | credits -= (int) entry->credit_alloc; | ||
626 | if (credits <= 0) | ||
627 | return status; | ||
628 | |||
629 | entry++; | ||
630 | entry->service_id = WMI_CONTROL_SVC; | ||
631 | entry->credit_alloc = credit_per_maxmsg; | ||
632 | credits -= (int) entry->credit_alloc; | ||
633 | if (credits <= 0) | ||
634 | return status; | ||
635 | |||
636 | entry++; | ||
637 | entry->service_id = WMI_DATA_BK_SVC; | ||
638 | entry->credit_alloc = credit_per_maxmsg; | ||
639 | credits -= (int) entry->credit_alloc; | ||
640 | if (credits <= 0) | ||
641 | return status; | ||
642 | |||
643 | /* leftovers go to best effort */ | ||
644 | entry++; | ||
645 | entry->service_id = WMI_DATA_BE_SVC; | ||
646 | entry->credit_alloc = (u8) credits; | ||
647 | status = 0; | ||
648 | } | ||
649 | |||
650 | if (status == 0) { | ||
651 | for (i = 0; i < ENDPOINT_MAX; i++) { | ||
652 | if (target->pipe.txcredit_alloc[i].service_id != 0) { | ||
653 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
654 | "HTC Service Index : %d TX : 0x%2.2X : alloc:%d\n", | ||
655 | i, | ||
656 | target->pipe.txcredit_alloc[i]. | ||
657 | service_id, | ||
658 | target->pipe.txcredit_alloc[i]. | ||
659 | credit_alloc); | ||
660 | } | ||
661 | } | ||
662 | } | ||
663 | return status; | ||
664 | } | ||
665 | |||
666 | /* process credit reports and call distribution function */ | ||
667 | static void htc_process_credit_report(struct htc_target *target, | ||
668 | struct htc_credit_report *rpt, | ||
669 | int num_entries, | ||
670 | enum htc_endpoint_id from_ep) | ||
671 | { | ||
672 | int total_credits = 0, i; | ||
673 | struct htc_endpoint *ep; | ||
674 | |||
675 | /* lock out TX while we update credits */ | ||
676 | spin_lock_bh(&target->tx_lock); | ||
677 | |||
678 | for (i = 0; i < num_entries; i++, rpt++) { | ||
679 | if (rpt->eid >= ENDPOINT_MAX) { | ||
680 | WARN_ON_ONCE(1); | ||
681 | spin_unlock_bh(&target->tx_lock); | ||
682 | return; | ||
683 | } | ||
684 | |||
685 | ep = &target->endpoint[rpt->eid]; | ||
686 | ep->cred_dist.credits += rpt->credits; | ||
687 | |||
688 | if (ep->cred_dist.credits && get_queue_depth(&ep->txq)) { | ||
689 | spin_unlock_bh(&target->tx_lock); | ||
690 | htc_try_send(target, ep, NULL); | ||
691 | spin_lock_bh(&target->tx_lock); | ||
692 | } | ||
693 | |||
694 | total_credits += rpt->credits; | ||
695 | } | ||
696 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
697 | "Report indicated %d credits to distribute\n", | ||
698 | total_credits); | ||
699 | |||
700 | spin_unlock_bh(&target->tx_lock); | ||
701 | } | ||
702 | |||
703 | /* flush endpoint TX queue */ | ||
704 | static void htc_flush_tx_endpoint(struct htc_target *target, | ||
705 | struct htc_endpoint *ep, u16 tag) | ||
706 | { | ||
707 | struct htc_packet *packet; | ||
708 | |||
709 | spin_lock_bh(&target->tx_lock); | ||
710 | while (get_queue_depth(&ep->txq)) { | ||
711 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | ||
712 | list_del(&packet->list); | ||
713 | packet->status = 0; | ||
714 | send_packet_completion(target, packet); | ||
715 | } | ||
716 | spin_unlock_bh(&target->tx_lock); | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * In the adapted HIF layer, struct sk_buff * are passed between HIF and HTC, | ||
721 | * since upper layers expects struct htc_packet containers we use the completed | ||
722 | * skb and lookup it's corresponding HTC packet buffer from a lookup list. | ||
723 | * This is extra overhead that can be fixed by re-aligning HIF interfaces with | ||
724 | * HTC. | ||
725 | */ | ||
726 | static struct htc_packet *htc_lookup_tx_packet(struct htc_target *target, | ||
727 | struct htc_endpoint *ep, | ||
728 | struct sk_buff *skb) | ||
729 | { | ||
730 | struct htc_packet *packet, *tmp_pkt, *found_packet = NULL; | ||
731 | |||
732 | spin_lock_bh(&target->tx_lock); | ||
733 | |||
734 | /* | ||
735 | * interate from the front of tx lookup queue | ||
736 | * this lookup should be fast since lower layers completes in-order and | ||
737 | * so the completed packet should be at the head of the list generally | ||
738 | */ | ||
739 | list_for_each_entry_safe(packet, tmp_pkt, &ep->pipe.tx_lookup_queue, | ||
740 | list) { | ||
741 | /* check for removal */ | ||
742 | if (skb == packet->skb) { | ||
743 | /* found it */ | ||
744 | list_del(&packet->list); | ||
745 | found_packet = packet; | ||
746 | break; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | spin_unlock_bh(&target->tx_lock); | ||
751 | |||
752 | return found_packet; | ||
753 | } | ||
754 | |||
755 | static int ath6kl_htc_pipe_tx_complete(struct ath6kl *ar, struct sk_buff *skb) | ||
756 | { | ||
757 | struct htc_target *target = ar->htc_target; | ||
758 | struct htc_frame_hdr *htc_hdr; | ||
759 | struct htc_endpoint *ep; | ||
760 | struct htc_packet *packet; | ||
761 | u8 ep_id, *netdata; | ||
762 | u32 netlen; | ||
763 | |||
764 | netdata = skb->data; | ||
765 | netlen = skb->len; | ||
766 | |||
767 | htc_hdr = (struct htc_frame_hdr *) netdata; | ||
768 | |||
769 | ep_id = htc_hdr->eid; | ||
770 | ep = &target->endpoint[ep_id]; | ||
771 | |||
772 | packet = htc_lookup_tx_packet(target, ep, skb); | ||
773 | if (packet == NULL) { | ||
774 | /* may have already been flushed and freed */ | ||
775 | ath6kl_err("HTC TX lookup failed!\n"); | ||
776 | } else { | ||
777 | /* will be giving this buffer back to upper layers */ | ||
778 | packet->status = 0; | ||
779 | send_packet_completion(target, packet); | ||
780 | } | ||
781 | skb = NULL; | ||
782 | |||
783 | if (!ep->pipe.tx_credit_flow_enabled) { | ||
784 | /* | ||
785 | * note: when using TX credit flow, the re-checking of queues | ||
786 | * happens when credits flow back from the target. in the | ||
787 | * non-TX credit case, we recheck after the packet completes | ||
788 | */ | ||
789 | htc_try_send(target, ep, NULL); | ||
790 | } | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | static int htc_send_packets_multiple(struct htc_target *target, | ||
796 | struct list_head *pkt_queue) | ||
797 | { | ||
798 | struct htc_endpoint *ep; | ||
799 | struct htc_packet *packet, *tmp_pkt; | ||
800 | |||
801 | if (list_empty(pkt_queue)) | ||
802 | return -EINVAL; | ||
803 | |||
804 | /* get first packet to find out which ep the packets will go into */ | ||
805 | packet = list_first_entry(pkt_queue, struct htc_packet, list); | ||
806 | if (packet == NULL) | ||
807 | return -EINVAL; | ||
808 | |||
809 | if (packet->endpoint >= ENDPOINT_MAX) { | ||
810 | WARN_ON_ONCE(1); | ||
811 | return -EINVAL; | ||
812 | } | ||
813 | ep = &target->endpoint[packet->endpoint]; | ||
814 | |||
815 | htc_try_send(target, ep, pkt_queue); | ||
816 | |||
817 | /* do completion on any packets that couldn't get in */ | ||
818 | if (!list_empty(pkt_queue)) { | ||
819 | list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { | ||
820 | packet->status = -ENOMEM; | ||
821 | } | ||
822 | |||
823 | do_send_completion(ep, pkt_queue); | ||
824 | } | ||
825 | |||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | /* htc pipe rx path */ | ||
830 | static struct htc_packet *alloc_htc_packet_container(struct htc_target *target) | ||
831 | { | ||
832 | struct htc_packet *packet; | ||
833 | spin_lock_bh(&target->rx_lock); | ||
834 | |||
835 | if (target->pipe.htc_packet_pool == NULL) { | ||
836 | spin_unlock_bh(&target->rx_lock); | ||
837 | return NULL; | ||
838 | } | ||
839 | |||
840 | packet = target->pipe.htc_packet_pool; | ||
841 | target->pipe.htc_packet_pool = (struct htc_packet *) packet->list.next; | ||
842 | |||
843 | spin_unlock_bh(&target->rx_lock); | ||
844 | |||
845 | packet->list.next = NULL; | ||
846 | return packet; | ||
847 | } | ||
848 | |||
849 | static void free_htc_packet_container(struct htc_target *target, | ||
850 | struct htc_packet *packet) | ||
851 | { | ||
852 | struct list_head *lh; | ||
853 | |||
854 | spin_lock_bh(&target->rx_lock); | ||
855 | |||
856 | if (target->pipe.htc_packet_pool == NULL) { | ||
857 | target->pipe.htc_packet_pool = packet; | ||
858 | packet->list.next = NULL; | ||
859 | } else { | ||
860 | lh = (struct list_head *) target->pipe.htc_packet_pool; | ||
861 | packet->list.next = lh; | ||
862 | target->pipe.htc_packet_pool = packet; | ||
863 | } | ||
864 | |||
865 | spin_unlock_bh(&target->rx_lock); | ||
866 | } | ||
867 | |||
868 | static int htc_process_trailer(struct htc_target *target, u8 *buffer, | ||
869 | int len, enum htc_endpoint_id from_ep) | ||
870 | { | ||
871 | struct htc_credit_report *report; | ||
872 | struct htc_record_hdr *record; | ||
873 | u8 *record_buf, *orig_buf; | ||
874 | int orig_len, status; | ||
875 | |||
876 | orig_buf = buffer; | ||
877 | orig_len = len; | ||
878 | status = 0; | ||
879 | |||
880 | while (len > 0) { | ||
881 | if (len < sizeof(struct htc_record_hdr)) { | ||
882 | status = -EINVAL; | ||
883 | break; | ||
884 | } | ||
885 | |||
886 | /* these are byte aligned structs */ | ||
887 | record = (struct htc_record_hdr *) buffer; | ||
888 | len -= sizeof(struct htc_record_hdr); | ||
889 | buffer += sizeof(struct htc_record_hdr); | ||
890 | |||
891 | if (record->len > len) { | ||
892 | /* no room left in buffer for record */ | ||
893 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
894 | "invalid length: %d (id:%d) buffer has: %d bytes left\n", | ||
895 | record->len, record->rec_id, len); | ||
896 | status = -EINVAL; | ||
897 | break; | ||
898 | } | ||
899 | |||
900 | /* start of record follows the header */ | ||
901 | record_buf = buffer; | ||
902 | |||
903 | switch (record->rec_id) { | ||
904 | case HTC_RECORD_CREDITS: | ||
905 | if (record->len < sizeof(struct htc_credit_report)) { | ||
906 | WARN_ON_ONCE(1); | ||
907 | return -EINVAL; | ||
908 | } | ||
909 | |||
910 | report = (struct htc_credit_report *) record_buf; | ||
911 | htc_process_credit_report(target, report, | ||
912 | record->len / sizeof(*report), | ||
913 | from_ep); | ||
914 | break; | ||
915 | default: | ||
916 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
917 | "unhandled record: id:%d length:%d\n", | ||
918 | record->rec_id, record->len); | ||
919 | break; | ||
920 | } | ||
921 | |||
922 | if (status != 0) | ||
923 | break; | ||
924 | |||
925 | /* advance buffer past this record for next time around */ | ||
926 | buffer += record->len; | ||
927 | len -= record->len; | ||
928 | } | ||
929 | |||
930 | return status; | ||
931 | } | ||
932 | |||
933 | static void do_recv_completion(struct htc_endpoint *ep, | ||
934 | struct list_head *queue_to_indicate) | ||
935 | { | ||
936 | struct htc_packet *packet; | ||
937 | |||
938 | if (list_empty(queue_to_indicate)) { | ||
939 | /* nothing to indicate */ | ||
940 | return; | ||
941 | } | ||
942 | |||
943 | /* using legacy EpRecv */ | ||
944 | while (!list_empty(queue_to_indicate)) { | ||
945 | packet = list_first_entry(queue_to_indicate, | ||
946 | struct htc_packet, list); | ||
947 | list_del(&packet->list); | ||
948 | ep->ep_cb.rx(ep->target, packet); | ||
949 | } | ||
950 | |||
951 | return; | ||
952 | } | ||
953 | |||
954 | static void recv_packet_completion(struct htc_target *target, | ||
955 | struct htc_endpoint *ep, | ||
956 | struct htc_packet *packet) | ||
957 | { | ||
958 | struct list_head container; | ||
959 | INIT_LIST_HEAD(&container); | ||
960 | list_add_tail(&packet->list, &container); | ||
961 | |||
962 | /* do completion */ | ||
963 | do_recv_completion(ep, &container); | ||
964 | } | ||
965 | |||
966 | static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, | ||
967 | u8 pipeid) | ||
968 | { | ||
969 | struct htc_target *target = ar->htc_target; | ||
970 | u8 *netdata, *trailer, hdr_info; | ||
971 | struct htc_frame_hdr *htc_hdr; | ||
972 | u32 netlen, trailerlen = 0; | ||
973 | struct htc_packet *packet; | ||
974 | struct htc_endpoint *ep; | ||
975 | u16 payload_len; | ||
976 | int status = 0; | ||
977 | |||
978 | netdata = skb->data; | ||
979 | netlen = skb->len; | ||
980 | |||
981 | htc_hdr = (struct htc_frame_hdr *) netdata; | ||
982 | |||
983 | ep = &target->endpoint[htc_hdr->eid]; | ||
984 | |||
985 | if (htc_hdr->eid >= ENDPOINT_MAX) { | ||
986 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
987 | "HTC Rx: invalid EndpointID=%d\n", | ||
988 | htc_hdr->eid); | ||
989 | status = -EINVAL; | ||
990 | goto free_skb; | ||
991 | } | ||
992 | |||
993 | payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); | ||
994 | |||
995 | if (netlen < (payload_len + HTC_HDR_LENGTH)) { | ||
996 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
997 | "HTC Rx: insufficient length, got:%d expected =%u\n", | ||
998 | netlen, payload_len + HTC_HDR_LENGTH); | ||
999 | status = -EINVAL; | ||
1000 | goto free_skb; | ||
1001 | } | ||
1002 | |||
1003 | /* get flags to check for trailer */ | ||
1004 | hdr_info = htc_hdr->flags; | ||
1005 | if (hdr_info & HTC_FLG_RX_TRAILER) { | ||
1006 | /* extract the trailer length */ | ||
1007 | hdr_info = htc_hdr->ctrl[0]; | ||
1008 | if ((hdr_info < sizeof(struct htc_record_hdr)) || | ||
1009 | (hdr_info > payload_len)) { | ||
1010 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1011 | "invalid header: payloadlen should be %d, CB[0]: %d\n", | ||
1012 | payload_len, hdr_info); | ||
1013 | status = -EINVAL; | ||
1014 | goto free_skb; | ||
1015 | } | ||
1016 | |||
1017 | trailerlen = hdr_info; | ||
1018 | /* process trailer after hdr/apps payload */ | ||
1019 | trailer = (u8 *) htc_hdr + HTC_HDR_LENGTH + | ||
1020 | payload_len - hdr_info; | ||
1021 | status = htc_process_trailer(target, trailer, hdr_info, | ||
1022 | htc_hdr->eid); | ||
1023 | if (status != 0) | ||
1024 | goto free_skb; | ||
1025 | } | ||
1026 | |||
1027 | if (((int) payload_len - (int) trailerlen) <= 0) { | ||
1028 | /* zero length packet with trailer, just drop these */ | ||
1029 | goto free_skb; | ||
1030 | } | ||
1031 | |||
1032 | if (htc_hdr->eid == ENDPOINT_0) { | ||
1033 | /* handle HTC control message */ | ||
1034 | if (target->htc_flags & HTC_OP_STATE_SETUP_COMPLETE) { | ||
1035 | /* | ||
1036 | * fatal: target should not send unsolicited | ||
1037 | * messageson the endpoint 0 | ||
1038 | */ | ||
1039 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1040 | "HTC ignores Rx Ctrl after setup complete\n"); | ||
1041 | status = -EINVAL; | ||
1042 | goto free_skb; | ||
1043 | } | ||
1044 | |||
1045 | /* remove HTC header */ | ||
1046 | skb_pull(skb, HTC_HDR_LENGTH); | ||
1047 | |||
1048 | netdata = skb->data; | ||
1049 | netlen = skb->len; | ||
1050 | |||
1051 | spin_lock_bh(&target->rx_lock); | ||
1052 | |||
1053 | target->pipe.ctrl_response_valid = true; | ||
1054 | target->pipe.ctrl_response_len = min_t(int, netlen, | ||
1055 | HTC_MAX_CTRL_MSG_LEN); | ||
1056 | memcpy(target->pipe.ctrl_response_buf, netdata, | ||
1057 | target->pipe.ctrl_response_len); | ||
1058 | |||
1059 | spin_unlock_bh(&target->rx_lock); | ||
1060 | |||
1061 | dev_kfree_skb(skb); | ||
1062 | skb = NULL; | ||
1063 | goto free_skb; | ||
1064 | } | ||
1065 | |||
1066 | /* | ||
1067 | * TODO: the message based HIF architecture allocates net bufs | ||
1068 | * for recv packets since it bridges that HIF to upper layers, | ||
1069 | * which expects HTC packets, we form the packets here | ||
1070 | */ | ||
1071 | packet = alloc_htc_packet_container(target); | ||
1072 | if (packet == NULL) { | ||
1073 | status = -ENOMEM; | ||
1074 | goto free_skb; | ||
1075 | } | ||
1076 | |||
1077 | packet->status = 0; | ||
1078 | packet->endpoint = htc_hdr->eid; | ||
1079 | packet->pkt_cntxt = skb; | ||
1080 | |||
1081 | /* TODO: for backwards compatibility */ | ||
1082 | packet->buf = skb_push(skb, 0) + HTC_HDR_LENGTH; | ||
1083 | packet->act_len = netlen - HTC_HDR_LENGTH - trailerlen; | ||
1084 | |||
1085 | /* | ||
1086 | * TODO: this is a hack because the driver layer will set the | ||
1087 | * actual len of the skb again which will just double the len | ||
1088 | */ | ||
1089 | skb_trim(skb, 0); | ||
1090 | |||
1091 | recv_packet_completion(target, ep, packet); | ||
1092 | |||
1093 | /* recover the packet container */ | ||
1094 | free_htc_packet_container(target, packet); | ||
1095 | skb = NULL; | ||
1096 | |||
1097 | free_skb: | ||
1098 | if (skb != NULL) | ||
1099 | dev_kfree_skb(skb); | ||
1100 | |||
1101 | return status; | ||
1102 | |||
1103 | } | ||
1104 | |||
1105 | static void htc_flush_rx_queue(struct htc_target *target, | ||
1106 | struct htc_endpoint *ep) | ||
1107 | { | ||
1108 | struct list_head container; | ||
1109 | struct htc_packet *packet; | ||
1110 | |||
1111 | spin_lock_bh(&target->rx_lock); | ||
1112 | |||
1113 | while (1) { | ||
1114 | if (list_empty(&ep->rx_bufq)) | ||
1115 | break; | ||
1116 | |||
1117 | packet = list_first_entry(&ep->rx_bufq, | ||
1118 | struct htc_packet, list); | ||
1119 | list_del(&packet->list); | ||
1120 | |||
1121 | spin_unlock_bh(&target->rx_lock); | ||
1122 | packet->status = -ECANCELED; | ||
1123 | packet->act_len = 0; | ||
1124 | |||
1125 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1126 | "Flushing RX packet:0x%p, length:%d, ep:%d\n", | ||
1127 | packet, packet->buf_len, | ||
1128 | packet->endpoint); | ||
1129 | |||
1130 | INIT_LIST_HEAD(&container); | ||
1131 | list_add_tail(&packet->list, &container); | ||
1132 | |||
1133 | /* give the packet back */ | ||
1134 | do_recv_completion(ep, &container); | ||
1135 | spin_lock_bh(&target->rx_lock); | ||
1136 | } | ||
1137 | |||
1138 | spin_unlock_bh(&target->rx_lock); | ||
1139 | } | ||
1140 | |||
1141 | /* polling routine to wait for a control packet to be received */ | ||
1142 | static int htc_wait_recv_ctrl_message(struct htc_target *target) | ||
1143 | { | ||
1144 | int count = HTC_TARGET_RESPONSE_POLL_COUNT; | ||
1145 | |||
1146 | while (count > 0) { | ||
1147 | spin_lock_bh(&target->rx_lock); | ||
1148 | |||
1149 | if (target->pipe.ctrl_response_valid) { | ||
1150 | target->pipe.ctrl_response_valid = false; | ||
1151 | spin_unlock_bh(&target->rx_lock); | ||
1152 | break; | ||
1153 | } | ||
1154 | |||
1155 | spin_unlock_bh(&target->rx_lock); | ||
1156 | |||
1157 | count--; | ||
1158 | |||
1159 | msleep_interruptible(HTC_TARGET_RESPONSE_POLL_WAIT); | ||
1160 | } | ||
1161 | |||
1162 | if (count <= 0) { | ||
1163 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__); | ||
1164 | return -ECOMM; | ||
1165 | } | ||
1166 | |||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | static void htc_rxctrl_complete(struct htc_target *context, | ||
1171 | struct htc_packet *packet) | ||
1172 | { | ||
1173 | /* TODO, can't really receive HTC control messages yet.... */ | ||
1174 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__); | ||
1175 | } | ||
1176 | |||
1177 | /* htc pipe initialization */ | ||
1178 | static void reset_endpoint_states(struct htc_target *target) | ||
1179 | { | ||
1180 | struct htc_endpoint *ep; | ||
1181 | int i; | ||
1182 | |||
1183 | for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { | ||
1184 | ep = &target->endpoint[i]; | ||
1185 | ep->svc_id = 0; | ||
1186 | ep->len_max = 0; | ||
1187 | ep->max_txq_depth = 0; | ||
1188 | ep->eid = i; | ||
1189 | INIT_LIST_HEAD(&ep->txq); | ||
1190 | INIT_LIST_HEAD(&ep->pipe.tx_lookup_queue); | ||
1191 | INIT_LIST_HEAD(&ep->rx_bufq); | ||
1192 | ep->target = target; | ||
1193 | ep->pipe.tx_credit_flow_enabled = (bool) 1; /* FIXME */ | ||
1194 | } | ||
1195 | } | ||
1196 | |||
1197 | /* start HTC, this is called after all services are connected */ | ||
1198 | static int htc_config_target_hif_pipe(struct htc_target *target) | ||
1199 | { | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | /* htc service functions */ | ||
1204 | static u8 htc_get_credit_alloc(struct htc_target *target, u16 service_id) | ||
1205 | { | ||
1206 | u8 allocation = 0; | ||
1207 | int i; | ||
1208 | |||
1209 | for (i = 0; i < ENDPOINT_MAX; i++) { | ||
1210 | if (target->pipe.txcredit_alloc[i].service_id == service_id) | ||
1211 | allocation = | ||
1212 | target->pipe.txcredit_alloc[i].credit_alloc; | ||
1213 | } | ||
1214 | |||
1215 | if (allocation == 0) { | ||
1216 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1217 | "HTC Service TX : 0x%2.2X : allocation is zero!\n", | ||
1218 | service_id); | ||
1219 | } | ||
1220 | |||
1221 | return allocation; | ||
1222 | } | ||
1223 | |||
1224 | static int ath6kl_htc_pipe_conn_service(struct htc_target *target, | ||
1225 | struct htc_service_connect_req *conn_req, | ||
1226 | struct htc_service_connect_resp *conn_resp) | ||
1227 | { | ||
1228 | struct ath6kl *ar = target->dev->ar; | ||
1229 | struct htc_packet *packet = NULL; | ||
1230 | struct htc_conn_service_resp *resp_msg; | ||
1231 | struct htc_conn_service_msg *conn_msg; | ||
1232 | enum htc_endpoint_id assigned_epid = ENDPOINT_MAX; | ||
1233 | bool disable_credit_flowctrl = false; | ||
1234 | unsigned int max_msg_size = 0; | ||
1235 | struct htc_endpoint *ep; | ||
1236 | int length, status = 0; | ||
1237 | struct sk_buff *skb; | ||
1238 | u8 tx_alloc; | ||
1239 | u16 flags; | ||
1240 | |||
1241 | if (conn_req->svc_id == 0) { | ||
1242 | WARN_ON_ONCE(1); | ||
1243 | status = -EINVAL; | ||
1244 | goto free_packet; | ||
1245 | } | ||
1246 | |||
1247 | if (conn_req->svc_id == HTC_CTRL_RSVD_SVC) { | ||
1248 | /* special case for pseudo control service */ | ||
1249 | assigned_epid = ENDPOINT_0; | ||
1250 | max_msg_size = HTC_MAX_CTRL_MSG_LEN; | ||
1251 | tx_alloc = 0; | ||
1252 | |||
1253 | } else { | ||
1254 | |||
1255 | tx_alloc = htc_get_credit_alloc(target, conn_req->svc_id); | ||
1256 | if (tx_alloc == 0) { | ||
1257 | status = -ENOMEM; | ||
1258 | goto free_packet; | ||
1259 | } | ||
1260 | |||
1261 | /* allocate a packet to send to the target */ | ||
1262 | packet = htc_alloc_txctrl_packet(target); | ||
1263 | |||
1264 | if (packet == NULL) { | ||
1265 | WARN_ON_ONCE(1); | ||
1266 | status = -ENOMEM; | ||
1267 | goto free_packet; | ||
1268 | } | ||
1269 | |||
1270 | skb = packet->skb; | ||
1271 | length = sizeof(struct htc_conn_service_msg); | ||
1272 | |||
1273 | /* assemble connect service message */ | ||
1274 | conn_msg = (struct htc_conn_service_msg *) skb_put(skb, | ||
1275 | length); | ||
1276 | if (conn_msg == NULL) { | ||
1277 | WARN_ON_ONCE(1); | ||
1278 | status = -EINVAL; | ||
1279 | goto free_packet; | ||
1280 | } | ||
1281 | |||
1282 | memset(conn_msg, 0, | ||
1283 | sizeof(struct htc_conn_service_msg)); | ||
1284 | conn_msg->msg_id = cpu_to_le16(HTC_MSG_CONN_SVC_ID); | ||
1285 | conn_msg->svc_id = cpu_to_le16(conn_req->svc_id); | ||
1286 | conn_msg->conn_flags = cpu_to_le16(conn_req->conn_flags & | ||
1287 | ~HTC_CONN_FLGS_SET_RECV_ALLOC_MASK); | ||
1288 | |||
1289 | /* tell target desired recv alloc for this ep */ | ||
1290 | flags = tx_alloc << HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT; | ||
1291 | conn_msg->conn_flags |= cpu_to_le16(flags); | ||
1292 | |||
1293 | if (conn_req->conn_flags & | ||
1294 | HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL) { | ||
1295 | disable_credit_flowctrl = true; | ||
1296 | } | ||
1297 | |||
1298 | set_htc_pkt_info(packet, NULL, (u8 *) conn_msg, | ||
1299 | length, | ||
1300 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); | ||
1301 | |||
1302 | status = ath6kl_htc_pipe_tx(target, packet); | ||
1303 | |||
1304 | /* we don't own it anymore */ | ||
1305 | packet = NULL; | ||
1306 | if (status != 0) | ||
1307 | goto free_packet; | ||
1308 | |||
1309 | /* wait for response */ | ||
1310 | status = htc_wait_recv_ctrl_message(target); | ||
1311 | if (status != 0) | ||
1312 | goto free_packet; | ||
1313 | |||
1314 | /* we controlled the buffer creation so it has to be | ||
1315 | * properly aligned | ||
1316 | */ | ||
1317 | resp_msg = (struct htc_conn_service_resp *) | ||
1318 | target->pipe.ctrl_response_buf; | ||
1319 | |||
1320 | if (resp_msg->msg_id != cpu_to_le16(HTC_MSG_CONN_SVC_RESP_ID) || | ||
1321 | (target->pipe.ctrl_response_len < sizeof(*resp_msg))) { | ||
1322 | /* this message is not valid */ | ||
1323 | WARN_ON_ONCE(1); | ||
1324 | status = -EINVAL; | ||
1325 | goto free_packet; | ||
1326 | } | ||
1327 | |||
1328 | ath6kl_dbg(ATH6KL_DBG_TRC, | ||
1329 | "%s: service 0x%X conn resp: status: %d ep: %d\n", | ||
1330 | __func__, resp_msg->svc_id, resp_msg->status, | ||
1331 | resp_msg->eid); | ||
1332 | |||
1333 | conn_resp->resp_code = resp_msg->status; | ||
1334 | /* check response status */ | ||
1335 | if (resp_msg->status != HTC_SERVICE_SUCCESS) { | ||
1336 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1337 | "Target failed service 0x%X connect request (status:%d)\n", | ||
1338 | resp_msg->svc_id, resp_msg->status); | ||
1339 | status = -EINVAL; | ||
1340 | goto free_packet; | ||
1341 | } | ||
1342 | |||
1343 | assigned_epid = (enum htc_endpoint_id) resp_msg->eid; | ||
1344 | max_msg_size = le16_to_cpu(resp_msg->max_msg_sz); | ||
1345 | } | ||
1346 | |||
1347 | /* the rest are parameter checks so set the error status */ | ||
1348 | status = -EINVAL; | ||
1349 | |||
1350 | if (assigned_epid >= ENDPOINT_MAX) { | ||
1351 | WARN_ON_ONCE(1); | ||
1352 | goto free_packet; | ||
1353 | } | ||
1354 | |||
1355 | if (max_msg_size == 0) { | ||
1356 | WARN_ON_ONCE(1); | ||
1357 | goto free_packet; | ||
1358 | } | ||
1359 | |||
1360 | ep = &target->endpoint[assigned_epid]; | ||
1361 | ep->eid = assigned_epid; | ||
1362 | if (ep->svc_id != 0) { | ||
1363 | /* endpoint already in use! */ | ||
1364 | WARN_ON_ONCE(1); | ||
1365 | goto free_packet; | ||
1366 | } | ||
1367 | |||
1368 | /* return assigned endpoint to caller */ | ||
1369 | conn_resp->endpoint = assigned_epid; | ||
1370 | conn_resp->len_max = max_msg_size; | ||
1371 | |||
1372 | /* setup the endpoint */ | ||
1373 | ep->svc_id = conn_req->svc_id; /* this marks ep in use */ | ||
1374 | ep->max_txq_depth = conn_req->max_txq_depth; | ||
1375 | ep->len_max = max_msg_size; | ||
1376 | ep->cred_dist.credits = tx_alloc; | ||
1377 | ep->cred_dist.cred_sz = target->tgt_cred_sz; | ||
1378 | ep->cred_dist.cred_per_msg = max_msg_size / target->tgt_cred_sz; | ||
1379 | if (max_msg_size % target->tgt_cred_sz) | ||
1380 | ep->cred_dist.cred_per_msg++; | ||
1381 | |||
1382 | /* copy all the callbacks */ | ||
1383 | ep->ep_cb = conn_req->ep_cb; | ||
1384 | |||
1385 | status = ath6kl_hif_pipe_map_service(ar, ep->svc_id, | ||
1386 | &ep->pipe.pipeid_ul, | ||
1387 | &ep->pipe.pipeid_dl); | ||
1388 | if (status != 0) | ||
1389 | goto free_packet; | ||
1390 | |||
1391 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1392 | "SVC Ready: 0x%4.4X: ULpipe:%d DLpipe:%d id:%d\n", | ||
1393 | ep->svc_id, ep->pipe.pipeid_ul, | ||
1394 | ep->pipe.pipeid_dl, ep->eid); | ||
1395 | |||
1396 | if (disable_credit_flowctrl && ep->pipe.tx_credit_flow_enabled) { | ||
1397 | ep->pipe.tx_credit_flow_enabled = false; | ||
1398 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1399 | "SVC: 0x%4.4X ep:%d TX flow control off\n", | ||
1400 | ep->svc_id, assigned_epid); | ||
1401 | } | ||
1402 | |||
1403 | free_packet: | ||
1404 | if (packet != NULL) | ||
1405 | htc_free_txctrl_packet(target, packet); | ||
1406 | return status; | ||
1407 | } | ||
1408 | |||
1409 | /* htc export functions */ | ||
1410 | static void *ath6kl_htc_pipe_create(struct ath6kl *ar) | ||
1411 | { | ||
1412 | int status = 0; | ||
1413 | struct htc_endpoint *ep = NULL; | ||
1414 | struct htc_target *target = NULL; | ||
1415 | struct htc_packet *packet; | ||
1416 | int i; | ||
1417 | |||
1418 | target = kzalloc(sizeof(struct htc_target), GFP_KERNEL); | ||
1419 | if (target == NULL) { | ||
1420 | ath6kl_err("htc create unable to allocate memory\n"); | ||
1421 | status = -ENOMEM; | ||
1422 | goto fail_htc_create; | ||
1423 | } | ||
1424 | |||
1425 | spin_lock_init(&target->htc_lock); | ||
1426 | spin_lock_init(&target->rx_lock); | ||
1427 | spin_lock_init(&target->tx_lock); | ||
1428 | |||
1429 | reset_endpoint_states(target); | ||
1430 | |||
1431 | for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) { | ||
1432 | packet = kzalloc(sizeof(struct htc_packet), GFP_KERNEL); | ||
1433 | |||
1434 | if (packet != NULL) | ||
1435 | free_htc_packet_container(target, packet); | ||
1436 | } | ||
1437 | |||
1438 | target->dev = kzalloc(sizeof(*target->dev), GFP_KERNEL); | ||
1439 | if (!target->dev) { | ||
1440 | ath6kl_err("unable to allocate memory\n"); | ||
1441 | status = -ENOMEM; | ||
1442 | goto fail_htc_create; | ||
1443 | } | ||
1444 | target->dev->ar = ar; | ||
1445 | target->dev->htc_cnxt = target; | ||
1446 | |||
1447 | /* Get HIF default pipe for HTC message exchange */ | ||
1448 | ep = &target->endpoint[ENDPOINT_0]; | ||
1449 | |||
1450 | ath6kl_hif_pipe_get_default(ar, &ep->pipe.pipeid_ul, | ||
1451 | &ep->pipe.pipeid_dl); | ||
1452 | |||
1453 | return target; | ||
1454 | |||
1455 | fail_htc_create: | ||
1456 | if (status != 0) { | ||
1457 | if (target != NULL) | ||
1458 | ath6kl_htc_pipe_cleanup(target); | ||
1459 | |||
1460 | target = NULL; | ||
1461 | } | ||
1462 | return target; | ||
1463 | } | ||
1464 | |||
1465 | /* cleanup the HTC instance */ | ||
1466 | static void ath6kl_htc_pipe_cleanup(struct htc_target *target) | ||
1467 | { | ||
1468 | struct htc_packet *packet; | ||
1469 | |||
1470 | while (true) { | ||
1471 | packet = alloc_htc_packet_container(target); | ||
1472 | if (packet == NULL) | ||
1473 | break; | ||
1474 | kfree(packet); | ||
1475 | } | ||
1476 | |||
1477 | kfree(target->dev); | ||
1478 | |||
1479 | /* kfree our instance */ | ||
1480 | kfree(target); | ||
1481 | } | ||
1482 | |||
1483 | static int ath6kl_htc_pipe_start(struct htc_target *target) | ||
1484 | { | ||
1485 | struct sk_buff *skb; | ||
1486 | struct htc_setup_comp_ext_msg *setup; | ||
1487 | struct htc_packet *packet; | ||
1488 | |||
1489 | htc_config_target_hif_pipe(target); | ||
1490 | |||
1491 | /* allocate a buffer to send */ | ||
1492 | packet = htc_alloc_txctrl_packet(target); | ||
1493 | if (packet == NULL) { | ||
1494 | WARN_ON_ONCE(1); | ||
1495 | return -ENOMEM; | ||
1496 | } | ||
1497 | |||
1498 | skb = packet->skb; | ||
1499 | |||
1500 | /* assemble setup complete message */ | ||
1501 | setup = (struct htc_setup_comp_ext_msg *) skb_put(skb, | ||
1502 | sizeof(*setup)); | ||
1503 | memset(setup, 0, sizeof(struct htc_setup_comp_ext_msg)); | ||
1504 | setup->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_EX_ID); | ||
1505 | |||
1506 | ath6kl_dbg(ATH6KL_DBG_HTC, "HTC using TX credit flow control\n"); | ||
1507 | |||
1508 | set_htc_pkt_info(packet, NULL, (u8 *) setup, | ||
1509 | sizeof(struct htc_setup_comp_ext_msg), | ||
1510 | ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); | ||
1511 | |||
1512 | target->htc_flags |= HTC_OP_STATE_SETUP_COMPLETE; | ||
1513 | |||
1514 | return ath6kl_htc_pipe_tx(target, packet); | ||
1515 | } | ||
1516 | |||
1517 | static void ath6kl_htc_pipe_stop(struct htc_target *target) | ||
1518 | { | ||
1519 | int i; | ||
1520 | struct htc_endpoint *ep; | ||
1521 | |||
1522 | /* cleanup endpoints */ | ||
1523 | for (i = 0; i < ENDPOINT_MAX; i++) { | ||
1524 | ep = &target->endpoint[i]; | ||
1525 | htc_flush_rx_queue(target, ep); | ||
1526 | htc_flush_tx_endpoint(target, ep, HTC_TX_PACKET_TAG_ALL); | ||
1527 | } | ||
1528 | |||
1529 | reset_endpoint_states(target); | ||
1530 | target->htc_flags &= ~HTC_OP_STATE_SETUP_COMPLETE; | ||
1531 | } | ||
1532 | |||
1533 | static int ath6kl_htc_pipe_get_rxbuf_num(struct htc_target *target, | ||
1534 | enum htc_endpoint_id endpoint) | ||
1535 | { | ||
1536 | int num; | ||
1537 | |||
1538 | spin_lock_bh(&target->rx_lock); | ||
1539 | num = get_queue_depth(&(target->endpoint[endpoint].rx_bufq)); | ||
1540 | spin_unlock_bh(&target->rx_lock); | ||
1541 | |||
1542 | return num; | ||
1543 | } | ||
1544 | |||
1545 | static int ath6kl_htc_pipe_tx(struct htc_target *target, | ||
1546 | struct htc_packet *packet) | ||
1547 | { | ||
1548 | struct list_head queue; | ||
1549 | |||
1550 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1551 | "%s: endPointId: %d, buffer: 0x%p, length: %d\n", | ||
1552 | __func__, packet->endpoint, packet->buf, | ||
1553 | packet->act_len); | ||
1554 | |||
1555 | INIT_LIST_HEAD(&queue); | ||
1556 | list_add_tail(&packet->list, &queue); | ||
1557 | |||
1558 | return htc_send_packets_multiple(target, &queue); | ||
1559 | } | ||
1560 | |||
1561 | static int ath6kl_htc_pipe_wait_target(struct htc_target *target) | ||
1562 | { | ||
1563 | struct htc_ready_ext_msg *ready_msg; | ||
1564 | struct htc_service_connect_req connect; | ||
1565 | struct htc_service_connect_resp resp; | ||
1566 | int status = 0; | ||
1567 | |||
1568 | status = htc_wait_recv_ctrl_message(target); | ||
1569 | |||
1570 | if (status != 0) | ||
1571 | return status; | ||
1572 | |||
1573 | if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { | ||
1574 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n", | ||
1575 | target->pipe.ctrl_response_len); | ||
1576 | return -ECOMM; | ||
1577 | } | ||
1578 | |||
1579 | ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; | ||
1580 | |||
1581 | if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { | ||
1582 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n", | ||
1583 | ready_msg->ver2_0_info.msg_id); | ||
1584 | return -ECOMM; | ||
1585 | } | ||
1586 | |||
1587 | ath6kl_dbg(ATH6KL_DBG_HTC, | ||
1588 | "Target Ready! : transmit resources : %d size:%d\n", | ||
1589 | ready_msg->ver2_0_info.cred_cnt, | ||
1590 | ready_msg->ver2_0_info.cred_sz); | ||
1591 | |||
1592 | target->tgt_creds = le16_to_cpu(ready_msg->ver2_0_info.cred_cnt); | ||
1593 | target->tgt_cred_sz = le16_to_cpu(ready_msg->ver2_0_info.cred_sz); | ||
1594 | |||
1595 | if ((target->tgt_creds == 0) || (target->tgt_cred_sz == 0)) | ||
1596 | return -ECOMM; | ||
1597 | |||
1598 | htc_setup_target_buffer_assignments(target); | ||
1599 | |||
1600 | /* setup our pseudo HTC control endpoint connection */ | ||
1601 | memset(&connect, 0, sizeof(connect)); | ||
1602 | memset(&resp, 0, sizeof(resp)); | ||
1603 | connect.ep_cb.tx_complete = htc_txctrl_complete; | ||
1604 | connect.ep_cb.rx = htc_rxctrl_complete; | ||
1605 | connect.max_txq_depth = NUM_CONTROL_TX_BUFFERS; | ||
1606 | connect.svc_id = HTC_CTRL_RSVD_SVC; | ||
1607 | |||
1608 | /* connect fake service */ | ||
1609 | status = ath6kl_htc_pipe_conn_service(target, &connect, &resp); | ||
1610 | |||
1611 | return status; | ||
1612 | } | ||
1613 | |||
1614 | static void ath6kl_htc_pipe_flush_txep(struct htc_target *target, | ||
1615 | enum htc_endpoint_id endpoint, u16 tag) | ||
1616 | { | ||
1617 | struct htc_endpoint *ep = &target->endpoint[endpoint]; | ||
1618 | |||
1619 | if (ep->svc_id == 0) { | ||
1620 | WARN_ON_ONCE(1); | ||
1621 | /* not in use.. */ | ||
1622 | return; | ||
1623 | } | ||
1624 | |||
1625 | htc_flush_tx_endpoint(target, ep, tag); | ||
1626 | } | ||
1627 | |||
1628 | static int ath6kl_htc_pipe_add_rxbuf_multiple(struct htc_target *target, | ||
1629 | struct list_head *pkt_queue) | ||
1630 | { | ||
1631 | struct htc_packet *packet, *tmp_pkt, *first; | ||
1632 | struct htc_endpoint *ep; | ||
1633 | int status = 0; | ||
1634 | |||
1635 | if (list_empty(pkt_queue)) | ||
1636 | return -EINVAL; | ||
1637 | |||
1638 | first = list_first_entry(pkt_queue, struct htc_packet, list); | ||
1639 | if (first == NULL) { | ||
1640 | WARN_ON_ONCE(1); | ||
1641 | return -EINVAL; | ||
1642 | } | ||
1643 | |||
1644 | if (first->endpoint >= ENDPOINT_MAX) { | ||
1645 | WARN_ON_ONCE(1); | ||
1646 | return -EINVAL; | ||
1647 | } | ||
1648 | |||
1649 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: epid: %d, cnt:%d, len: %d\n", | ||
1650 | __func__, first->endpoint, get_queue_depth(pkt_queue), | ||
1651 | first->buf_len); | ||
1652 | |||
1653 | ep = &target->endpoint[first->endpoint]; | ||
1654 | |||
1655 | spin_lock_bh(&target->rx_lock); | ||
1656 | |||
1657 | /* store receive packets */ | ||
1658 | list_splice_tail_init(pkt_queue, &ep->rx_bufq); | ||
1659 | |||
1660 | spin_unlock_bh(&target->rx_lock); | ||
1661 | |||
1662 | if (status != 0) { | ||
1663 | /* walk through queue and mark each one canceled */ | ||
1664 | list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) { | ||
1665 | packet->status = -ECANCELED; | ||
1666 | } | ||
1667 | |||
1668 | do_recv_completion(ep, pkt_queue); | ||
1669 | } | ||
1670 | |||
1671 | return status; | ||
1672 | } | ||
1673 | |||
1674 | static void ath6kl_htc_pipe_activity_changed(struct htc_target *target, | ||
1675 | enum htc_endpoint_id ep, | ||
1676 | bool active) | ||
1677 | { | ||
1678 | /* TODO */ | ||
1679 | } | ||
1680 | |||
1681 | static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target) | ||
1682 | { | ||
1683 | /* TODO */ | ||
1684 | } | ||
1685 | |||
1686 | static int ath6kl_htc_pipe_credit_setup(struct htc_target *target, | ||
1687 | struct ath6kl_htc_credit_info *info) | ||
1688 | { | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | static const struct ath6kl_htc_ops ath6kl_htc_pipe_ops = { | ||
1693 | .create = ath6kl_htc_pipe_create, | ||
1694 | .wait_target = ath6kl_htc_pipe_wait_target, | ||
1695 | .start = ath6kl_htc_pipe_start, | ||
1696 | .conn_service = ath6kl_htc_pipe_conn_service, | ||
1697 | .tx = ath6kl_htc_pipe_tx, | ||
1698 | .stop = ath6kl_htc_pipe_stop, | ||
1699 | .cleanup = ath6kl_htc_pipe_cleanup, | ||
1700 | .flush_txep = ath6kl_htc_pipe_flush_txep, | ||
1701 | .flush_rx_buf = ath6kl_htc_pipe_flush_rx_buf, | ||
1702 | .activity_changed = ath6kl_htc_pipe_activity_changed, | ||
1703 | .get_rxbuf_num = ath6kl_htc_pipe_get_rxbuf_num, | ||
1704 | .add_rxbuf_multiple = ath6kl_htc_pipe_add_rxbuf_multiple, | ||
1705 | .credit_setup = ath6kl_htc_pipe_credit_setup, | ||
1706 | .tx_complete = ath6kl_htc_pipe_tx_complete, | ||
1707 | .rx_complete = ath6kl_htc_pipe_rx_complete, | ||
1708 | }; | ||
1709 | |||
1710 | void ath6kl_htc_pipe_attach(struct ath6kl *ar) | ||
1711 | { | ||
1712 | ar->htc_ops = &ath6kl_htc_pipe_ops; | ||
1713 | } | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index eb7cc2f5b96f..29ef50ea07d5 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -23,12 +23,14 @@ | |||
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/mmc/sdio_func.h> | 25 | #include <linux/mmc/sdio_func.h> |
26 | #include <linux/vmalloc.h> | ||
26 | 27 | ||
27 | #include "core.h" | 28 | #include "core.h" |
28 | #include "cfg80211.h" | 29 | #include "cfg80211.h" |
29 | #include "target.h" | 30 | #include "target.h" |
30 | #include "debug.h" | 31 | #include "debug.h" |
31 | #include "hif-ops.h" | 32 | #include "hif-ops.h" |
33 | #include "htc-ops.h" | ||
32 | 34 | ||
33 | static const struct ath6kl_hw hw_list[] = { | 35 | static const struct ath6kl_hw hw_list[] = { |
34 | { | 36 | { |
@@ -258,6 +260,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar) | |||
258 | memset(&connect, 0, sizeof(connect)); | 260 | memset(&connect, 0, sizeof(connect)); |
259 | 261 | ||
260 | /* these fields are the same for all service endpoints */ | 262 | /* these fields are the same for all service endpoints */ |
263 | connect.ep_cb.tx_comp_multi = ath6kl_tx_complete; | ||
261 | connect.ep_cb.rx = ath6kl_rx; | 264 | connect.ep_cb.rx = ath6kl_rx; |
262 | connect.ep_cb.rx_refill = ath6kl_rx_refill; | 265 | connect.ep_cb.rx_refill = ath6kl_rx_refill; |
263 | connect.ep_cb.tx_full = ath6kl_tx_queue_full; | 266 | connect.ep_cb.tx_full = ath6kl_tx_queue_full; |
@@ -487,22 +490,31 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
487 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); | 490 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); |
488 | 491 | ||
489 | /* | 492 | /* |
490 | * By default, submodes : | 493 | * Submodes when fw does not support dynamic interface |
494 | * switching: | ||
491 | * vif[0] - AP/STA/IBSS | 495 | * vif[0] - AP/STA/IBSS |
492 | * vif[1] - "P2P dev"/"P2P GO"/"P2P Client" | 496 | * vif[1] - "P2P dev"/"P2P GO"/"P2P Client" |
493 | * vif[2] - "P2P dev"/"P2P GO"/"P2P Client" | 497 | * vif[2] - "P2P dev"/"P2P GO"/"P2P Client" |
498 | * Otherwise, All the interface are initialized to p2p dev. | ||
494 | */ | 499 | */ |
495 | 500 | ||
496 | for (i = 0; i < ar->max_norm_iface; i++) | 501 | if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, |
497 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << | 502 | ar->fw_capabilities)) { |
498 | (i * HI_OPTION_FW_SUBMODE_BITS); | 503 | for (i = 0; i < ar->vif_max; i++) |
504 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << | ||
505 | (i * HI_OPTION_FW_SUBMODE_BITS); | ||
506 | } else { | ||
507 | for (i = 0; i < ar->max_norm_iface; i++) | ||
508 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << | ||
509 | (i * HI_OPTION_FW_SUBMODE_BITS); | ||
499 | 510 | ||
500 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) | 511 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) |
501 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << | 512 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << |
502 | (i * HI_OPTION_FW_SUBMODE_BITS); | 513 | (i * HI_OPTION_FW_SUBMODE_BITS); |
503 | 514 | ||
504 | if (ar->p2p && ar->vif_max == 1) | 515 | if (ar->p2p && ar->vif_max == 1) |
505 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; | 516 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; |
517 | } | ||
506 | 518 | ||
507 | if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest, | 519 | if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest, |
508 | HTC_PROTOCOL_VERSION) != 0) { | 520 | HTC_PROTOCOL_VERSION) != 0) { |
@@ -541,18 +553,20 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
541 | * but possible in theory. | 553 | * but possible in theory. |
542 | */ | 554 | */ |
543 | 555 | ||
544 | param = ar->hw.board_ext_data_addr; | 556 | if (ar->target_type == TARGET_TYPE_AR6003) { |
545 | ram_reserved_size = ar->hw.reserved_ram_size; | 557 | param = ar->hw.board_ext_data_addr; |
558 | ram_reserved_size = ar->hw.reserved_ram_size; | ||
546 | 559 | ||
547 | if (ath6kl_bmi_write_hi32(ar, hi_board_ext_data, param) != 0) { | 560 | if (ath6kl_bmi_write_hi32(ar, hi_board_ext_data, param) != 0) { |
548 | ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); | 561 | ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); |
549 | return -EIO; | 562 | return -EIO; |
550 | } | 563 | } |
551 | 564 | ||
552 | if (ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, | 565 | if (ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, |
553 | ram_reserved_size) != 0) { | 566 | ram_reserved_size) != 0) { |
554 | ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); | 567 | ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); |
555 | return -EIO; | 568 | return -EIO; |
569 | } | ||
556 | } | 570 | } |
557 | 571 | ||
558 | /* set the block size for the target */ | 572 | /* set the block size for the target */ |
@@ -926,13 +940,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
926 | if (ar->fw != NULL) | 940 | if (ar->fw != NULL) |
927 | break; | 941 | break; |
928 | 942 | ||
929 | ar->fw = kmemdup(data, ie_len, GFP_KERNEL); | 943 | ar->fw = vmalloc(ie_len); |
930 | 944 | ||
931 | if (ar->fw == NULL) { | 945 | if (ar->fw == NULL) { |
932 | ret = -ENOMEM; | 946 | ret = -ENOMEM; |
933 | goto out; | 947 | goto out; |
934 | } | 948 | } |
935 | 949 | ||
950 | memcpy(ar->fw, data, ie_len); | ||
936 | ar->fw_len = ie_len; | 951 | ar->fw_len = ie_len; |
937 | break; | 952 | break; |
938 | case ATH6KL_FW_IE_PATCH_IMAGE: | 953 | case ATH6KL_FW_IE_PATCH_IMAGE: |
@@ -1509,7 +1524,7 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1509 | } | 1524 | } |
1510 | 1525 | ||
1511 | /* setup credit distribution */ | 1526 | /* setup credit distribution */ |
1512 | ath6kl_credit_setup(ar->htc_target, &ar->credit_state_info); | 1527 | ath6kl_htc_credit_setup(ar->htc_target, &ar->credit_state_info); |
1513 | 1528 | ||
1514 | /* start HTC */ | 1529 | /* start HTC */ |
1515 | ret = ath6kl_htc_start(ar->htc_target); | 1530 | ret = ath6kl_htc_start(ar->htc_target); |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 07071fce8a0e..4d818f96c415 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -758,6 +758,10 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) | |||
758 | stats->wow_evt_discarded += | 758 | stats->wow_evt_discarded += |
759 | le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded); | 759 | le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded); |
760 | 760 | ||
761 | stats->arp_received = le32_to_cpu(tgt_stats->arp_stats.arp_received); | ||
762 | stats->arp_replied = le32_to_cpu(tgt_stats->arp_stats.arp_replied); | ||
763 | stats->arp_matched = le32_to_cpu(tgt_stats->arp_stats.arp_matched); | ||
764 | |||
761 | if (test_bit(STATS_UPDATE_PEND, &vif->flags)) { | 765 | if (test_bit(STATS_UPDATE_PEND, &vif->flags)) { |
762 | clear_bit(STATS_UPDATE_PEND, &vif->flags); | 766 | clear_bit(STATS_UPDATE_PEND, &vif->flags); |
763 | wake_up(&ar->event_wq); | 767 | wake_up(&ar->event_wq); |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 53528648b425..44ea7a742101 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -1362,7 +1362,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
1362 | goto err_core_alloc; | 1362 | goto err_core_alloc; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | ret = ath6kl_core_init(ar); | 1365 | ret = ath6kl_core_init(ar, ATH6KL_HTC_TYPE_MBOX); |
1366 | if (ret) { | 1366 | if (ret) { |
1367 | ath6kl_err("Failed to init ath6kl core\n"); | 1367 | ath6kl_err("Failed to init ath6kl core\n"); |
1368 | goto err_core_alloc; | 1368 | goto err_core_alloc; |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 521f0be990f1..82f2f5cb475b 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "htc-ops.h" | ||
22 | 23 | ||
23 | /* | 24 | /* |
24 | * tid - tid_mux0..tid_mux3 | 25 | * tid - tid_mux0..tid_mux3 |
@@ -324,6 +325,7 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, | |||
324 | cookie->map_no = 0; | 325 | cookie->map_no = 0; |
325 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, | 326 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, |
326 | eid, ATH6KL_CONTROL_PKT_TAG); | 327 | eid, ATH6KL_CONTROL_PKT_TAG); |
328 | cookie->htc_pkt.skb = skb; | ||
327 | 329 | ||
328 | /* | 330 | /* |
329 | * This interface is asynchronous, if there is an error, cleanup | 331 | * This interface is asynchronous, if there is an error, cleanup |
@@ -492,6 +494,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
492 | cookie->map_no = map_no; | 494 | cookie->map_no = map_no; |
493 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, | 495 | set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len, |
494 | eid, htc_tag); | 496 | eid, htc_tag); |
497 | cookie->htc_pkt.skb = skb; | ||
495 | 498 | ||
496 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ", | 499 | ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ", |
497 | skb->data, skb->len); | 500 | skb->data, skb->len); |
@@ -572,7 +575,7 @@ void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active) | |||
572 | 575 | ||
573 | notify_htc: | 576 | notify_htc: |
574 | /* notify HTC, this may cause credit distribution changes */ | 577 | /* notify HTC, this may cause credit distribution changes */ |
575 | ath6kl_htc_indicate_activity_change(ar->htc_target, eid, active); | 578 | ath6kl_htc_activity_changed(ar->htc_target, eid, active); |
576 | } | 579 | } |
577 | 580 | ||
578 | enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | 581 | enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, |
@@ -668,9 +671,10 @@ static void ath6kl_tx_clear_node_map(struct ath6kl_vif *vif, | |||
668 | } | 671 | } |
669 | } | 672 | } |
670 | 673 | ||
671 | void ath6kl_tx_complete(void *context, struct list_head *packet_queue) | 674 | void ath6kl_tx_complete(struct htc_target *target, |
675 | struct list_head *packet_queue) | ||
672 | { | 676 | { |
673 | struct ath6kl *ar = context; | 677 | struct ath6kl *ar = target->dev->ar; |
674 | struct sk_buff_head skb_queue; | 678 | struct sk_buff_head skb_queue; |
675 | struct htc_packet *packet; | 679 | struct htc_packet *packet; |
676 | struct sk_buff *skb; | 680 | struct sk_buff *skb; |
@@ -889,6 +893,7 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint) | |||
889 | skb->data = PTR_ALIGN(skb->data - 4, 4); | 893 | skb->data = PTR_ALIGN(skb->data - 4, 4); |
890 | set_htc_rxpkt_info(packet, skb, skb->data, | 894 | set_htc_rxpkt_info(packet, skb, skb->data, |
891 | ATH6KL_BUFFER_SIZE, endpoint); | 895 | ATH6KL_BUFFER_SIZE, endpoint); |
896 | packet->skb = skb; | ||
892 | list_add_tail(&packet->list, &queue); | 897 | list_add_tail(&packet->list, &queue); |
893 | } | 898 | } |
894 | 899 | ||
@@ -911,6 +916,8 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count) | |||
911 | skb->data = PTR_ALIGN(skb->data - 4, 4); | 916 | skb->data = PTR_ALIGN(skb->data - 4, 4); |
912 | set_htc_rxpkt_info(packet, skb, skb->data, | 917 | set_htc_rxpkt_info(packet, skb, skb->data, |
913 | ATH6KL_AMSDU_BUFFER_SIZE, 0); | 918 | ATH6KL_AMSDU_BUFFER_SIZE, 0); |
919 | packet->skb = skb; | ||
920 | |||
914 | spin_lock_bh(&ar->lock); | 921 | spin_lock_bh(&ar->lock); |
915 | list_add_tail(&packet->list, &ar->amsdu_rx_buffer_queue); | 922 | list_add_tail(&packet->list, &ar->amsdu_rx_buffer_queue); |
916 | spin_unlock_bh(&ar->lock); | 923 | spin_unlock_bh(&ar->lock); |
@@ -1283,6 +1290,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1283 | struct wmi_data_hdr *dhdr; | 1290 | struct wmi_data_hdr *dhdr; |
1284 | int min_hdr_len; | 1291 | int min_hdr_len; |
1285 | u8 meta_type, dot11_hdr = 0; | 1292 | u8 meta_type, dot11_hdr = 0; |
1293 | u8 pad_before_data_start; | ||
1286 | int status = packet->status; | 1294 | int status = packet->status; |
1287 | enum htc_endpoint_id ept = packet->endpoint; | 1295 | enum htc_endpoint_id ept = packet->endpoint; |
1288 | bool is_amsdu, prev_ps, ps_state = false; | 1296 | bool is_amsdu, prev_ps, ps_state = false; |
@@ -1494,6 +1502,10 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1494 | seq_no = wmi_data_hdr_get_seqno(dhdr); | 1502 | seq_no = wmi_data_hdr_get_seqno(dhdr); |
1495 | meta_type = wmi_data_hdr_get_meta(dhdr); | 1503 | meta_type = wmi_data_hdr_get_meta(dhdr); |
1496 | dot11_hdr = wmi_data_hdr_get_dot11(dhdr); | 1504 | dot11_hdr = wmi_data_hdr_get_dot11(dhdr); |
1505 | pad_before_data_start = | ||
1506 | (le16_to_cpu(dhdr->info3) >> WMI_DATA_HDR_PAD_BEFORE_DATA_SHIFT) | ||
1507 | & WMI_DATA_HDR_PAD_BEFORE_DATA_MASK; | ||
1508 | |||
1497 | skb_pull(skb, sizeof(struct wmi_data_hdr)); | 1509 | skb_pull(skb, sizeof(struct wmi_data_hdr)); |
1498 | 1510 | ||
1499 | switch (meta_type) { | 1511 | switch (meta_type) { |
@@ -1512,6 +1524,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1512 | break; | 1524 | break; |
1513 | } | 1525 | } |
1514 | 1526 | ||
1527 | skb_pull(skb, pad_before_data_start); | ||
1528 | |||
1515 | if (dot11_hdr) | 1529 | if (dot11_hdr) |
1516 | status = ath6kl_wmi_dot11_hdr_remove(ar->wmi, skb); | 1530 | status = ath6kl_wmi_dot11_hdr_remove(ar->wmi, skb); |
1517 | else if (!is_amsdu) | 1531 | else if (!is_amsdu) |
@@ -1581,7 +1595,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1581 | /* aggregation code will handle the skb */ | 1595 | /* aggregation code will handle the skb */ |
1582 | return; | 1596 | return; |
1583 | } | 1597 | } |
1584 | } | 1598 | } else if (!is_broadcast_ether_addr(datap->h_dest)) |
1599 | vif->net_stats.multicast++; | ||
1585 | 1600 | ||
1586 | ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); | 1601 | ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); |
1587 | } | 1602 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 325b1224c2b1..ec7f1f5fd1ca 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -21,15 +21,77 @@ | |||
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "core.h" | 22 | #include "core.h" |
23 | 23 | ||
24 | /* constants */ | ||
25 | #define TX_URB_COUNT 32 | ||
26 | #define RX_URB_COUNT 32 | ||
27 | #define ATH6KL_USB_RX_BUFFER_SIZE 1700 | ||
28 | |||
29 | /* tx/rx pipes for usb */ | ||
30 | enum ATH6KL_USB_PIPE_ID { | ||
31 | ATH6KL_USB_PIPE_TX_CTRL = 0, | ||
32 | ATH6KL_USB_PIPE_TX_DATA_LP, | ||
33 | ATH6KL_USB_PIPE_TX_DATA_MP, | ||
34 | ATH6KL_USB_PIPE_TX_DATA_HP, | ||
35 | ATH6KL_USB_PIPE_RX_CTRL, | ||
36 | ATH6KL_USB_PIPE_RX_DATA, | ||
37 | ATH6KL_USB_PIPE_RX_DATA2, | ||
38 | ATH6KL_USB_PIPE_RX_INT, | ||
39 | ATH6KL_USB_PIPE_MAX | ||
40 | }; | ||
41 | |||
42 | #define ATH6KL_USB_PIPE_INVALID ATH6KL_USB_PIPE_MAX | ||
43 | |||
44 | struct ath6kl_usb_pipe { | ||
45 | struct list_head urb_list_head; | ||
46 | struct usb_anchor urb_submitted; | ||
47 | u32 urb_alloc; | ||
48 | u32 urb_cnt; | ||
49 | u32 urb_cnt_thresh; | ||
50 | unsigned int usb_pipe_handle; | ||
51 | u32 flags; | ||
52 | u8 ep_address; | ||
53 | u8 logical_pipe_num; | ||
54 | struct ath6kl_usb *ar_usb; | ||
55 | u16 max_packet_size; | ||
56 | struct work_struct io_complete_work; | ||
57 | struct sk_buff_head io_comp_queue; | ||
58 | struct usb_endpoint_descriptor *ep_desc; | ||
59 | }; | ||
60 | |||
61 | #define ATH6KL_USB_PIPE_FLAG_TX (1 << 0) | ||
62 | |||
24 | /* usb device object */ | 63 | /* usb device object */ |
25 | struct ath6kl_usb { | 64 | struct ath6kl_usb { |
65 | /* protects pipe->urb_list_head and pipe->urb_cnt */ | ||
66 | spinlock_t cs_lock; | ||
67 | |||
26 | struct usb_device *udev; | 68 | struct usb_device *udev; |
27 | struct usb_interface *interface; | 69 | struct usb_interface *interface; |
70 | struct ath6kl_usb_pipe pipes[ATH6KL_USB_PIPE_MAX]; | ||
28 | u8 *diag_cmd_buffer; | 71 | u8 *diag_cmd_buffer; |
29 | u8 *diag_resp_buffer; | 72 | u8 *diag_resp_buffer; |
30 | struct ath6kl *ar; | 73 | struct ath6kl *ar; |
31 | }; | 74 | }; |
32 | 75 | ||
76 | /* usb urb object */ | ||
77 | struct ath6kl_urb_context { | ||
78 | struct list_head link; | ||
79 | struct ath6kl_usb_pipe *pipe; | ||
80 | struct sk_buff *skb; | ||
81 | struct ath6kl *ar; | ||
82 | }; | ||
83 | |||
84 | /* USB endpoint definitions */ | ||
85 | #define ATH6KL_USB_EP_ADDR_APP_CTRL_IN 0x81 | ||
86 | #define ATH6KL_USB_EP_ADDR_APP_DATA_IN 0x82 | ||
87 | #define ATH6KL_USB_EP_ADDR_APP_DATA2_IN 0x83 | ||
88 | #define ATH6KL_USB_EP_ADDR_APP_INT_IN 0x84 | ||
89 | |||
90 | #define ATH6KL_USB_EP_ADDR_APP_CTRL_OUT 0x01 | ||
91 | #define ATH6KL_USB_EP_ADDR_APP_DATA_LP_OUT 0x02 | ||
92 | #define ATH6KL_USB_EP_ADDR_APP_DATA_MP_OUT 0x03 | ||
93 | #define ATH6KL_USB_EP_ADDR_APP_DATA_HP_OUT 0x04 | ||
94 | |||
33 | /* diagnostic command defnitions */ | 95 | /* diagnostic command defnitions */ |
34 | #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 | 96 | #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 |
35 | #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 | 97 | #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 |
@@ -55,11 +117,493 @@ struct ath6kl_usb_ctrl_diag_resp_read { | |||
55 | __le32 value; | 117 | __le32 value; |
56 | } __packed; | 118 | } __packed; |
57 | 119 | ||
120 | /* function declarations */ | ||
121 | static void ath6kl_usb_recv_complete(struct urb *urb); | ||
122 | |||
123 | #define ATH6KL_USB_IS_BULK_EP(attr) (((attr) & 3) == 0x02) | ||
124 | #define ATH6KL_USB_IS_INT_EP(attr) (((attr) & 3) == 0x03) | ||
125 | #define ATH6KL_USB_IS_ISOC_EP(attr) (((attr) & 3) == 0x01) | ||
126 | #define ATH6KL_USB_IS_DIR_IN(addr) ((addr) & 0x80) | ||
127 | |||
128 | /* pipe/urb operations */ | ||
129 | static struct ath6kl_urb_context * | ||
130 | ath6kl_usb_alloc_urb_from_pipe(struct ath6kl_usb_pipe *pipe) | ||
131 | { | ||
132 | struct ath6kl_urb_context *urb_context = NULL; | ||
133 | unsigned long flags; | ||
134 | |||
135 | spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags); | ||
136 | if (!list_empty(&pipe->urb_list_head)) { | ||
137 | urb_context = | ||
138 | list_first_entry(&pipe->urb_list_head, | ||
139 | struct ath6kl_urb_context, link); | ||
140 | list_del(&urb_context->link); | ||
141 | pipe->urb_cnt--; | ||
142 | } | ||
143 | spin_unlock_irqrestore(&pipe->ar_usb->cs_lock, flags); | ||
144 | |||
145 | return urb_context; | ||
146 | } | ||
147 | |||
148 | static void ath6kl_usb_free_urb_to_pipe(struct ath6kl_usb_pipe *pipe, | ||
149 | struct ath6kl_urb_context *urb_context) | ||
150 | { | ||
151 | unsigned long flags; | ||
152 | |||
153 | spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags); | ||
154 | pipe->urb_cnt++; | ||
155 | |||
156 | list_add(&urb_context->link, &pipe->urb_list_head); | ||
157 | spin_unlock_irqrestore(&pipe->ar_usb->cs_lock, flags); | ||
158 | } | ||
159 | |||
160 | static void ath6kl_usb_cleanup_recv_urb(struct ath6kl_urb_context *urb_context) | ||
161 | { | ||
162 | if (urb_context->skb != NULL) { | ||
163 | dev_kfree_skb(urb_context->skb); | ||
164 | urb_context->skb = NULL; | ||
165 | } | ||
166 | |||
167 | ath6kl_usb_free_urb_to_pipe(urb_context->pipe, urb_context); | ||
168 | } | ||
169 | |||
170 | static inline struct ath6kl_usb *ath6kl_usb_priv(struct ath6kl *ar) | ||
171 | { | ||
172 | return ar->hif_priv; | ||
173 | } | ||
174 | |||
175 | /* pipe resource allocation/cleanup */ | ||
176 | static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe, | ||
177 | int urb_cnt) | ||
178 | { | ||
179 | struct ath6kl_urb_context *urb_context; | ||
180 | int status = 0, i; | ||
181 | |||
182 | INIT_LIST_HEAD(&pipe->urb_list_head); | ||
183 | init_usb_anchor(&pipe->urb_submitted); | ||
184 | |||
185 | for (i = 0; i < urb_cnt; i++) { | ||
186 | urb_context = kzalloc(sizeof(struct ath6kl_urb_context), | ||
187 | GFP_KERNEL); | ||
188 | if (urb_context == NULL) | ||
189 | /* FIXME: set status to -ENOMEM */ | ||
190 | break; | ||
191 | |||
192 | urb_context->pipe = pipe; | ||
193 | |||
194 | /* | ||
195 | * we are only allocate the urb contexts here, the actual URB | ||
196 | * is allocated from the kernel as needed to do a transaction | ||
197 | */ | ||
198 | pipe->urb_alloc++; | ||
199 | ath6kl_usb_free_urb_to_pipe(pipe, urb_context); | ||
200 | } | ||
201 | |||
202 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
203 | "ath6kl usb: alloc resources lpipe:%d hpipe:0x%X urbs:%d\n", | ||
204 | pipe->logical_pipe_num, pipe->usb_pipe_handle, | ||
205 | pipe->urb_alloc); | ||
206 | |||
207 | return status; | ||
208 | } | ||
209 | |||
210 | static void ath6kl_usb_free_pipe_resources(struct ath6kl_usb_pipe *pipe) | ||
211 | { | ||
212 | struct ath6kl_urb_context *urb_context; | ||
213 | |||
214 | if (pipe->ar_usb == NULL) { | ||
215 | /* nothing allocated for this pipe */ | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
220 | "ath6kl usb: free resources lpipe:%d" | ||
221 | "hpipe:0x%X urbs:%d avail:%d\n", | ||
222 | pipe->logical_pipe_num, pipe->usb_pipe_handle, | ||
223 | pipe->urb_alloc, pipe->urb_cnt); | ||
224 | |||
225 | if (pipe->urb_alloc != pipe->urb_cnt) { | ||
226 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
227 | "ath6kl usb: urb leak! lpipe:%d" | ||
228 | "hpipe:0x%X urbs:%d avail:%d\n", | ||
229 | pipe->logical_pipe_num, pipe->usb_pipe_handle, | ||
230 | pipe->urb_alloc, pipe->urb_cnt); | ||
231 | } | ||
232 | |||
233 | while (true) { | ||
234 | urb_context = ath6kl_usb_alloc_urb_from_pipe(pipe); | ||
235 | if (urb_context == NULL) | ||
236 | break; | ||
237 | kfree(urb_context); | ||
238 | } | ||
239 | |||
240 | } | ||
241 | |||
242 | static void ath6kl_usb_cleanup_pipe_resources(struct ath6kl_usb *ar_usb) | ||
243 | { | ||
244 | int i; | ||
245 | |||
246 | for (i = 0; i < ATH6KL_USB_PIPE_MAX; i++) | ||
247 | ath6kl_usb_free_pipe_resources(&ar_usb->pipes[i]); | ||
248 | |||
249 | } | ||
250 | |||
251 | static u8 ath6kl_usb_get_logical_pipe_num(struct ath6kl_usb *ar_usb, | ||
252 | u8 ep_address, int *urb_count) | ||
253 | { | ||
254 | u8 pipe_num = ATH6KL_USB_PIPE_INVALID; | ||
255 | |||
256 | switch (ep_address) { | ||
257 | case ATH6KL_USB_EP_ADDR_APP_CTRL_IN: | ||
258 | pipe_num = ATH6KL_USB_PIPE_RX_CTRL; | ||
259 | *urb_count = RX_URB_COUNT; | ||
260 | break; | ||
261 | case ATH6KL_USB_EP_ADDR_APP_DATA_IN: | ||
262 | pipe_num = ATH6KL_USB_PIPE_RX_DATA; | ||
263 | *urb_count = RX_URB_COUNT; | ||
264 | break; | ||
265 | case ATH6KL_USB_EP_ADDR_APP_INT_IN: | ||
266 | pipe_num = ATH6KL_USB_PIPE_RX_INT; | ||
267 | *urb_count = RX_URB_COUNT; | ||
268 | break; | ||
269 | case ATH6KL_USB_EP_ADDR_APP_DATA2_IN: | ||
270 | pipe_num = ATH6KL_USB_PIPE_RX_DATA2; | ||
271 | *urb_count = RX_URB_COUNT; | ||
272 | break; | ||
273 | case ATH6KL_USB_EP_ADDR_APP_CTRL_OUT: | ||
274 | pipe_num = ATH6KL_USB_PIPE_TX_CTRL; | ||
275 | *urb_count = TX_URB_COUNT; | ||
276 | break; | ||
277 | case ATH6KL_USB_EP_ADDR_APP_DATA_LP_OUT: | ||
278 | pipe_num = ATH6KL_USB_PIPE_TX_DATA_LP; | ||
279 | *urb_count = TX_URB_COUNT; | ||
280 | break; | ||
281 | case ATH6KL_USB_EP_ADDR_APP_DATA_MP_OUT: | ||
282 | pipe_num = ATH6KL_USB_PIPE_TX_DATA_MP; | ||
283 | *urb_count = TX_URB_COUNT; | ||
284 | break; | ||
285 | case ATH6KL_USB_EP_ADDR_APP_DATA_HP_OUT: | ||
286 | pipe_num = ATH6KL_USB_PIPE_TX_DATA_HP; | ||
287 | *urb_count = TX_URB_COUNT; | ||
288 | break; | ||
289 | default: | ||
290 | /* note: there may be endpoints not currently used */ | ||
291 | break; | ||
292 | } | ||
293 | |||
294 | return pipe_num; | ||
295 | } | ||
296 | |||
297 | static int ath6kl_usb_setup_pipe_resources(struct ath6kl_usb *ar_usb) | ||
298 | { | ||
299 | struct usb_interface *interface = ar_usb->interface; | ||
300 | struct usb_host_interface *iface_desc = interface->cur_altsetting; | ||
301 | struct usb_endpoint_descriptor *endpoint; | ||
302 | struct ath6kl_usb_pipe *pipe; | ||
303 | int i, urbcount, status = 0; | ||
304 | u8 pipe_num; | ||
305 | |||
306 | ath6kl_dbg(ATH6KL_DBG_USB, "setting up USB Pipes using interface\n"); | ||
307 | |||
308 | /* walk decriptors and setup pipes */ | ||
309 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
310 | endpoint = &iface_desc->endpoint[i].desc; | ||
311 | |||
312 | if (ATH6KL_USB_IS_BULK_EP(endpoint->bmAttributes)) { | ||
313 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
314 | "%s Bulk Ep:0x%2.2X maxpktsz:%d\n", | ||
315 | ATH6KL_USB_IS_DIR_IN | ||
316 | (endpoint->bEndpointAddress) ? | ||
317 | "RX" : "TX", endpoint->bEndpointAddress, | ||
318 | le16_to_cpu(endpoint->wMaxPacketSize)); | ||
319 | } else if (ATH6KL_USB_IS_INT_EP(endpoint->bmAttributes)) { | ||
320 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
321 | "%s Int Ep:0x%2.2X maxpktsz:%d interval:%d\n", | ||
322 | ATH6KL_USB_IS_DIR_IN | ||
323 | (endpoint->bEndpointAddress) ? | ||
324 | "RX" : "TX", endpoint->bEndpointAddress, | ||
325 | le16_to_cpu(endpoint->wMaxPacketSize), | ||
326 | endpoint->bInterval); | ||
327 | } else if (ATH6KL_USB_IS_ISOC_EP(endpoint->bmAttributes)) { | ||
328 | /* TODO for ISO */ | ||
329 | ath6kl_dbg(ATH6KL_DBG_USB, | ||
330 | "%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d\n", | ||
331 | ATH6KL_USB_IS_DIR_IN | ||
332 | (endpoint->bEndpointAddress) ? | ||
333 | "RX" : "TX", endpoint->bEndpointAddress, | ||
334 | le16_to_cpu(endpoint->wMaxPacketSize), | ||
335 | endpoint->bInterval); | ||
336 | } | ||
337 | urbcount = 0; | ||
338 | |||
339 | pipe_num = | ||
340 | ath6kl_usb_get_logical_pipe_num(ar_usb, | ||
341 | endpoint->bEndpointAddress, | ||
342 | &urbcount); | ||
343 | if (pipe_num == ATH6KL_USB_PIPE_INVALID) | ||
344 | continue; | ||
345 | |||
346 | pipe = &ar_usb->pipes[pipe_num]; | ||
347 | if (pipe->ar_usb != NULL) { | ||
348 | /* hmmm..pipe was already setup */ | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | pipe->ar_usb = ar_usb; | ||
353 | pipe->logical_pipe_num = pipe_num; | ||
354 | pipe->ep_address = endpoint->bEndpointAddress; | ||
355 | pipe->max_packet_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
356 | |||
357 | if (ATH6KL_USB_IS_BULK_EP(endpoint->bmAttributes)) { | ||
358 | if (ATH6KL_USB_IS_DIR_IN(pipe->ep_address)) { | ||
359 | pipe->usb_pipe_handle = | ||
360 | usb_rcvbulkpipe(ar_usb->udev, | ||
361 | pipe->ep_address); | ||
362 | } else { | ||
363 | pipe->usb_pipe_handle = | ||
364 | usb_sndbulkpipe(ar_usb->udev, | ||
365 | pipe->ep_address); | ||
366 | } | ||
367 | } else if (ATH6KL_USB_IS_INT_EP(endpoint->bmAttributes)) { | ||
368 | if (ATH6KL_USB_IS_DIR_IN(pipe->ep_address)) { | ||
369 | pipe->usb_pipe_handle = | ||
370 | usb_rcvintpipe(ar_usb->udev, | ||
371 | pipe->ep_address); | ||
372 | } else { | ||
373 | pipe->usb_pipe_handle = | ||
374 | usb_sndintpipe(ar_usb->udev, | ||
375 | pipe->ep_address); | ||
376 | } | ||
377 | } else if (ATH6KL_USB_IS_ISOC_EP(endpoint->bmAttributes)) { | ||
378 | /* TODO for ISO */ | ||
379 | if (ATH6KL_USB_IS_DIR_IN(pipe->ep_address)) { | ||
380 | pipe->usb_pipe_handle = | ||
381 | usb_rcvisocpipe(ar_usb->udev, | ||
382 | pipe->ep_address); | ||
383 | } else { | ||
384 | pipe->usb_pipe_handle = | ||
385 | usb_sndisocpipe(ar_usb->udev, | ||
386 | pipe->ep_address); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | pipe->ep_desc = endpoint; | ||
391 | |||
392 | if (!ATH6KL_USB_IS_DIR_IN(pipe->ep_address)) | ||
393 | pipe->flags |= ATH6KL_USB_PIPE_FLAG_TX; | ||
394 | |||
395 | status = ath6kl_usb_alloc_pipe_resources(pipe, urbcount); | ||
396 | if (status != 0) | ||
397 | break; | ||
398 | } | ||
399 | |||
400 | return status; | ||
401 | } | ||
402 | |||
403 | /* pipe operations */ | ||
404 | static void ath6kl_usb_post_recv_transfers(struct ath6kl_usb_pipe *recv_pipe, | ||
405 | int buffer_length) | ||
406 | { | ||
407 | struct ath6kl_urb_context *urb_context; | ||
408 | struct urb *urb; | ||
409 | int usb_status; | ||
410 | |||
411 | while (true) { | ||
412 | urb_context = ath6kl_usb_alloc_urb_from_pipe(recv_pipe); | ||
413 | if (urb_context == NULL) | ||
414 | break; | ||
415 | |||
416 | urb_context->skb = dev_alloc_skb(buffer_length); | ||
417 | if (urb_context->skb == NULL) | ||
418 | goto err_cleanup_urb; | ||
419 | |||
420 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
421 | if (urb == NULL) | ||
422 | goto err_cleanup_urb; | ||
423 | |||
424 | usb_fill_bulk_urb(urb, | ||
425 | recv_pipe->ar_usb->udev, | ||
426 | recv_pipe->usb_pipe_handle, | ||
427 | urb_context->skb->data, | ||
428 | buffer_length, | ||
429 | ath6kl_usb_recv_complete, urb_context); | ||
430 | |||
431 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
432 | "ath6kl usb: bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes buf:0x%p\n", | ||
433 | recv_pipe->logical_pipe_num, | ||
434 | recv_pipe->usb_pipe_handle, recv_pipe->ep_address, | ||
435 | buffer_length, urb_context->skb); | ||
436 | |||
437 | usb_anchor_urb(urb, &recv_pipe->urb_submitted); | ||
438 | usb_status = usb_submit_urb(urb, GFP_ATOMIC); | ||
439 | |||
440 | if (usb_status) { | ||
441 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
442 | "ath6kl usb : usb bulk recv failed %d\n", | ||
443 | usb_status); | ||
444 | usb_unanchor_urb(urb); | ||
445 | usb_free_urb(urb); | ||
446 | goto err_cleanup_urb; | ||
447 | } | ||
448 | usb_free_urb(urb); | ||
449 | } | ||
450 | return; | ||
451 | |||
452 | err_cleanup_urb: | ||
453 | ath6kl_usb_cleanup_recv_urb(urb_context); | ||
454 | return; | ||
455 | } | ||
456 | |||
457 | static void ath6kl_usb_flush_all(struct ath6kl_usb *ar_usb) | ||
458 | { | ||
459 | int i; | ||
460 | |||
461 | for (i = 0; i < ATH6KL_USB_PIPE_MAX; i++) { | ||
462 | if (ar_usb->pipes[i].ar_usb != NULL) | ||
463 | usb_kill_anchored_urbs(&ar_usb->pipes[i].urb_submitted); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Flushing any pending I/O may schedule work this call will block | ||
468 | * until all scheduled work runs to completion. | ||
469 | */ | ||
470 | flush_scheduled_work(); | ||
471 | } | ||
472 | |||
473 | static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb) | ||
474 | { | ||
475 | /* | ||
476 | * note: control pipe is no longer used | ||
477 | * ar_usb->pipes[ATH6KL_USB_PIPE_RX_CTRL].urb_cnt_thresh = | ||
478 | * ar_usb->pipes[ATH6KL_USB_PIPE_RX_CTRL].urb_alloc/2; | ||
479 | * ath6kl_usb_post_recv_transfers(&ar_usb-> | ||
480 | * pipes[ATH6KL_USB_PIPE_RX_CTRL], | ||
481 | * ATH6KL_USB_RX_BUFFER_SIZE); | ||
482 | */ | ||
483 | |||
484 | ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA].urb_cnt_thresh = | ||
485 | ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA].urb_alloc / 2; | ||
486 | ath6kl_usb_post_recv_transfers(&ar_usb->pipes[ATH6KL_USB_PIPE_RX_DATA], | ||
487 | ATH6KL_USB_RX_BUFFER_SIZE); | ||
488 | } | ||
489 | |||
490 | /* hif usb rx/tx completion functions */ | ||
491 | static void ath6kl_usb_recv_complete(struct urb *urb) | ||
492 | { | ||
493 | struct ath6kl_urb_context *urb_context = urb->context; | ||
494 | struct ath6kl_usb_pipe *pipe = urb_context->pipe; | ||
495 | struct sk_buff *skb = NULL; | ||
496 | int status = 0; | ||
497 | |||
498 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
499 | "%s: recv pipe: %d, stat:%d, len:%d urb:0x%p\n", __func__, | ||
500 | pipe->logical_pipe_num, urb->status, urb->actual_length, | ||
501 | urb); | ||
502 | |||
503 | if (urb->status != 0) { | ||
504 | status = -EIO; | ||
505 | switch (urb->status) { | ||
506 | case -ECONNRESET: | ||
507 | case -ENOENT: | ||
508 | case -ESHUTDOWN: | ||
509 | /* | ||
510 | * no need to spew these errors when device | ||
511 | * removed or urb killed due to driver shutdown | ||
512 | */ | ||
513 | status = -ECANCELED; | ||
514 | break; | ||
515 | default: | ||
516 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
517 | "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", | ||
518 | __func__, pipe->logical_pipe_num, | ||
519 | pipe->ep_address, urb->status); | ||
520 | break; | ||
521 | } | ||
522 | goto cleanup_recv_urb; | ||
523 | } | ||
524 | |||
525 | if (urb->actual_length == 0) | ||
526 | goto cleanup_recv_urb; | ||
527 | |||
528 | skb = urb_context->skb; | ||
529 | |||
530 | /* we are going to pass it up */ | ||
531 | urb_context->skb = NULL; | ||
532 | skb_put(skb, urb->actual_length); | ||
533 | |||
534 | /* note: queue implements a lock */ | ||
535 | skb_queue_tail(&pipe->io_comp_queue, skb); | ||
536 | schedule_work(&pipe->io_complete_work); | ||
537 | |||
538 | cleanup_recv_urb: | ||
539 | ath6kl_usb_cleanup_recv_urb(urb_context); | ||
540 | |||
541 | if (status == 0 && | ||
542 | pipe->urb_cnt >= pipe->urb_cnt_thresh) { | ||
543 | /* our free urbs are piling up, post more transfers */ | ||
544 | ath6kl_usb_post_recv_transfers(pipe, ATH6KL_USB_RX_BUFFER_SIZE); | ||
545 | } | ||
546 | } | ||
547 | |||
548 | static void ath6kl_usb_usb_transmit_complete(struct urb *urb) | ||
549 | { | ||
550 | struct ath6kl_urb_context *urb_context = urb->context; | ||
551 | struct ath6kl_usb_pipe *pipe = urb_context->pipe; | ||
552 | struct sk_buff *skb; | ||
553 | |||
554 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
555 | "%s: pipe: %d, stat:%d, len:%d\n", | ||
556 | __func__, pipe->logical_pipe_num, urb->status, | ||
557 | urb->actual_length); | ||
558 | |||
559 | if (urb->status != 0) { | ||
560 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
561 | "%s: pipe: %d, failed:%d\n", | ||
562 | __func__, pipe->logical_pipe_num, urb->status); | ||
563 | } | ||
564 | |||
565 | skb = urb_context->skb; | ||
566 | urb_context->skb = NULL; | ||
567 | ath6kl_usb_free_urb_to_pipe(urb_context->pipe, urb_context); | ||
568 | |||
569 | /* note: queue implements a lock */ | ||
570 | skb_queue_tail(&pipe->io_comp_queue, skb); | ||
571 | schedule_work(&pipe->io_complete_work); | ||
572 | } | ||
573 | |||
574 | static void ath6kl_usb_io_comp_work(struct work_struct *work) | ||
575 | { | ||
576 | struct ath6kl_usb_pipe *pipe = container_of(work, | ||
577 | struct ath6kl_usb_pipe, | ||
578 | io_complete_work); | ||
579 | struct ath6kl_usb *ar_usb; | ||
580 | struct sk_buff *skb; | ||
581 | |||
582 | ar_usb = pipe->ar_usb; | ||
583 | |||
584 | while ((skb = skb_dequeue(&pipe->io_comp_queue))) { | ||
585 | if (pipe->flags & ATH6KL_USB_PIPE_FLAG_TX) { | ||
586 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
587 | "ath6kl usb xmit callback buf:0x%p\n", skb); | ||
588 | ath6kl_core_tx_complete(ar_usb->ar, skb); | ||
589 | } else { | ||
590 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
591 | "ath6kl usb recv callback buf:0x%p\n", skb); | ||
592 | ath6kl_core_rx_complete(ar_usb->ar, skb, | ||
593 | pipe->logical_pipe_num); | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | |||
58 | #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) | 598 | #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) |
59 | #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) | 599 | #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) |
60 | 600 | ||
61 | static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) | 601 | static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) |
62 | { | 602 | { |
603 | ath6kl_usb_flush_all(ar_usb); | ||
604 | |||
605 | ath6kl_usb_cleanup_pipe_resources(ar_usb); | ||
606 | |||
63 | usb_set_intfdata(ar_usb->interface, NULL); | 607 | usb_set_intfdata(ar_usb->interface, NULL); |
64 | 608 | ||
65 | kfree(ar_usb->diag_cmd_buffer); | 609 | kfree(ar_usb->diag_cmd_buffer); |
@@ -70,19 +614,28 @@ static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) | |||
70 | 614 | ||
71 | static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) | 615 | static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) |
72 | { | 616 | { |
73 | struct ath6kl_usb *ar_usb = NULL; | ||
74 | struct usb_device *dev = interface_to_usbdev(interface); | 617 | struct usb_device *dev = interface_to_usbdev(interface); |
618 | struct ath6kl_usb *ar_usb; | ||
619 | struct ath6kl_usb_pipe *pipe; | ||
75 | int status = 0; | 620 | int status = 0; |
621 | int i; | ||
76 | 622 | ||
77 | ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); | 623 | ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); |
78 | if (ar_usb == NULL) | 624 | if (ar_usb == NULL) |
79 | goto fail_ath6kl_usb_create; | 625 | goto fail_ath6kl_usb_create; |
80 | 626 | ||
81 | memset(ar_usb, 0, sizeof(struct ath6kl_usb)); | ||
82 | usb_set_intfdata(interface, ar_usb); | 627 | usb_set_intfdata(interface, ar_usb); |
628 | spin_lock_init(&(ar_usb->cs_lock)); | ||
83 | ar_usb->udev = dev; | 629 | ar_usb->udev = dev; |
84 | ar_usb->interface = interface; | 630 | ar_usb->interface = interface; |
85 | 631 | ||
632 | for (i = 0; i < ATH6KL_USB_PIPE_MAX; i++) { | ||
633 | pipe = &ar_usb->pipes[i]; | ||
634 | INIT_WORK(&pipe->io_complete_work, | ||
635 | ath6kl_usb_io_comp_work); | ||
636 | skb_queue_head_init(&pipe->io_comp_queue); | ||
637 | } | ||
638 | |||
86 | ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); | 639 | ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); |
87 | if (ar_usb->diag_cmd_buffer == NULL) { | 640 | if (ar_usb->diag_cmd_buffer == NULL) { |
88 | status = -ENOMEM; | 641 | status = -ENOMEM; |
@@ -96,6 +649,8 @@ static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) | |||
96 | goto fail_ath6kl_usb_create; | 649 | goto fail_ath6kl_usb_create; |
97 | } | 650 | } |
98 | 651 | ||
652 | status = ath6kl_usb_setup_pipe_resources(ar_usb); | ||
653 | |||
99 | fail_ath6kl_usb_create: | 654 | fail_ath6kl_usb_create: |
100 | if (status != 0) { | 655 | if (status != 0) { |
101 | ath6kl_usb_destroy(ar_usb); | 656 | ath6kl_usb_destroy(ar_usb); |
@@ -114,11 +669,177 @@ static void ath6kl_usb_device_detached(struct usb_interface *interface) | |||
114 | 669 | ||
115 | ath6kl_stop_txrx(ar_usb->ar); | 670 | ath6kl_stop_txrx(ar_usb->ar); |
116 | 671 | ||
672 | /* Delay to wait for the target to reboot */ | ||
673 | mdelay(20); | ||
117 | ath6kl_core_cleanup(ar_usb->ar); | 674 | ath6kl_core_cleanup(ar_usb->ar); |
118 | |||
119 | ath6kl_usb_destroy(ar_usb); | 675 | ath6kl_usb_destroy(ar_usb); |
120 | } | 676 | } |
121 | 677 | ||
678 | /* exported hif usb APIs for htc pipe */ | ||
679 | static void hif_start(struct ath6kl *ar) | ||
680 | { | ||
681 | struct ath6kl_usb *device = ath6kl_usb_priv(ar); | ||
682 | int i; | ||
683 | |||
684 | ath6kl_usb_start_recv_pipes(device); | ||
685 | |||
686 | /* set the TX resource avail threshold for each TX pipe */ | ||
687 | for (i = ATH6KL_USB_PIPE_TX_CTRL; | ||
688 | i <= ATH6KL_USB_PIPE_TX_DATA_HP; i++) { | ||
689 | device->pipes[i].urb_cnt_thresh = | ||
690 | device->pipes[i].urb_alloc / 2; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | static int ath6kl_usb_send(struct ath6kl *ar, u8 PipeID, | ||
695 | struct sk_buff *hdr_skb, struct sk_buff *skb) | ||
696 | { | ||
697 | struct ath6kl_usb *device = ath6kl_usb_priv(ar); | ||
698 | struct ath6kl_usb_pipe *pipe = &device->pipes[PipeID]; | ||
699 | struct ath6kl_urb_context *urb_context; | ||
700 | int usb_status, status = 0; | ||
701 | struct urb *urb; | ||
702 | u8 *data; | ||
703 | u32 len; | ||
704 | |||
705 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, "+%s pipe : %d, buf:0x%p\n", | ||
706 | __func__, PipeID, skb); | ||
707 | |||
708 | urb_context = ath6kl_usb_alloc_urb_from_pipe(pipe); | ||
709 | |||
710 | if (urb_context == NULL) { | ||
711 | /* | ||
712 | * TODO: it is possible to run out of urbs if | ||
713 | * 2 endpoints map to the same pipe ID | ||
714 | */ | ||
715 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
716 | "%s pipe:%d no urbs left. URB Cnt : %d\n", | ||
717 | __func__, PipeID, pipe->urb_cnt); | ||
718 | status = -ENOMEM; | ||
719 | goto fail_hif_send; | ||
720 | } | ||
721 | |||
722 | urb_context->skb = skb; | ||
723 | |||
724 | data = skb->data; | ||
725 | len = skb->len; | ||
726 | |||
727 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
728 | if (urb == NULL) { | ||
729 | status = -ENOMEM; | ||
730 | ath6kl_usb_free_urb_to_pipe(urb_context->pipe, | ||
731 | urb_context); | ||
732 | goto fail_hif_send; | ||
733 | } | ||
734 | |||
735 | usb_fill_bulk_urb(urb, | ||
736 | device->udev, | ||
737 | pipe->usb_pipe_handle, | ||
738 | data, | ||
739 | len, | ||
740 | ath6kl_usb_usb_transmit_complete, urb_context); | ||
741 | |||
742 | if ((len % pipe->max_packet_size) == 0) { | ||
743 | /* hit a max packet boundary on this pipe */ | ||
744 | urb->transfer_flags |= URB_ZERO_PACKET; | ||
745 | } | ||
746 | |||
747 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
748 | "athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes\n", | ||
749 | pipe->logical_pipe_num, pipe->usb_pipe_handle, | ||
750 | pipe->ep_address, len); | ||
751 | |||
752 | usb_anchor_urb(urb, &pipe->urb_submitted); | ||
753 | usb_status = usb_submit_urb(urb, GFP_ATOMIC); | ||
754 | |||
755 | if (usb_status) { | ||
756 | ath6kl_dbg(ATH6KL_DBG_USB_BULK, | ||
757 | "ath6kl usb : usb bulk transmit failed %d\n", | ||
758 | usb_status); | ||
759 | usb_unanchor_urb(urb); | ||
760 | ath6kl_usb_free_urb_to_pipe(urb_context->pipe, | ||
761 | urb_context); | ||
762 | status = -EINVAL; | ||
763 | } | ||
764 | usb_free_urb(urb); | ||
765 | |||
766 | fail_hif_send: | ||
767 | return status; | ||
768 | } | ||
769 | |||
770 | static void hif_stop(struct ath6kl *ar) | ||
771 | { | ||
772 | struct ath6kl_usb *device = ath6kl_usb_priv(ar); | ||
773 | |||
774 | ath6kl_usb_flush_all(device); | ||
775 | } | ||
776 | |||
777 | static void ath6kl_usb_get_default_pipe(struct ath6kl *ar, | ||
778 | u8 *ul_pipe, u8 *dl_pipe) | ||
779 | { | ||
780 | *ul_pipe = ATH6KL_USB_PIPE_TX_CTRL; | ||
781 | *dl_pipe = ATH6KL_USB_PIPE_RX_CTRL; | ||
782 | } | ||
783 | |||
784 | static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, | ||
785 | u8 *ul_pipe, u8 *dl_pipe) | ||
786 | { | ||
787 | int status = 0; | ||
788 | |||
789 | switch (svc_id) { | ||
790 | case HTC_CTRL_RSVD_SVC: | ||
791 | case WMI_CONTROL_SVC: | ||
792 | *ul_pipe = ATH6KL_USB_PIPE_TX_CTRL; | ||
793 | /* due to large control packets, shift to data pipe */ | ||
794 | *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; | ||
795 | break; | ||
796 | case WMI_DATA_BE_SVC: | ||
797 | case WMI_DATA_BK_SVC: | ||
798 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; | ||
799 | /* | ||
800 | * Disable rxdata2 directly, it will be enabled | ||
801 | * if FW enable rxdata2 | ||
802 | */ | ||
803 | *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; | ||
804 | break; | ||
805 | case WMI_DATA_VI_SVC: | ||
806 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; | ||
807 | /* | ||
808 | * Disable rxdata2 directly, it will be enabled | ||
809 | * if FW enable rxdata2 | ||
810 | */ | ||
811 | *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; | ||
812 | break; | ||
813 | case WMI_DATA_VO_SVC: | ||
814 | *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_HP; | ||
815 | /* | ||
816 | * Disable rxdata2 directly, it will be enabled | ||
817 | * if FW enable rxdata2 | ||
818 | */ | ||
819 | *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; | ||
820 | break; | ||
821 | default: | ||
822 | status = -EPERM; | ||
823 | break; | ||
824 | } | ||
825 | |||
826 | return status; | ||
827 | } | ||
828 | |||
829 | static u16 ath6kl_usb_get_free_queue_number(struct ath6kl *ar, u8 pipe_id) | ||
830 | { | ||
831 | struct ath6kl_usb *device = ath6kl_usb_priv(ar); | ||
832 | |||
833 | return device->pipes[pipe_id].urb_cnt; | ||
834 | } | ||
835 | |||
836 | static void hif_detach_htc(struct ath6kl *ar) | ||
837 | { | ||
838 | struct ath6kl_usb *device = ath6kl_usb_priv(ar); | ||
839 | |||
840 | ath6kl_usb_flush_all(device); | ||
841 | } | ||
842 | |||
122 | static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | 843 | static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, |
123 | u8 req, u16 value, u16 index, void *data, | 844 | u8 req, u16 value, u16 index, void *data, |
124 | u32 size) | 845 | u32 size) |
@@ -301,14 +1022,21 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | |||
301 | 1022 | ||
302 | static int ath6kl_usb_power_on(struct ath6kl *ar) | 1023 | static int ath6kl_usb_power_on(struct ath6kl *ar) |
303 | { | 1024 | { |
1025 | hif_start(ar); | ||
304 | return 0; | 1026 | return 0; |
305 | } | 1027 | } |
306 | 1028 | ||
307 | static int ath6kl_usb_power_off(struct ath6kl *ar) | 1029 | static int ath6kl_usb_power_off(struct ath6kl *ar) |
308 | { | 1030 | { |
1031 | hif_detach_htc(ar); | ||
309 | return 0; | 1032 | return 0; |
310 | } | 1033 | } |
311 | 1034 | ||
1035 | static void ath6kl_usb_stop(struct ath6kl *ar) | ||
1036 | { | ||
1037 | hif_stop(ar); | ||
1038 | } | ||
1039 | |||
312 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | 1040 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { |
313 | .diag_read32 = ath6kl_usb_diag_read32, | 1041 | .diag_read32 = ath6kl_usb_diag_read32, |
314 | .diag_write32 = ath6kl_usb_diag_write32, | 1042 | .diag_write32 = ath6kl_usb_diag_write32, |
@@ -316,6 +1044,11 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = { | |||
316 | .bmi_write = ath6kl_usb_bmi_write, | 1044 | .bmi_write = ath6kl_usb_bmi_write, |
317 | .power_on = ath6kl_usb_power_on, | 1045 | .power_on = ath6kl_usb_power_on, |
318 | .power_off = ath6kl_usb_power_off, | 1046 | .power_off = ath6kl_usb_power_off, |
1047 | .stop = ath6kl_usb_stop, | ||
1048 | .pipe_send = ath6kl_usb_send, | ||
1049 | .pipe_get_default = ath6kl_usb_get_default_pipe, | ||
1050 | .pipe_map_service = ath6kl_usb_map_service_pipe, | ||
1051 | .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, | ||
319 | }; | 1052 | }; |
320 | 1053 | ||
321 | /* ath6kl usb driver registered functions */ | 1054 | /* ath6kl usb driver registered functions */ |
@@ -368,7 +1101,7 @@ static int ath6kl_usb_probe(struct usb_interface *interface, | |||
368 | 1101 | ||
369 | ar_usb->ar = ar; | 1102 | ar_usb->ar = ar; |
370 | 1103 | ||
371 | ret = ath6kl_core_init(ar); | 1104 | ret = ath6kl_core_init(ar, ATH6KL_HTC_TYPE_PIPE); |
372 | if (ret) { | 1105 | if (ret) { |
373 | ath6kl_err("Failed to init ath6kl core: %d\n", ret); | 1106 | ath6kl_err("Failed to init ath6kl core: %d\n", ret); |
374 | goto err_core_free; | 1107 | goto err_core_free; |
@@ -392,6 +1125,46 @@ static void ath6kl_usb_remove(struct usb_interface *interface) | |||
392 | ath6kl_usb_device_detached(interface); | 1125 | ath6kl_usb_device_detached(interface); |
393 | } | 1126 | } |
394 | 1127 | ||
1128 | #ifdef CONFIG_PM | ||
1129 | |||
1130 | static int ath6kl_usb_suspend(struct usb_interface *interface, | ||
1131 | pm_message_t message) | ||
1132 | { | ||
1133 | struct ath6kl_usb *device; | ||
1134 | device = usb_get_intfdata(interface); | ||
1135 | |||
1136 | ath6kl_usb_flush_all(device); | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static int ath6kl_usb_resume(struct usb_interface *interface) | ||
1141 | { | ||
1142 | struct ath6kl_usb *device; | ||
1143 | device = usb_get_intfdata(interface); | ||
1144 | |||
1145 | ath6kl_usb_post_recv_transfers(&device->pipes[ATH6KL_USB_PIPE_RX_DATA], | ||
1146 | ATH6KL_USB_RX_BUFFER_SIZE); | ||
1147 | ath6kl_usb_post_recv_transfers(&device->pipes[ATH6KL_USB_PIPE_RX_DATA2], | ||
1148 | ATH6KL_USB_RX_BUFFER_SIZE); | ||
1149 | |||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | static int ath6kl_usb_reset_resume(struct usb_interface *intf) | ||
1154 | { | ||
1155 | if (usb_get_intfdata(intf)) | ||
1156 | ath6kl_usb_remove(intf); | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | #else | ||
1161 | |||
1162 | #define ath6kl_usb_suspend NULL | ||
1163 | #define ath6kl_usb_resume NULL | ||
1164 | #define ath6kl_usb_reset_resume NULL | ||
1165 | |||
1166 | #endif | ||
1167 | |||
395 | /* table of devices that work with this driver */ | 1168 | /* table of devices that work with this driver */ |
396 | static struct usb_device_id ath6kl_usb_ids[] = { | 1169 | static struct usb_device_id ath6kl_usb_ids[] = { |
397 | {USB_DEVICE(0x0cf3, 0x9374)}, | 1170 | {USB_DEVICE(0x0cf3, 0x9374)}, |
@@ -403,8 +1176,12 @@ MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); | |||
403 | static struct usb_driver ath6kl_usb_driver = { | 1176 | static struct usb_driver ath6kl_usb_driver = { |
404 | .name = "ath6kl_usb", | 1177 | .name = "ath6kl_usb", |
405 | .probe = ath6kl_usb_probe, | 1178 | .probe = ath6kl_usb_probe, |
1179 | .suspend = ath6kl_usb_suspend, | ||
1180 | .resume = ath6kl_usb_resume, | ||
1181 | .reset_resume = ath6kl_usb_reset_resume, | ||
406 | .disconnect = ath6kl_usb_remove, | 1182 | .disconnect = ath6kl_usb_remove, |
407 | .id_table = ath6kl_usb_ids, | 1183 | .id_table = ath6kl_usb_ids, |
1184 | .supports_autosuspend = true, | ||
408 | }; | 1185 | }; |
409 | 1186 | ||
410 | static int ath6kl_usb_init(void) | 1187 | static int ath6kl_usb_init(void) |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 2b442332cd0f..7c8a9977faf5 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -2882,6 +2882,43 @@ int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, | |||
2882 | return ret; | 2882 | return ret; |
2883 | } | 2883 | } |
2884 | 2884 | ||
2885 | int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, | ||
2886 | enum ieee80211_band band, | ||
2887 | struct ath6kl_htcap *htcap) | ||
2888 | { | ||
2889 | struct sk_buff *skb; | ||
2890 | struct wmi_set_htcap_cmd *cmd; | ||
2891 | |||
2892 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2893 | if (!skb) | ||
2894 | return -ENOMEM; | ||
2895 | |||
2896 | cmd = (struct wmi_set_htcap_cmd *) skb->data; | ||
2897 | |||
2898 | /* | ||
2899 | * NOTE: Band in firmware matches enum ieee80211_band, it is unlikely | ||
2900 | * this will be changed in firmware. If at all there is any change in | ||
2901 | * band value, the host needs to be fixed. | ||
2902 | */ | ||
2903 | cmd->band = band; | ||
2904 | cmd->ht_enable = !!htcap->ht_enable; | ||
2905 | cmd->ht20_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_20); | ||
2906 | cmd->ht40_supported = | ||
2907 | !!(htcap->cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
2908 | cmd->ht40_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_40); | ||
2909 | cmd->intolerant_40mhz = | ||
2910 | !!(htcap->cap_info & IEEE80211_HT_CAP_40MHZ_INTOLERANT); | ||
2911 | cmd->max_ampdu_len_exp = htcap->ampdu_factor; | ||
2912 | |||
2913 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
2914 | "Set htcap: band:%d ht_enable:%d 40mhz:%d sgi_20mhz:%d sgi_40mhz:%d 40mhz_intolerant:%d ampdu_len_exp:%d\n", | ||
2915 | cmd->band, cmd->ht_enable, cmd->ht40_supported, | ||
2916 | cmd->ht20_sgi, cmd->ht40_sgi, cmd->intolerant_40mhz, | ||
2917 | cmd->max_ampdu_len_exp); | ||
2918 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_HT_CAP_CMDID, | ||
2919 | NO_SYNC_WMIFLAG); | ||
2920 | } | ||
2921 | |||
2885 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) | 2922 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) |
2886 | { | 2923 | { |
2887 | struct sk_buff *skb; | 2924 | struct sk_buff *skb; |
@@ -3032,6 +3069,9 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, | |||
3032 | cm->reason = cpu_to_le16(reason); | 3069 | cm->reason = cpu_to_le16(reason); |
3033 | cm->cmd = cmd; | 3070 | cm->cmd = cmd; |
3034 | 3071 | ||
3072 | ath6kl_dbg(ATH6KL_DBG_WMI, "ap_set_mlme: cmd=%d reason=%d\n", cm->cmd, | ||
3073 | cm->reason); | ||
3074 | |||
3035 | return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID, | 3075 | return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID, |
3036 | NO_SYNC_WMIFLAG); | 3076 | NO_SYNC_WMIFLAG); |
3037 | } | 3077 | } |
@@ -3181,6 +3221,29 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | |||
3181 | NO_SYNC_WMIFLAG); | 3221 | NO_SYNC_WMIFLAG); |
3182 | } | 3222 | } |
3183 | 3223 | ||
3224 | int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field, | ||
3225 | const u8 *ie_info, u8 ie_len) | ||
3226 | { | ||
3227 | struct sk_buff *skb; | ||
3228 | struct wmi_set_ie_cmd *p; | ||
3229 | |||
3230 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len); | ||
3231 | if (!skb) | ||
3232 | return -ENOMEM; | ||
3233 | |||
3234 | ath6kl_dbg(ATH6KL_DBG_WMI, "set_ie_cmd: ie_id=%u ie_ie_field=%u ie_len=%u\n", | ||
3235 | ie_id, ie_field, ie_len); | ||
3236 | p = (struct wmi_set_ie_cmd *) skb->data; | ||
3237 | p->ie_id = ie_id; | ||
3238 | p->ie_field = ie_field; | ||
3239 | p->ie_len = ie_len; | ||
3240 | if (ie_info && ie_len > 0) | ||
3241 | memcpy(p->ie_info, ie_info, ie_len); | ||
3242 | |||
3243 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IE_CMDID, | ||
3244 | NO_SYNC_WMIFLAG); | ||
3245 | } | ||
3246 | |||
3184 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) | 3247 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) |
3185 | { | 3248 | { |
3186 | struct sk_buff *skb; | 3249 | struct sk_buff *skb; |
@@ -3392,6 +3455,23 @@ int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx) | |||
3392 | WMI_CANCEL_REMAIN_ON_CHNL_CMDID); | 3455 | WMI_CANCEL_REMAIN_ON_CHNL_CMDID); |
3393 | } | 3456 | } |
3394 | 3457 | ||
3458 | int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout) | ||
3459 | { | ||
3460 | struct sk_buff *skb; | ||
3461 | struct wmi_set_inact_period_cmd *cmd; | ||
3462 | |||
3463 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3464 | if (!skb) | ||
3465 | return -ENOMEM; | ||
3466 | |||
3467 | cmd = (struct wmi_set_inact_period_cmd *) skb->data; | ||
3468 | cmd->inact_period = cpu_to_le32(inact_timeout); | ||
3469 | cmd->num_null_func = 0; | ||
3470 | |||
3471 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_CONN_INACT_CMDID, | ||
3472 | NO_SYNC_WMIFLAG); | ||
3473 | } | ||
3474 | |||
3395 | static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) | 3475 | static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) |
3396 | { | 3476 | { |
3397 | struct wmix_cmd_hdr *cmd; | 3477 | struct wmix_cmd_hdr *cmd; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 4092e3e80790..d3d2ab5c1689 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -182,6 +182,9 @@ enum wmi_data_hdr_flags { | |||
182 | #define WMI_DATA_HDR_META_MASK 0x7 | 182 | #define WMI_DATA_HDR_META_MASK 0x7 |
183 | #define WMI_DATA_HDR_META_SHIFT 13 | 183 | #define WMI_DATA_HDR_META_SHIFT 13 |
184 | 184 | ||
185 | #define WMI_DATA_HDR_PAD_BEFORE_DATA_MASK 0xFF | ||
186 | #define WMI_DATA_HDR_PAD_BEFORE_DATA_SHIFT 0x8 | ||
187 | |||
185 | /* Macros for operating on WMI_DATA_HDR (info3) field */ | 188 | /* Macros for operating on WMI_DATA_HDR (info3) field */ |
186 | #define WMI_DATA_HDR_IF_IDX_MASK 0xF | 189 | #define WMI_DATA_HDR_IF_IDX_MASK 0xF |
187 | 190 | ||
@@ -423,6 +426,7 @@ enum wmi_cmd_id { | |||
423 | WMI_SET_FRAMERATES_CMDID, | 426 | WMI_SET_FRAMERATES_CMDID, |
424 | WMI_SET_AP_PS_CMDID, | 427 | WMI_SET_AP_PS_CMDID, |
425 | WMI_SET_QOS_SUPP_CMDID, | 428 | WMI_SET_QOS_SUPP_CMDID, |
429 | WMI_SET_IE_CMDID, | ||
426 | 430 | ||
427 | /* WMI_THIN_RESERVED_... mark the start and end | 431 | /* WMI_THIN_RESERVED_... mark the start and end |
428 | * values for WMI_THIN_RESERVED command IDs. These | 432 | * values for WMI_THIN_RESERVED command IDs. These |
@@ -629,6 +633,11 @@ enum wmi_mgmt_frame_type { | |||
629 | WMI_NUM_MGMT_FRAME | 633 | WMI_NUM_MGMT_FRAME |
630 | }; | 634 | }; |
631 | 635 | ||
636 | enum wmi_ie_field_type { | ||
637 | WMI_RSN_IE_CAPB = 0x1, | ||
638 | WMI_IE_FULL = 0xFF, /* indicats full IE */ | ||
639 | }; | ||
640 | |||
632 | /* WMI_CONNECT_CMDID */ | 641 | /* WMI_CONNECT_CMDID */ |
633 | enum network_type { | 642 | enum network_type { |
634 | INFRA_NETWORK = 0x01, | 643 | INFRA_NETWORK = 0x01, |
@@ -1268,6 +1277,16 @@ struct wmi_mcast_filter_add_del_cmd { | |||
1268 | u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | 1277 | u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; |
1269 | } __packed; | 1278 | } __packed; |
1270 | 1279 | ||
1280 | struct wmi_set_htcap_cmd { | ||
1281 | u8 band; | ||
1282 | u8 ht_enable; | ||
1283 | u8 ht40_supported; | ||
1284 | u8 ht20_sgi; | ||
1285 | u8 ht40_sgi; | ||
1286 | u8 intolerant_40mhz; | ||
1287 | u8 max_ampdu_len_exp; | ||
1288 | } __packed; | ||
1289 | |||
1271 | /* Command Replies */ | 1290 | /* Command Replies */ |
1272 | 1291 | ||
1273 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ | 1292 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ |
@@ -1913,6 +1932,14 @@ struct wmi_set_appie_cmd { | |||
1913 | u8 ie_info[0]; | 1932 | u8 ie_info[0]; |
1914 | } __packed; | 1933 | } __packed; |
1915 | 1934 | ||
1935 | struct wmi_set_ie_cmd { | ||
1936 | u8 ie_id; | ||
1937 | u8 ie_field; /* enum wmi_ie_field_type */ | ||
1938 | u8 ie_len; | ||
1939 | u8 reserved; | ||
1940 | u8 ie_info[0]; | ||
1941 | } __packed; | ||
1942 | |||
1916 | /* Notify the WSC registration status to the target */ | 1943 | /* Notify the WSC registration status to the target */ |
1917 | #define WSC_REG_ACTIVE 1 | 1944 | #define WSC_REG_ACTIVE 1 |
1918 | #define WSC_REG_INACTIVE 0 | 1945 | #define WSC_REG_INACTIVE 0 |
@@ -2141,6 +2168,11 @@ struct wmi_ap_hidden_ssid_cmd { | |||
2141 | u8 hidden_ssid; | 2168 | u8 hidden_ssid; |
2142 | } __packed; | 2169 | } __packed; |
2143 | 2170 | ||
2171 | struct wmi_set_inact_period_cmd { | ||
2172 | __le32 inact_period; | ||
2173 | u8 num_null_func; | ||
2174 | } __packed; | ||
2175 | |||
2144 | /* AP mode events */ | 2176 | /* AP mode events */ |
2145 | struct wmi_ap_set_apsd_cmd { | 2177 | struct wmi_ap_set_apsd_cmd { |
2146 | u8 enable; | 2178 | u8 enable; |
@@ -2465,6 +2497,9 @@ int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi); | |||
2465 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); | 2497 | int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg); |
2466 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, | 2498 | int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, |
2467 | u8 keep_alive_intvl); | 2499 | u8 keep_alive_intvl); |
2500 | int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, | ||
2501 | enum ieee80211_band band, | ||
2502 | struct ath6kl_htcap *htcap); | ||
2468 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); | 2503 | int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); |
2469 | 2504 | ||
2470 | s32 ath6kl_wmi_get_rate(s8 rate_index); | 2505 | s32 ath6kl_wmi_get_rate(s8 rate_index); |
@@ -2515,6 +2550,9 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx, | |||
2515 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | 2550 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, |
2516 | const u8 *ie, u8 ie_len); | 2551 | const u8 *ie, u8 ie_len); |
2517 | 2552 | ||
2553 | int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field, | ||
2554 | const u8 *ie_info, u8 ie_len); | ||
2555 | |||
2518 | /* P2P */ | 2556 | /* P2P */ |
2519 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable); | 2557 | int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable); |
2520 | 2558 | ||
@@ -2538,6 +2576,8 @@ int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx); | |||
2538 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | 2576 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, |
2539 | const u8 *ie, u8 ie_len); | 2577 | const u8 *ie, u8 ie_len); |
2540 | 2578 | ||
2579 | int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout); | ||
2580 | |||
2541 | void ath6kl_wmi_sscan_timer(unsigned long ptr); | 2581 | void ath6kl_wmi_sscan_timer(unsigned long ptr); |
2542 | 2582 | ||
2543 | struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx); | 2583 | struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx); |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 47a9fb4a116a..b4c77f9d7470 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -274,7 +274,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
274 | aniState->rssiThrLow, aniState->rssiThrHigh); | 274 | aniState->rssiThrLow, aniState->rssiThrHigh); |
275 | 275 | ||
276 | if (aniState->update_ani) | 276 | if (aniState->update_ani) |
277 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | 277 | aniState->ofdmNoiseImmunityLevel = |
278 | (immunityLevel > ATH9K_ANI_OFDM_DEF_LEVEL) ? | ||
279 | immunityLevel : ATH9K_ANI_OFDM_DEF_LEVEL; | ||
278 | 280 | ||
279 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 281 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
280 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 282 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
@@ -340,7 +342,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
340 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | 342 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; |
341 | 343 | ||
342 | if (aniState->update_ani) | 344 | if (aniState->update_ani) |
343 | aniState->cckNoiseImmunityLevel = immunityLevel; | 345 | aniState->cckNoiseImmunityLevel = |
346 | (immunityLevel > ATH9K_ANI_CCK_DEF_LEVEL) ? | ||
347 | immunityLevel : ATH9K_ANI_CCK_DEF_LEVEL; | ||
344 | 348 | ||
345 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 349 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
346 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 350 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 52ff5caf2d0b..de30cb34b8f3 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -245,7 +245,6 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
245 | REG_WRITE(ah, AR_PHY(0x37), reg32); | 245 | REG_WRITE(ah, AR_PHY(0x37), reg32); |
246 | 246 | ||
247 | ah->curchan = chan; | 247 | ah->curchan = chan; |
248 | ah->curchan_rad_index = -1; | ||
249 | 248 | ||
250 | return 0; | 249 | return 0; |
251 | } | 250 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index aa2abaf31cba..8d78253c26ce 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -136,6 +136,7 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | if (sync_cause) { | 138 | if (sync_cause) { |
139 | ath9k_debug_sync_cause(common, sync_cause); | ||
139 | fatal_int = | 140 | fatal_int = |
140 | (sync_cause & | 141 | (sync_cause & |
141 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | 142 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 3cbbb033fcea..846dd7974eb8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -152,7 +152,6 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
152 | REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); | 152 | REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); |
153 | 153 | ||
154 | ah->curchan = chan; | 154 | ah->curchan = chan; |
155 | ah->curchan_rad_index = -1; | ||
156 | 155 | ||
157 | return 0; | 156 | return 0; |
158 | } | 157 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 6bb4db052bb0..1188db205e32 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -30,11 +30,6 @@ | |||
30 | #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) | 30 | #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) |
31 | #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) | 31 | #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) |
32 | #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) | 32 | #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) |
33 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
34 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ | ||
35 | #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */ | ||
36 | #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */ | ||
37 | #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */ | ||
38 | 33 | ||
39 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ | 34 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ |
40 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ | 35 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ |
@@ -2936,15 +2931,6 @@ static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id) | |||
2936 | #undef N_LOOP | 2931 | #undef N_LOOP |
2937 | } | 2932 | } |
2938 | 2933 | ||
2939 | |||
2940 | static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | ||
2941 | { | ||
2942 | if (fbin == AR5416_BCHAN_UNUSED) | ||
2943 | return fbin; | ||
2944 | |||
2945 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
2946 | } | ||
2947 | |||
2948 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) | 2934 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) |
2949 | { | 2935 | { |
2950 | return 0; | 2936 | return 0; |
@@ -4070,7 +4056,7 @@ static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah, | |||
4070 | * targetpower piers stored on eeprom | 4056 | * targetpower piers stored on eeprom |
4071 | */ | 4057 | */ |
4072 | for (i = 0; i < numPiers; i++) { | 4058 | for (i = 0; i < numPiers; i++) { |
4073 | freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); | 4059 | freqArray[i] = ath9k_hw_fbin2freq(pFreqBin[i], is2GHz); |
4074 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; | 4060 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; |
4075 | } | 4061 | } |
4076 | 4062 | ||
@@ -4106,7 +4092,7 @@ static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah, | |||
4106 | * from targetpower piers stored on eeprom | 4092 | * from targetpower piers stored on eeprom |
4107 | */ | 4093 | */ |
4108 | for (i = 0; i < numPiers; i++) { | 4094 | for (i = 0; i < numPiers; i++) { |
4109 | freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); | 4095 | freqArray[i] = ath9k_hw_fbin2freq(pFreqBin[i], is2GHz); |
4110 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; | 4096 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; |
4111 | } | 4097 | } |
4112 | 4098 | ||
@@ -4142,7 +4128,7 @@ static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah, | |||
4142 | * targetpower piers stored on eeprom | 4128 | * targetpower piers stored on eeprom |
4143 | */ | 4129 | */ |
4144 | for (i = 0; i < numPiers; i++) { | 4130 | for (i = 0; i < numPiers; i++) { |
4145 | freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); | 4131 | freqArray[i] = ath9k_hw_fbin2freq(pFreqBin[i], is2GHz); |
4146 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; | 4132 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; |
4147 | } | 4133 | } |
4148 | 4134 | ||
@@ -4167,7 +4153,7 @@ static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah, | |||
4167 | * targetpower piers stored on eeprom | 4153 | * targetpower piers stored on eeprom |
4168 | */ | 4154 | */ |
4169 | for (i = 0; i < numPiers; i++) { | 4155 | for (i = 0; i < numPiers; i++) { |
4170 | freqArray[i] = FBIN2FREQ(pFreqBin[i], 1); | 4156 | freqArray[i] = ath9k_hw_fbin2freq(pFreqBin[i], 1); |
4171 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; | 4157 | targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; |
4172 | } | 4158 | } |
4173 | 4159 | ||
@@ -4464,7 +4450,7 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
4464 | is2GHz = 1; | 4450 | is2GHz = 1; |
4465 | } | 4451 | } |
4466 | 4452 | ||
4467 | *pfrequency = FBIN2FREQ(*pCalPier, is2GHz); | 4453 | *pfrequency = ath9k_hw_fbin2freq(*pCalPier, is2GHz); |
4468 | *pcorrection = pCalPierStruct->refPower; | 4454 | *pcorrection = pCalPierStruct->refPower; |
4469 | *ptemperature = pCalPierStruct->tempMeas; | 4455 | *ptemperature = pCalPierStruct->tempMeas; |
4470 | *pvoltage = pCalPierStruct->voltMeas; | 4456 | *pvoltage = pCalPierStruct->voltMeas; |
@@ -4789,30 +4775,8 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
4789 | bool is2ghz = IS_CHAN_2GHZ(chan); | 4775 | bool is2ghz = IS_CHAN_2GHZ(chan); |
4790 | 4776 | ||
4791 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 4777 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
4792 | scaledPower = powerLimit - antenna_reduction; | 4778 | scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit, |
4793 | 4779 | antenna_reduction); | |
4794 | /* | ||
4795 | * Reduce scaled Power by number of chains active to get | ||
4796 | * to per chain tx power level | ||
4797 | */ | ||
4798 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
4799 | case 1: | ||
4800 | break; | ||
4801 | case 2: | ||
4802 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) | ||
4803 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
4804 | else | ||
4805 | scaledPower = 0; | ||
4806 | break; | ||
4807 | case 3: | ||
4808 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) | ||
4809 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
4810 | else | ||
4811 | scaledPower = 0; | ||
4812 | break; | ||
4813 | } | ||
4814 | |||
4815 | scaledPower = max((u16)0, scaledPower); | ||
4816 | 4780 | ||
4817 | /* | 4781 | /* |
4818 | * Get target powers from EEPROM - our baseline for TX Power | 4782 | * Get target powers from EEPROM - our baseline for TX Power |
@@ -5060,8 +5024,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, | |||
5060 | i, targetPowerValT2[i]); | 5024 | i, targetPowerValT2[i]); |
5061 | } | 5025 | } |
5062 | 5026 | ||
5063 | ah->txpower_limit = regulatory->max_power_level; | ||
5064 | |||
5065 | /* Write target power array to registers */ | 5027 | /* Write target power array to registers */ |
5066 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | 5028 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); |
5067 | ar9003_hw_calibration_apply(ah, chan->channel); | 5029 | ar9003_hw_calibration_apply(ah, chan->channel); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index bb223fe82816..2505ac44f0c1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -42,7 +42,6 @@ | |||
42 | #define AR9300_EEPMISC_WOW 0x02 | 42 | #define AR9300_EEPMISC_WOW 0x02 |
43 | #define AR9300_CUSTOMER_DATA_SIZE 20 | 43 | #define AR9300_CUSTOMER_DATA_SIZE 20 |
44 | 44 | ||
45 | #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) | ||
46 | #define AR9300_MAX_CHAINS 3 | 45 | #define AR9300_MAX_CHAINS 3 |
47 | #define AR9300_ANT_16S 25 | 46 | #define AR9300_ANT_16S 25 |
48 | #define AR9300_FUTURE_MODAL_SZ 6 | 47 | #define AR9300_FUTURE_MODAL_SZ 6 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 0f56e322dd3b..a0e3394b10dc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -305,11 +305,6 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
305 | ar9462_common_rx_gain_table_2p0, | 305 | ar9462_common_rx_gain_table_2p0, |
306 | ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2); | 306 | ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2); |
307 | 307 | ||
308 | INIT_INI_ARRAY(&ah->ini_BTCOEX_MAX_TXPWR, | ||
309 | ar9462_2p0_BTCOEX_MAX_TXPWR_table, | ||
310 | ARRAY_SIZE(ar9462_2p0_BTCOEX_MAX_TXPWR_table), | ||
311 | 2); | ||
312 | |||
313 | /* Awake -> Sleep Setting */ | 308 | /* Awake -> Sleep Setting */ |
314 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 309 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
315 | PCIE_PLL_ON_CREQ_DIS_L1_2P0, | 310 | PCIE_PLL_ON_CREQ_DIS_L1_2P0, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index a66a13b76848..d9e0824af093 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -306,6 +306,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
306 | ar9003_mci_get_isr(ah, masked); | 306 | ar9003_mci_get_isr(ah, masked); |
307 | 307 | ||
308 | if (sync_cause) { | 308 | if (sync_cause) { |
309 | ath9k_debug_sync_cause(common, sync_cause); | ||
310 | |||
309 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | 311 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { |
310 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | 312 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); |
311 | REG_WRITE(ah, AR_RC, 0); | 313 | REG_WRITE(ah, AR_RC, 0); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 79070bf04eab..bbda25f4e9f0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -152,7 +152,6 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
152 | REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); | 152 | REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); |
153 | 153 | ||
154 | ah->curchan = chan; | 154 | ah->curchan = chan; |
155 | ah->curchan_rad_index = -1; | ||
156 | 155 | ||
157 | return 0; | 156 | return 0; |
158 | } | 157 | } |
@@ -209,11 +208,12 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | |||
209 | continue; | 208 | continue; |
210 | negative = 0; | 209 | negative = 0; |
211 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) | 210 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) |
212 | cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], | 211 | cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i], |
213 | IS_CHAN_2GHZ(chan)) - synth_freq; | 212 | IS_CHAN_2GHZ(chan)); |
214 | else | 213 | else |
215 | cur_bb_spur = spur_freq[i] - synth_freq; | 214 | cur_bb_spur = spur_freq[i]; |
216 | 215 | ||
216 | cur_bb_spur -= synth_freq; | ||
217 | if (cur_bb_spur < 0) { | 217 | if (cur_bb_spur < 0) { |
218 | negative = 1; | 218 | negative = 1; |
219 | cur_bb_spur = -cur_bb_spur; | 219 | cur_bb_spur = -cur_bb_spur; |
@@ -443,7 +443,8 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, | |||
443 | ar9003_hw_spur_ofdm_clear(ah); | 443 | ar9003_hw_spur_ofdm_clear(ah); |
444 | 444 | ||
445 | for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { | 445 | for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { |
446 | freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; | 446 | freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i], mode); |
447 | freq_offset -= synth_freq; | ||
447 | if (abs(freq_offset) < range) { | 448 | if (abs(freq_offset) < range) { |
448 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); | 449 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); |
449 | break; | 450 | break; |
@@ -684,9 +685,6 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
684 | 685 | ||
685 | REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites); | 686 | REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites); |
686 | 687 | ||
687 | if (AR_SREV_9462(ah)) | ||
688 | ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1); | ||
689 | |||
690 | if (chan->channel == 2484) | 688 | if (chan->channel == 2484) |
691 | ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); | 689 | ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); |
692 | 690 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index b6ba1e8149be..1d6658e139b5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -1115,9 +1115,9 @@ static const u32 ar9462_2p0_mac_core[][2] = { | |||
1115 | {0x000081f8, 0x00000000}, | 1115 | {0x000081f8, 0x00000000}, |
1116 | {0x000081fc, 0x00000000}, | 1116 | {0x000081fc, 0x00000000}, |
1117 | {0x00008240, 0x00100000}, | 1117 | {0x00008240, 0x00100000}, |
1118 | {0x00008244, 0x0010f400}, | 1118 | {0x00008244, 0x0010f424}, |
1119 | {0x00008248, 0x00000800}, | 1119 | {0x00008248, 0x00000800}, |
1120 | {0x0000824c, 0x0001e800}, | 1120 | {0x0000824c, 0x0001e848}, |
1121 | {0x00008250, 0x00000000}, | 1121 | {0x00008250, 0x00000000}, |
1122 | {0x00008254, 0x00000000}, | 1122 | {0x00008254, 0x00000000}, |
1123 | {0x00008258, 0x00000000}, | 1123 | {0x00008258, 0x00000000}, |
@@ -1448,16 +1448,4 @@ static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = { | |||
1448 | {0x0000b1fc, 0x00000196}, | 1448 | {0x0000b1fc, 0x00000196}, |
1449 | }; | 1449 | }; |
1450 | 1450 | ||
1451 | static const u32 ar9462_2p0_BTCOEX_MAX_TXPWR_table[][2] = { | ||
1452 | /* Addr allmodes */ | ||
1453 | {0x000018c0, 0x10101010}, | ||
1454 | {0x000018c4, 0x10101010}, | ||
1455 | {0x000018c8, 0x10101010}, | ||
1456 | {0x000018cc, 0x10101010}, | ||
1457 | {0x000018d0, 0x10101010}, | ||
1458 | {0x000018d4, 0x10101010}, | ||
1459 | {0x000018d8, 0x10101010}, | ||
1460 | {0x000018dc, 0x10101010}, | ||
1461 | }; | ||
1462 | |||
1463 | #endif /* INITVALS_9462_2P0_H */ | 1451 | #endif /* INITVALS_9462_2P0_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0a37631390db..a277cf6f339d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -370,7 +370,7 @@ struct ath_vif { | |||
370 | * number of beacon intervals, the game's up. | 370 | * number of beacon intervals, the game's up. |
371 | */ | 371 | */ |
372 | #define BSTUCK_THRESH 9 | 372 | #define BSTUCK_THRESH 9 |
373 | #define ATH_BCBUF 4 | 373 | #define ATH_BCBUF 8 |
374 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ | 374 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ |
375 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 375 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
376 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | 376 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 626418222c85..702e5abc38b2 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
91 | info.txpower = MAX_RATE_POWER; | 91 | info.txpower = MAX_RATE_POWER; |
92 | info.keyix = ATH9K_TXKEYIX_INVALID; | 92 | info.keyix = ATH9K_TXKEYIX_INVALID; |
93 | info.keytype = ATH9K_KEY_TYPE_CLEAR; | 93 | info.keytype = ATH9K_KEY_TYPE_CLEAR; |
94 | info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ; | 94 | info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK; |
95 | 95 | ||
96 | info.buf_addr[0] = bf->bf_buf_addr; | 96 | info.buf_addr[0] = bf->bf_buf_addr; |
97 | info.buf_len[0] = roundup(skb->len, 4); | 97 | info.buf_len[0] = roundup(skb->len, 4); |
@@ -359,6 +359,11 @@ void ath_beacon_tasklet(unsigned long data) | |||
359 | int slot; | 359 | int slot; |
360 | u32 bfaddr, bc = 0; | 360 | u32 bfaddr, bc = 0; |
361 | 361 | ||
362 | if (work_pending(&sc->hw_reset_work)) { | ||
363 | ath_dbg(common, RESET, | ||
364 | "reset work is pending, skip beaconing now\n"); | ||
365 | return; | ||
366 | } | ||
362 | /* | 367 | /* |
363 | * Check if the previous beacon has gone out. If | 368 | * Check if the previous beacon has gone out. If |
364 | * not don't try to post another, skip this period | 369 | * not don't try to post another, skip this period |
@@ -369,6 +374,9 @@ void ath_beacon_tasklet(unsigned long data) | |||
369 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { | 374 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { |
370 | sc->beacon.bmisscnt++; | 375 | sc->beacon.bmisscnt++; |
371 | 376 | ||
377 | if (!ath9k_hw_check_alive(ah)) | ||
378 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
379 | |||
372 | if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { | 380 | if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { |
373 | ath_dbg(common, BSTUCK, | 381 | ath_dbg(common, BSTUCK, |
374 | "missed %u consecutive beacons\n", | 382 | "missed %u consecutive beacons\n", |
@@ -378,6 +386,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
378 | ath9k_hw_bstuck_nfcal(ah); | 386 | ath9k_hw_bstuck_nfcal(ah); |
379 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 387 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
380 | ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); | 388 | ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); |
389 | sc->beacon.bmisscnt = 0; | ||
381 | sc->sc_flags |= SC_OP_TSF_RESET; | 390 | sc->sc_flags |= SC_OP_TSF_RESET; |
382 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 391 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
383 | } | 392 | } |
@@ -650,6 +659,8 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
650 | u32 tsf, intval, nexttbtt; | 659 | u32 tsf, intval, nexttbtt; |
651 | 660 | ||
652 | ath9k_reset_beacon_status(sc); | 661 | ath9k_reset_beacon_status(sc); |
662 | if (!(sc->sc_flags & SC_OP_BEACONS)) | ||
663 | ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp); | ||
653 | 664 | ||
654 | intval = TU_TO_USEC(conf->beacon_interval); | 665 | intval = TU_TO_USEC(conf->beacon_interval); |
655 | tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval); | 666 | tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 04edce941cb7..fde700c4e490 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -380,63 +380,75 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
380 | size_t count, loff_t *ppos) | 380 | size_t count, loff_t *ppos) |
381 | { | 381 | { |
382 | struct ath_softc *sc = file->private_data; | 382 | struct ath_softc *sc = file->private_data; |
383 | char buf[512]; | ||
384 | unsigned int len = 0; | 383 | unsigned int len = 0; |
384 | int rv; | ||
385 | int mxlen = 4000; | ||
386 | char *buf = kmalloc(mxlen, GFP_KERNEL); | ||
387 | if (!buf) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | #define PR_IS(a, s) \ | ||
391 | do { \ | ||
392 | len += snprintf(buf + len, mxlen - len, \ | ||
393 | "%21s: %10u\n", a, \ | ||
394 | sc->debug.stats.istats.s); \ | ||
395 | } while (0) | ||
385 | 396 | ||
386 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 397 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
387 | len += snprintf(buf + len, sizeof(buf) - len, | 398 | PR_IS("RXLP", rxlp); |
388 | "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); | 399 | PR_IS("RXHP", rxhp); |
389 | len += snprintf(buf + len, sizeof(buf) - len, | 400 | PR_IS("WATHDOG", bb_watchdog); |
390 | "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); | ||
391 | len += snprintf(buf + len, sizeof(buf) - len, | ||
392 | "%8s: %10u\n", "WATCHDOG", | ||
393 | sc->debug.stats.istats.bb_watchdog); | ||
394 | } else { | 401 | } else { |
395 | len += snprintf(buf + len, sizeof(buf) - len, | 402 | PR_IS("RX", rxok); |
396 | "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); | ||
397 | } | 403 | } |
398 | len += snprintf(buf + len, sizeof(buf) - len, | 404 | PR_IS("RXEOL", rxeol); |
399 | "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); | 405 | PR_IS("RXORN", rxorn); |
400 | len += snprintf(buf + len, sizeof(buf) - len, | 406 | PR_IS("TX", txok); |
401 | "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); | 407 | PR_IS("TXURN", txurn); |
402 | len += snprintf(buf + len, sizeof(buf) - len, | 408 | PR_IS("MIB", mib); |
403 | "%8s: %10u\n", "TX", sc->debug.stats.istats.txok); | 409 | PR_IS("RXPHY", rxphyerr); |
404 | len += snprintf(buf + len, sizeof(buf) - len, | 410 | PR_IS("RXKCM", rx_keycache_miss); |
405 | "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); | 411 | PR_IS("SWBA", swba); |
406 | len += snprintf(buf + len, sizeof(buf) - len, | 412 | PR_IS("BMISS", bmiss); |
407 | "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); | 413 | PR_IS("BNR", bnr); |
408 | len += snprintf(buf + len, sizeof(buf) - len, | 414 | PR_IS("CST", cst); |
409 | "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); | 415 | PR_IS("GTT", gtt); |
410 | len += snprintf(buf + len, sizeof(buf) - len, | 416 | PR_IS("TIM", tim); |
411 | "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); | 417 | PR_IS("CABEND", cabend); |
412 | len += snprintf(buf + len, sizeof(buf) - len, | 418 | PR_IS("DTIMSYNC", dtimsync); |
413 | "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); | 419 | PR_IS("DTIM", dtim); |
414 | len += snprintf(buf + len, sizeof(buf) - len, | 420 | PR_IS("TSFOOR", tsfoor); |
415 | "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); | 421 | PR_IS("TOTAL", total); |
416 | len += snprintf(buf + len, sizeof(buf) - len, | 422 | |
417 | "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); | 423 | len += snprintf(buf + len, mxlen - len, |
418 | len += snprintf(buf + len, sizeof(buf) - len, | 424 | "SYNC_CAUSE stats:\n"); |
419 | "%8s: %10u\n", "CST", sc->debug.stats.istats.cst); | 425 | |
420 | len += snprintf(buf + len, sizeof(buf) - len, | 426 | PR_IS("Sync-All", sync_cause_all); |
421 | "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); | 427 | PR_IS("RTC-IRQ", sync_rtc_irq); |
422 | len += snprintf(buf + len, sizeof(buf) - len, | 428 | PR_IS("MAC-IRQ", sync_mac_irq); |
423 | "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); | 429 | PR_IS("EEPROM-Illegal-Access", eeprom_illegal_access); |
424 | len += snprintf(buf + len, sizeof(buf) - len, | 430 | PR_IS("APB-Timeout", apb_timeout); |
425 | "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); | 431 | PR_IS("PCI-Mode-Conflict", pci_mode_conflict); |
426 | len += snprintf(buf + len, sizeof(buf) - len, | 432 | PR_IS("HOST1-Fatal", host1_fatal); |
427 | "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); | 433 | PR_IS("HOST1-Perr", host1_perr); |
428 | len += snprintf(buf + len, sizeof(buf) - len, | 434 | PR_IS("TRCV-FIFO-Perr", trcv_fifo_perr); |
429 | "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); | 435 | PR_IS("RADM-CPL-EP", radm_cpl_ep); |
430 | len += snprintf(buf + len, sizeof(buf) - len, | 436 | PR_IS("RADM-CPL-DLLP-Abort", radm_cpl_dllp_abort); |
431 | "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); | 437 | PR_IS("RADM-CPL-TLP-Abort", radm_cpl_tlp_abort); |
432 | len += snprintf(buf + len, sizeof(buf) - len, | 438 | PR_IS("RADM-CPL-ECRC-Err", radm_cpl_ecrc_err); |
433 | "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); | 439 | PR_IS("RADM-CPL-Timeout", radm_cpl_timeout); |
434 | 440 | PR_IS("Local-Bus-Timeout", local_timeout); | |
435 | 441 | PR_IS("PM-Access", pm_access); | |
436 | if (len > sizeof(buf)) | 442 | PR_IS("MAC-Awake", mac_awake); |
437 | len = sizeof(buf); | 443 | PR_IS("MAC-Asleep", mac_asleep); |
438 | 444 | PR_IS("MAC-Sleep-Access", mac_sleep_access); | |
439 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 445 | |
446 | if (len > mxlen) | ||
447 | len = mxlen; | ||
448 | |||
449 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
450 | kfree(buf); | ||
451 | return rv; | ||
440 | } | 452 | } |
441 | 453 | ||
442 | static const struct file_operations fops_interrupt = { | 454 | static const struct file_operations fops_interrupt = { |
@@ -881,6 +893,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
881 | len += snprintf(buf + len, size - len, "%22s : %10u\n", s, \ | 893 | len += snprintf(buf + len, size - len, "%22s : %10u\n", s, \ |
882 | sc->debug.stats.rxstats.phy_err_stats[p]); | 894 | sc->debug.stats.rxstats.phy_err_stats[p]); |
883 | 895 | ||
896 | #define RXS_ERR(s, e) \ | ||
897 | do { \ | ||
898 | len += snprintf(buf + len, size - len, \ | ||
899 | "%22s : %10u\n", s, \ | ||
900 | sc->debug.stats.rxstats.e); \ | ||
901 | } while (0) | ||
902 | |||
884 | struct ath_softc *sc = file->private_data; | 903 | struct ath_softc *sc = file->private_data; |
885 | char *buf; | 904 | char *buf; |
886 | unsigned int len = 0, size = 1600; | 905 | unsigned int len = 0, size = 1600; |
@@ -890,42 +909,18 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
890 | if (buf == NULL) | 909 | if (buf == NULL) |
891 | return -ENOMEM; | 910 | return -ENOMEM; |
892 | 911 | ||
893 | len += snprintf(buf + len, size - len, | 912 | RXS_ERR("CRC ERR", crc_err); |
894 | "%22s : %10u\n", "CRC ERR", | 913 | RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err); |
895 | sc->debug.stats.rxstats.crc_err); | 914 | RXS_ERR("PHY ERR", phy_err); |
896 | len += snprintf(buf + len, size - len, | 915 | RXS_ERR("MIC ERR", mic_err); |
897 | "%22s : %10u\n", "DECRYPT CRC ERR", | 916 | RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err); |
898 | sc->debug.stats.rxstats.decrypt_crc_err); | 917 | RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err); |
899 | len += snprintf(buf + len, size - len, | 918 | RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err); |
900 | "%22s : %10u\n", "PHY ERR", | 919 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); |
901 | sc->debug.stats.rxstats.phy_err); | 920 | RXS_ERR("RX-OOM-ERR", rx_oom_err); |
902 | len += snprintf(buf + len, size - len, | 921 | RXS_ERR("RX-RATE-ERR", rx_rate_err); |
903 | "%22s : %10u\n", "MIC ERR", | 922 | RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); |
904 | sc->debug.stats.rxstats.mic_err); | 923 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); |
905 | len += snprintf(buf + len, size - len, | ||
906 | "%22s : %10u\n", "PRE-DELIM CRC ERR", | ||
907 | sc->debug.stats.rxstats.pre_delim_crc_err); | ||
908 | len += snprintf(buf + len, size - len, | ||
909 | "%22s : %10u\n", "POST-DELIM CRC ERR", | ||
910 | sc->debug.stats.rxstats.post_delim_crc_err); | ||
911 | len += snprintf(buf + len, size - len, | ||
912 | "%22s : %10u\n", "DECRYPT BUSY ERR", | ||
913 | sc->debug.stats.rxstats.decrypt_busy_err); | ||
914 | len += snprintf(buf + len, size - len, | ||
915 | "%22s : %10u\n", "RX-LENGTH-ERR", | ||
916 | sc->debug.stats.rxstats.rx_len_err); | ||
917 | len += snprintf(buf + len, size - len, | ||
918 | "%22s : %10u\n", "RX-OOM-ERR", | ||
919 | sc->debug.stats.rxstats.rx_oom_err); | ||
920 | len += snprintf(buf + len, size - len, | ||
921 | "%22s : %10u\n", "RX-RATE-ERR", | ||
922 | sc->debug.stats.rxstats.rx_rate_err); | ||
923 | len += snprintf(buf + len, size - len, | ||
924 | "%22s : %10u\n", "RX-DROP-RXFLUSH", | ||
925 | sc->debug.stats.rxstats.rx_drop_rxflush); | ||
926 | len += snprintf(buf + len, size - len, | ||
927 | "%22s : %10u\n", "RX-TOO-MANY-FRAGS", | ||
928 | sc->debug.stats.rxstats.rx_too_many_frags_err); | ||
929 | 924 | ||
930 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | 925 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); |
931 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | 926 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); |
@@ -954,18 +949,10 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
954 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | 949 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
955 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | 950 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); |
956 | 951 | ||
957 | len += snprintf(buf + len, size - len, | 952 | RXS_ERR("RX-Pkts-All", rx_pkts_all); |
958 | "%22s : %10u\n", "RX-Pkts-All", | 953 | RXS_ERR("RX-Bytes-All", rx_bytes_all); |
959 | sc->debug.stats.rxstats.rx_pkts_all); | 954 | RXS_ERR("RX-Beacons", rx_beacons); |
960 | len += snprintf(buf + len, size - len, | 955 | RXS_ERR("RX-Frags", rx_frags); |
961 | "%22s : %10u\n", "RX-Bytes-All", | ||
962 | sc->debug.stats.rxstats.rx_bytes_all); | ||
963 | len += snprintf(buf + len, size - len, | ||
964 | "%22s : %10u\n", "RX-Beacons", | ||
965 | sc->debug.stats.rxstats.rx_beacons); | ||
966 | len += snprintf(buf + len, size - len, | ||
967 | "%22s : %10u\n", "RX-Frags", | ||
968 | sc->debug.stats.rxstats.rx_frags); | ||
969 | 956 | ||
970 | if (len > size) | 957 | if (len > size) |
971 | len = size; | 958 | len = size; |
@@ -975,6 +962,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
975 | 962 | ||
976 | return retval; | 963 | return retval; |
977 | 964 | ||
965 | #undef RXS_ERR | ||
978 | #undef PHY_ERR | 966 | #undef PHY_ERR |
979 | } | 967 | } |
980 | 968 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 17f6cc27af32..c34da09d9103 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -60,6 +60,7 @@ struct ath_buf; | |||
60 | * @tsfoor: TSF out of range, indicates that the corrected TSF received | 60 | * @tsfoor: TSF out of range, indicates that the corrected TSF received |
61 | * from a beacon differs from the PCU's internal TSF by more than a | 61 | * from a beacon differs from the PCU's internal TSF by more than a |
62 | * (programmable) threshold | 62 | * (programmable) threshold |
63 | * @local_timeout: Internal bus timeout. | ||
63 | */ | 64 | */ |
64 | struct ath_interrupt_stats { | 65 | struct ath_interrupt_stats { |
65 | u32 total; | 66 | u32 total; |
@@ -85,8 +86,30 @@ struct ath_interrupt_stats { | |||
85 | u32 dtim; | 86 | u32 dtim; |
86 | u32 bb_watchdog; | 87 | u32 bb_watchdog; |
87 | u32 tsfoor; | 88 | u32 tsfoor; |
89 | |||
90 | /* Sync-cause stats */ | ||
91 | u32 sync_cause_all; | ||
92 | u32 sync_rtc_irq; | ||
93 | u32 sync_mac_irq; | ||
94 | u32 eeprom_illegal_access; | ||
95 | u32 apb_timeout; | ||
96 | u32 pci_mode_conflict; | ||
97 | u32 host1_fatal; | ||
98 | u32 host1_perr; | ||
99 | u32 trcv_fifo_perr; | ||
100 | u32 radm_cpl_ep; | ||
101 | u32 radm_cpl_dllp_abort; | ||
102 | u32 radm_cpl_tlp_abort; | ||
103 | u32 radm_cpl_ecrc_err; | ||
104 | u32 radm_cpl_timeout; | ||
105 | u32 local_timeout; | ||
106 | u32 pm_access; | ||
107 | u32 mac_awake; | ||
108 | u32 mac_asleep; | ||
109 | u32 mac_sleep_access; | ||
88 | }; | 110 | }; |
89 | 111 | ||
112 | |||
90 | /** | 113 | /** |
91 | * struct ath_tx_stats - Statistics about TX | 114 | * struct ath_tx_stats - Statistics about TX |
92 | * @tx_pkts_all: No. of total frames transmitted, including ones that | 115 | * @tx_pkts_all: No. of total frames transmitted, including ones that |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index c43523233319..0512397a293c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -16,14 +16,6 @@ | |||
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | ||
20 | { | ||
21 | if (fbin == AR5416_BCHAN_UNUSED) | ||
22 | return fbin; | ||
23 | |||
24 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
25 | } | ||
26 | |||
27 | void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val) | 19 | void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val) |
28 | { | 20 | { |
29 | REG_WRITE(ah, reg, val); | 21 | REG_WRITE(ah, reg, val); |
@@ -290,6 +282,34 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | |||
290 | return twiceMaxEdgePower; | 282 | return twiceMaxEdgePower; |
291 | } | 283 | } |
292 | 284 | ||
285 | u16 ath9k_hw_get_scaled_power(struct ath_hw *ah, u16 power_limit, | ||
286 | u8 antenna_reduction) | ||
287 | { | ||
288 | u16 reduction = antenna_reduction; | ||
289 | |||
290 | /* | ||
291 | * Reduce scaled Power by number of chains active | ||
292 | * to get the per chain tx power level. | ||
293 | */ | ||
294 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
295 | case 1: | ||
296 | break; | ||
297 | case 2: | ||
298 | reduction += POWER_CORRECTION_FOR_TWO_CHAIN; | ||
299 | break; | ||
300 | case 3: | ||
301 | reduction += POWER_CORRECTION_FOR_THREE_CHAIN; | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | if (power_limit > reduction) | ||
306 | power_limit -= reduction; | ||
307 | else | ||
308 | power_limit = 0; | ||
309 | |||
310 | return power_limit; | ||
311 | } | ||
312 | |||
293 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) | 313 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) |
294 | { | 314 | { |
295 | struct ath_common *common = ath9k_hw_common(ah); | 315 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -299,10 +319,10 @@ void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) | |||
299 | case 1: | 319 | case 1: |
300 | break; | 320 | break; |
301 | case 2: | 321 | case 2: |
302 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | 322 | regulatory->max_power_level += POWER_CORRECTION_FOR_TWO_CHAIN; |
303 | break; | 323 | break; |
304 | case 3: | 324 | case 3: |
305 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | 325 | regulatory->max_power_level += POWER_CORRECTION_FOR_THREE_CHAIN; |
306 | break; | 326 | break; |
307 | default: | 327 | default: |
308 | ath_dbg(common, EEPROM, "Invalid chainmask configuration\n"); | 328 | ath_dbg(common, EEPROM, "Invalid chainmask configuration\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 5ff7ab965120..33acb920ed3f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -79,8 +79,8 @@ | |||
79 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 | 79 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 |
80 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 | 80 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 |
81 | 81 | ||
82 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | 82 | #define POWER_CORRECTION_FOR_TWO_CHAIN 6 /* 10*log10(2)*2 */ |
83 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | 83 | #define POWER_CORRECTION_FOR_THREE_CHAIN 10 /* 10*log10(3)*2 */ |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * For AR9285 and later chipsets, the following bits are not being programmed | 86 | * For AR9285 and later chipsets, the following bits are not being programmed |
@@ -686,6 +686,8 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, | |||
686 | u16 numRates, bool isHt40Target); | 686 | u16 numRates, bool isHt40Target); |
687 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | 687 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, |
688 | bool is2GHz, int num_band_edges); | 688 | bool is2GHz, int num_band_edges); |
689 | u16 ath9k_hw_get_scaled_power(struct ath_hw *ah, u16 power_limit, | ||
690 | u8 antenna_reduction); | ||
689 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); | 691 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); |
690 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | 692 | int ath9k_hw_eeprom_init(struct ath_hw *ah); |
691 | 693 | ||
@@ -697,6 +699,14 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
697 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | 699 | u16 *pPdGainBoundaries, u8 *pPDADCValues, |
698 | u16 numXpdGains); | 700 | u16 numXpdGains); |
699 | 701 | ||
702 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | ||
703 | { | ||
704 | if (fbin == AR5416_BCHAN_UNUSED) | ||
705 | return fbin; | ||
706 | |||
707 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
708 | } | ||
709 | |||
700 | #define ar5416_get_ntxchains(_txchainmask) \ | 710 | #define ar5416_get_ntxchains(_txchainmask) \ |
701 | (((_txchainmask >> 2) & 1) + \ | 711 | (((_txchainmask >> 2) & 1) + \ |
702 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | 712 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index f272236d8053..5ab0e6ed4655 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -564,9 +564,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
564 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | 564 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ |
565 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) | 565 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) |
566 | 566 | ||
567 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | ||
568 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | ||
569 | |||
570 | u16 twiceMaxEdgePower; | 567 | u16 twiceMaxEdgePower; |
571 | int i; | 568 | int i; |
572 | struct cal_ctl_data_ar9287 *rep; | 569 | struct cal_ctl_data_ar9287 *rep; |
@@ -591,29 +588,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
591 | tx_chainmask = ah->txchainmask; | 588 | tx_chainmask = ah->txchainmask; |
592 | 589 | ||
593 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 590 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
594 | scaledPower = powerLimit - antenna_reduction; | 591 | scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit, |
595 | 592 | antenna_reduction); | |
596 | /* | ||
597 | * Reduce scaled Power by number of chains active | ||
598 | * to get the per chain tx power level. | ||
599 | */ | ||
600 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
601 | case 1: | ||
602 | break; | ||
603 | case 2: | ||
604 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) | ||
605 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
606 | else | ||
607 | scaledPower = 0; | ||
608 | break; | ||
609 | case 3: | ||
610 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) | ||
611 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
612 | else | ||
613 | scaledPower = 0; | ||
614 | break; | ||
615 | } | ||
616 | scaledPower = max((u16)0, scaledPower); | ||
617 | 593 | ||
618 | /* | 594 | /* |
619 | * Get TX power from EEPROM. | 595 | * Get TX power from EEPROM. |
@@ -786,8 +762,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
786 | 762 | ||
787 | #undef CMP_CTL | 763 | #undef CMP_CTL |
788 | #undef CMP_NO_CTL | 764 | #undef CMP_NO_CTL |
789 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | ||
790 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | ||
791 | } | 765 | } |
792 | 766 | ||
793 | static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | 767 | static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 619b95d764ff..b5fba8b18b8b 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -991,9 +991,6 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
991 | u16 antenna_reduction, | 991 | u16 antenna_reduction, |
992 | u16 powerLimit) | 992 | u16 powerLimit) |
993 | { | 993 | { |
994 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
995 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ | ||
996 | |||
997 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 994 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
998 | u16 twiceMaxEdgePower; | 995 | u16 twiceMaxEdgePower; |
999 | int i; | 996 | int i; |
@@ -1027,24 +1024,8 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1027 | 1024 | ||
1028 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 1025 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
1029 | 1026 | ||
1030 | scaledPower = powerLimit - antenna_reduction; | 1027 | scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit, |
1031 | 1028 | antenna_reduction); | |
1032 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
1033 | case 1: | ||
1034 | break; | ||
1035 | case 2: | ||
1036 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) | ||
1037 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
1038 | else | ||
1039 | scaledPower = 0; | ||
1040 | break; | ||
1041 | case 3: | ||
1042 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) | ||
1043 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
1044 | else | ||
1045 | scaledPower = 0; | ||
1046 | break; | ||
1047 | } | ||
1048 | 1029 | ||
1049 | if (IS_CHAN_2GHZ(chan)) { | 1030 | if (IS_CHAN_2GHZ(chan)) { |
1050 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | 1031 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - |
@@ -1263,20 +1244,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1263 | regulatory->max_power_level = ratesArray[i]; | 1244 | regulatory->max_power_level = ratesArray[i]; |
1264 | } | 1245 | } |
1265 | 1246 | ||
1266 | switch(ar5416_get_ntxchains(ah->txchainmask)) { | 1247 | ath9k_hw_update_regulatory_maxpower(ah); |
1267 | case 1: | ||
1268 | break; | ||
1269 | case 2: | ||
1270 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
1271 | break; | ||
1272 | case 3: | ||
1273 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
1274 | break; | ||
1275 | default: | ||
1276 | ath_dbg(ath9k_hw_common(ah), EEPROM, | ||
1277 | "Invalid chainmask configuration\n"); | ||
1278 | break; | ||
1279 | } | ||
1280 | 1248 | ||
1281 | if (test) | 1249 | if (test) |
1282 | return; | 1250 | return; |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index fbe23de1297f..dd10f4ac03ef 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -41,6 +41,9 @@ void ath_init_leds(struct ath_softc *sc) | |||
41 | { | 41 | { |
42 | int ret; | 42 | int ret; |
43 | 43 | ||
44 | if (AR_SREV_9100(sc->sc_ah)) | ||
45 | return; | ||
46 | |||
44 | if (sc->sc_ah->led_pin < 0) { | 47 | if (sc->sc_ah->led_pin < 0) { |
45 | if (AR_SREV_9287(sc->sc_ah)) | 48 | if (AR_SREV_9287(sc->sc_ah)) |
46 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | 49 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 424aabb2c730..f67cd952e741 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -53,6 +53,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { | |||
53 | .driver_info = AR9280_USB }, /* SMC Networks */ | 53 | .driver_info = AR9280_USB }, /* SMC Networks */ |
54 | { USB_DEVICE(0x0411, 0x017f), | 54 | { USB_DEVICE(0x0411, 0x017f), |
55 | .driver_info = AR9280_USB }, /* Sony UWA-BR100 */ | 55 | .driver_info = AR9280_USB }, /* Sony UWA-BR100 */ |
56 | { USB_DEVICE(0x04da, 0x3904), | ||
57 | .driver_info = AR9280_USB }, | ||
56 | 58 | ||
57 | { USB_DEVICE(0x0cf3, 0x20ff), | 59 | { USB_DEVICE(0x0cf3, 0x20ff), |
58 | .driver_info = STORAGE_DEVICE }, | 60 | .driver_info = STORAGE_DEVICE }, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d1345a8a2b15..72c5bcd4886d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include "rc.h" | 24 | #include "rc.h" |
25 | #include "ar9003_mac.h" | 25 | #include "ar9003_mac.h" |
26 | #include "ar9003_mci.h" | 26 | #include "ar9003_mci.h" |
27 | #include "debug.h" | ||
28 | #include "ath9k.h" | ||
27 | 29 | ||
28 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 30 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
29 | 31 | ||
@@ -83,6 +85,53 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
83 | /* Helper Functions */ | 85 | /* Helper Functions */ |
84 | /********************/ | 86 | /********************/ |
85 | 87 | ||
88 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
89 | |||
90 | void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) | ||
91 | { | ||
92 | struct ath_softc *sc = common->priv; | ||
93 | if (sync_cause) | ||
94 | sc->debug.stats.istats.sync_cause_all++; | ||
95 | if (sync_cause & AR_INTR_SYNC_RTC_IRQ) | ||
96 | sc->debug.stats.istats.sync_rtc_irq++; | ||
97 | if (sync_cause & AR_INTR_SYNC_MAC_IRQ) | ||
98 | sc->debug.stats.istats.sync_mac_irq++; | ||
99 | if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS) | ||
100 | sc->debug.stats.istats.eeprom_illegal_access++; | ||
101 | if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT) | ||
102 | sc->debug.stats.istats.apb_timeout++; | ||
103 | if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT) | ||
104 | sc->debug.stats.istats.pci_mode_conflict++; | ||
105 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) | ||
106 | sc->debug.stats.istats.host1_fatal++; | ||
107 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) | ||
108 | sc->debug.stats.istats.host1_perr++; | ||
109 | if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR) | ||
110 | sc->debug.stats.istats.trcv_fifo_perr++; | ||
111 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP) | ||
112 | sc->debug.stats.istats.radm_cpl_ep++; | ||
113 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT) | ||
114 | sc->debug.stats.istats.radm_cpl_dllp_abort++; | ||
115 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT) | ||
116 | sc->debug.stats.istats.radm_cpl_tlp_abort++; | ||
117 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR) | ||
118 | sc->debug.stats.istats.radm_cpl_ecrc_err++; | ||
119 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) | ||
120 | sc->debug.stats.istats.radm_cpl_timeout++; | ||
121 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) | ||
122 | sc->debug.stats.istats.local_timeout++; | ||
123 | if (sync_cause & AR_INTR_SYNC_PM_ACCESS) | ||
124 | sc->debug.stats.istats.pm_access++; | ||
125 | if (sync_cause & AR_INTR_SYNC_MAC_AWAKE) | ||
126 | sc->debug.stats.istats.mac_awake++; | ||
127 | if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP) | ||
128 | sc->debug.stats.istats.mac_asleep++; | ||
129 | if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS) | ||
130 | sc->debug.stats.istats.mac_sleep_access++; | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | |||
86 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) | 135 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) |
87 | { | 136 | { |
88 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 137 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
@@ -388,8 +437,8 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
388 | { | 437 | { |
389 | int i; | 438 | int i; |
390 | 439 | ||
391 | ah->config.dma_beacon_response_time = 2; | 440 | ah->config.dma_beacon_response_time = 1; |
392 | ah->config.sw_beacon_response_time = 10; | 441 | ah->config.sw_beacon_response_time = 6; |
393 | ah->config.additional_swba_backoff = 0; | 442 | ah->config.additional_swba_backoff = 0; |
394 | ah->config.ack_6mb = 0x0; | 443 | ah->config.ack_6mb = 0x0; |
395 | ah->config.cwm_ignore_extcca = 0; | 444 | ah->config.cwm_ignore_extcca = 0; |
@@ -445,7 +494,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
445 | AR_STA_ID1_MCAST_KSRCH; | 494 | AR_STA_ID1_MCAST_KSRCH; |
446 | if (AR_SREV_9100(ah)) | 495 | if (AR_SREV_9100(ah)) |
447 | ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; | 496 | ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; |
448 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | ||
449 | ah->slottime = ATH9K_SLOT_TIME_9; | 497 | ah->slottime = ATH9K_SLOT_TIME_9; |
450 | ah->globaltxtimeout = (u32) -1; | 498 | ah->globaltxtimeout = (u32) -1; |
451 | ah->power_mode = ATH9K_PM_UNDEFINED; | 499 | ah->power_mode = ATH9K_PM_UNDEFINED; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index aa1680a0c7fd..dd4b8f4097c8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -708,7 +708,6 @@ struct ath_hw { | |||
708 | struct ar5416Stats stats; | 708 | struct ar5416Stats stats; |
709 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; | 709 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
710 | 710 | ||
711 | int16_t curchan_rad_index; | ||
712 | enum ath9k_int imask; | 711 | enum ath9k_int imask; |
713 | u32 imrs2_reg; | 712 | u32 imrs2_reg; |
714 | u32 txok_interrupt_mask; | 713 | u32 txok_interrupt_mask; |
@@ -762,11 +761,6 @@ struct ath_hw { | |||
762 | 761 | ||
763 | u32 sta_id1_defaults; | 762 | u32 sta_id1_defaults; |
764 | u32 misc_mode; | 763 | u32 misc_mode; |
765 | enum { | ||
766 | AUTO_32KHZ, | ||
767 | USE_32KHZ, | ||
768 | DONT_USE_32KHZ, | ||
769 | } enable_32kHz_clock; | ||
770 | 764 | ||
771 | /* Private to hardware code */ | 765 | /* Private to hardware code */ |
772 | struct ath_hw_private_ops private_ops; | 766 | struct ath_hw_private_ops private_ops; |
@@ -783,7 +777,6 @@ struct ath_hw { | |||
783 | u32 *analogBank7Data; | 777 | u32 *analogBank7Data; |
784 | u32 *bank6Temp; | 778 | u32 *bank6Temp; |
785 | 779 | ||
786 | u8 txpower_limit; | ||
787 | int coverage_class; | 780 | int coverage_class; |
788 | u32 slottime; | 781 | u32 slottime; |
789 | u32 globaltxtimeout; | 782 | u32 globaltxtimeout; |
@@ -848,7 +841,6 @@ struct ath_hw { | |||
848 | struct ath_gen_timer_table hw_gen_timers; | 841 | struct ath_gen_timer_table hw_gen_timers; |
849 | 842 | ||
850 | struct ar9003_txs *ts_ring; | 843 | struct ar9003_txs *ts_ring; |
851 | void *ts_start; | ||
852 | u32 ts_paddr_start; | 844 | u32 ts_paddr_start; |
853 | u32 ts_paddr_end; | 845 | u32 ts_paddr_end; |
854 | u16 ts_tail; | 846 | u16 ts_tail; |
@@ -915,7 +907,6 @@ static inline u8 get_streams(int mask) | |||
915 | } | 907 | } |
916 | 908 | ||
917 | /* Initialization, Detach, Reset */ | 909 | /* Initialization, Detach, Reset */ |
918 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | ||
919 | void ath9k_hw_deinit(struct ath_hw *ah); | 910 | void ath9k_hw_deinit(struct ath_hw *ah); |
920 | int ath9k_hw_init(struct ath_hw *ah); | 911 | int ath9k_hw_init(struct ath_hw *ah); |
921 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 912 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
@@ -965,6 +956,12 @@ bool ath9k_hw_check_alive(struct ath_hw *ah); | |||
965 | 956 | ||
966 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); | 957 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
967 | 958 | ||
959 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
960 | void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause); | ||
961 | #else | ||
962 | static void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) {} | ||
963 | #endif | ||
964 | |||
968 | /* Generic hw timer primitives */ | 965 | /* Generic hw timer primitives */ |
969 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | 966 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, |
970 | void (*trigger)(void *), | 967 | void (*trigger)(void *), |
@@ -1011,7 +1008,6 @@ int ar9003_paprd_create_curve(struct ath_hw *ah, | |||
1011 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | 1008 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); |
1012 | int ar9003_paprd_init_table(struct ath_hw *ah); | 1009 | int ar9003_paprd_init_table(struct ath_hw *ah); |
1013 | bool ar9003_paprd_is_done(struct ath_hw *ah); | 1010 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
1014 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); | ||
1015 | 1011 | ||
1016 | /* Hardware family op attach helpers */ | 1012 | /* Hardware family op attach helpers */ |
1017 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 1013 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c8d123957188..384e5c498440 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -692,17 +692,6 @@ void ath9k_tasklet(unsigned long data) | |||
692 | goto out; | 692 | goto out; |
693 | } | 693 | } |
694 | 694 | ||
695 | /* | ||
696 | * Only run the baseband hang check if beacons stop working in AP or | ||
697 | * IBSS mode, because it has a high false positive rate. For station | ||
698 | * mode it should not be necessary, since the upper layers will detect | ||
699 | * this through a beacon miss automatically and the following channel | ||
700 | * change will trigger a hardware reset anyway | ||
701 | */ | ||
702 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 && | ||
703 | !ath9k_hw_check_alive(ah)) | ||
704 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
705 | |||
706 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | 695 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { |
707 | /* | 696 | /* |
708 | * TSF sync does not look correct; remain awake to sync with | 697 | * TSF sync does not look correct; remain awake to sync with |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 6c87a823f5a9..d07c0301da6a 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -3989,8 +3989,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3989 | atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000); | 3989 | atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000); |
3990 | } | 3990 | } |
3991 | 3991 | ||
3992 | if (fw_entry) | 3992 | release_firmware(fw_entry); |
3993 | release_firmware(fw_entry); | ||
3994 | } | 3993 | } |
3995 | 3994 | ||
3996 | err = atmel_wakeup_firmware(priv); | 3995 | err = atmel_wakeup_firmware(priv); |
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 9ab1192004c0..51e33b53386e 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c | |||
@@ -74,15 +74,4 @@ static void __devexit atmel_pci_remove(struct pci_dev *pdev) | |||
74 | stop_atmel_card(pci_get_drvdata(pdev)); | 74 | stop_atmel_card(pci_get_drvdata(pdev)); |
75 | } | 75 | } |
76 | 76 | ||
77 | static int __init atmel_init_module(void) | 77 | module_pci_driver(atmel_driver); |
78 | { | ||
79 | return pci_register_driver(&atmel_driver); | ||
80 | } | ||
81 | |||
82 | static void __exit atmel_cleanup_module(void) | ||
83 | { | ||
84 | pci_unregister_driver(&atmel_driver); | ||
85 | } | ||
86 | |||
87 | module_init(atmel_init_module); | ||
88 | module_exit(atmel_cleanup_module); | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index cba413536270..b31ccc02fa21 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -290,7 +290,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
290 | txhdr->dur_fb = wlhdr->duration_id; | 290 | txhdr->dur_fb = wlhdr->duration_id; |
291 | } else { | 291 | } else { |
292 | txhdr->dur_fb = ieee80211_generic_frame_duration( | 292 | txhdr->dur_fb = ieee80211_generic_frame_duration( |
293 | dev->wl->hw, info->control.vif, fragment_len, fbrate); | 293 | dev->wl->hw, info->control.vif, info->band, |
294 | fragment_len, fbrate); | ||
294 | } | 295 | } |
295 | 296 | ||
296 | plcp_fragment_len = fragment_len + FCS_LEN; | 297 | plcp_fragment_len = fragment_len + FCS_LEN; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index df7e16dfb36c..1be214b815fb 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -1056,6 +1056,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, | |||
1056 | b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); | 1056 | b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); |
1057 | dur = ieee80211_generic_frame_duration(dev->wl->hw, | 1057 | dur = ieee80211_generic_frame_duration(dev->wl->hw, |
1058 | dev->wl->vif, | 1058 | dev->wl->vif, |
1059 | IEEE80211_BAND_2GHZ, | ||
1059 | size, | 1060 | size, |
1060 | rate); | 1061 | rate); |
1061 | /* Write PLCP in two parts and timing for packet transfer */ | 1062 | /* Write PLCP in two parts and timing for packet transfer */ |
@@ -1121,6 +1122,7 @@ static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, | |||
1121 | IEEE80211_STYPE_PROBE_RESP); | 1122 | IEEE80211_STYPE_PROBE_RESP); |
1122 | dur = ieee80211_generic_frame_duration(dev->wl->hw, | 1123 | dur = ieee80211_generic_frame_duration(dev->wl->hw, |
1123 | dev->wl->vif, | 1124 | dev->wl->vif, |
1125 | IEEE80211_BAND_2GHZ, | ||
1124 | *dest_size, | 1126 | *dest_size, |
1125 | rate); | 1127 | rate); |
1126 | hdr->duration_id = dur; | 1128 | hdr->duration_id = dur; |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index e6c573af494d..a8012f2749ee 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -228,6 +228,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
228 | } else { | 228 | } else { |
229 | txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, | 229 | txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, |
230 | info->control.vif, | 230 | info->control.vif, |
231 | info->band, | ||
231 | fragment_len, | 232 | fragment_len, |
232 | rate_fb); | 233 | rate_fb); |
233 | } | 234 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 07686a748d3c..9f637014486e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -632,7 +632,6 @@ extern const struct bcmevent_name bcmevent_names[]; | |||
632 | extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, | 632 | extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, |
633 | char *buf, uint len); | 633 | char *buf, uint len); |
634 | 634 | ||
635 | extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx); | ||
636 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); | 635 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); |
637 | 636 | ||
638 | extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); | 637 | extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index b3e3b7f25d82..a5c15cac5e7d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -421,6 +421,7 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx, | |||
421 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; | 421 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; |
422 | 422 | ||
423 | skb_pull(pktbuf, BDC_HEADER_LEN); | 423 | skb_pull(pktbuf, BDC_HEADER_LEN); |
424 | skb_pull(pktbuf, h->data_offset << 2); | ||
424 | 425 | ||
425 | return 0; | 426 | return 0; |
426 | } | 427 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 4187435220f3..236cb9fa460c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -799,7 +799,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |||
799 | { | 799 | { |
800 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for | 800 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for |
801 | "event_msgs" + '\0' + bitvec */ | 801 | "event_msgs" + '\0' + bitvec */ |
802 | uint up = 0; | ||
803 | char buf[128], *ptr; | 802 | char buf[128], *ptr; |
804 | u32 dongle_align = drvr->bus_if->align; | 803 | u32 dongle_align = drvr->bus_if->align; |
805 | u32 glom = 0; | 804 | u32 glom = 0; |
@@ -853,9 +852,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |||
853 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | 852 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, |
854 | sizeof(iovbuf)); | 853 | sizeof(iovbuf)); |
855 | 854 | ||
856 | /* Force STA UP */ | ||
857 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up)); | ||
858 | |||
859 | /* Setup event_msgs */ | 855 | /* Setup event_msgs */ |
860 | brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | 856 | brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, |
861 | iovbuf, sizeof(iovbuf)); | 857 | iovbuf, sizeof(iovbuf)); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 2a1e5ae0c402..8933f9b31a9a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -799,6 +799,7 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
799 | struct brcmf_bus *bus_if = drvr->bus_if; | 799 | struct brcmf_bus *bus_if = drvr->bus_if; |
800 | u32 toe_ol; | 800 | u32 toe_ol; |
801 | s32 ret = 0; | 801 | s32 ret = 0; |
802 | uint up = 0; | ||
802 | 803 | ||
803 | brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); | 804 | brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); |
804 | 805 | ||
@@ -822,6 +823,10 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
822 | drvr->iflist[ifp->idx]->ndev->features &= | 823 | drvr->iflist[ifp->idx]->ndev->features &= |
823 | ~NETIF_F_IP_CSUM; | 824 | ~NETIF_F_IP_CSUM; |
824 | } | 825 | } |
826 | |||
827 | /* make sure RF is ready for work */ | ||
828 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up)); | ||
829 | |||
825 | /* Allow transmit calls */ | 830 | /* Allow transmit calls */ |
826 | netif_start_queue(ndev); | 831 | netif_start_queue(ndev); |
827 | drvr->bus_if->drvr_up = true; | 832 | drvr->bus_if->drvr_up = true; |
@@ -843,6 +848,63 @@ static const struct net_device_ops brcmf_netdev_ops_pri = { | |||
843 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list | 848 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list |
844 | }; | 849 | }; |
845 | 850 | ||
851 | static int brcmf_net_attach(struct brcmf_if *ifp) | ||
852 | { | ||
853 | struct brcmf_pub *drvr = ifp->drvr; | ||
854 | struct net_device *ndev; | ||
855 | u8 temp_addr[ETH_ALEN]; | ||
856 | |||
857 | brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); | ||
858 | |||
859 | ndev = drvr->iflist[ifp->idx]->ndev; | ||
860 | ndev->netdev_ops = &brcmf_netdev_ops_pri; | ||
861 | |||
862 | /* | ||
863 | * determine mac address to use | ||
864 | */ | ||
865 | if (is_valid_ether_addr(ifp->mac_addr)) | ||
866 | memcpy(temp_addr, ifp->mac_addr, ETH_ALEN); | ||
867 | else | ||
868 | memcpy(temp_addr, drvr->mac, ETH_ALEN); | ||
869 | |||
870 | if (ifp->idx == 1) { | ||
871 | brcmf_dbg(TRACE, "ACCESS POINT MAC:\n"); | ||
872 | /* ACCESSPOINT INTERFACE CASE */ | ||
873 | temp_addr[0] |= 0X02; /* set bit 2 , | ||
874 | - Locally Administered address */ | ||
875 | |||
876 | } | ||
877 | ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; | ||
878 | ndev->ethtool_ops = &brcmf_ethtool_ops; | ||
879 | |||
880 | drvr->rxsz = ndev->mtu + ndev->hard_header_len + | ||
881 | drvr->hdrlen; | ||
882 | |||
883 | memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); | ||
884 | |||
885 | /* attach to cfg80211 for primary interface */ | ||
886 | if (!ifp->idx) { | ||
887 | drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr); | ||
888 | if (drvr->config == NULL) { | ||
889 | brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); | ||
890 | goto fail; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | if (register_netdev(ndev) != 0) { | ||
895 | brcmf_dbg(ERROR, "couldn't register the net device\n"); | ||
896 | goto fail; | ||
897 | } | ||
898 | |||
899 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); | ||
900 | |||
901 | return 0; | ||
902 | |||
903 | fail: | ||
904 | ndev->netdev_ops = NULL; | ||
905 | return -EBADE; | ||
906 | } | ||
907 | |||
846 | int | 908 | int |
847 | brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | 909 | brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) |
848 | { | 910 | { |
@@ -882,7 +944,7 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | |||
882 | if (mac_addr != NULL) | 944 | if (mac_addr != NULL) |
883 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); | 945 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); |
884 | 946 | ||
885 | if (brcmf_net_attach(drvr, ifp->idx)) { | 947 | if (brcmf_net_attach(ifp)) { |
886 | brcmf_dbg(ERROR, "brcmf_net_attach failed"); | 948 | brcmf_dbg(ERROR, "brcmf_net_attach failed"); |
887 | free_netdev(ifp->ndev); | 949 | free_netdev(ifp->ndev); |
888 | drvr->iflist[ifidx] = NULL; | 950 | drvr->iflist[ifidx] = NULL; |
@@ -1016,69 +1078,16 @@ int brcmf_bus_start(struct device *dev) | |||
1016 | if (ret < 0) | 1078 | if (ret < 0) |
1017 | return ret; | 1079 | return ret; |
1018 | 1080 | ||
1081 | /* add primary networking interface */ | ||
1082 | ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac); | ||
1083 | if (ret < 0) | ||
1084 | return ret; | ||
1085 | |||
1019 | /* signal bus ready */ | 1086 | /* signal bus ready */ |
1020 | bus_if->state = BRCMF_BUS_DATA; | 1087 | bus_if->state = BRCMF_BUS_DATA; |
1021 | return 0; | 1088 | return 0; |
1022 | } | 1089 | } |
1023 | 1090 | ||
1024 | int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) | ||
1025 | { | ||
1026 | struct net_device *ndev; | ||
1027 | u8 temp_addr[ETH_ALEN] = { | ||
1028 | 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33}; | ||
1029 | |||
1030 | brcmf_dbg(TRACE, "ifidx %d\n", ifidx); | ||
1031 | |||
1032 | ndev = drvr->iflist[ifidx]->ndev; | ||
1033 | ndev->netdev_ops = &brcmf_netdev_ops_pri; | ||
1034 | |||
1035 | /* | ||
1036 | * We have to use the primary MAC for virtual interfaces | ||
1037 | */ | ||
1038 | if (ifidx != 0) { | ||
1039 | /* for virtual interfaces use the primary MAC */ | ||
1040 | memcpy(temp_addr, drvr->mac, ETH_ALEN); | ||
1041 | |||
1042 | } | ||
1043 | |||
1044 | if (ifidx == 1) { | ||
1045 | brcmf_dbg(TRACE, "ACCESS POINT MAC:\n"); | ||
1046 | /* ACCESSPOINT INTERFACE CASE */ | ||
1047 | temp_addr[0] |= 0X02; /* set bit 2 , | ||
1048 | - Locally Administered address */ | ||
1049 | |||
1050 | } | ||
1051 | ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; | ||
1052 | ndev->ethtool_ops = &brcmf_ethtool_ops; | ||
1053 | |||
1054 | drvr->rxsz = ndev->mtu + ndev->hard_header_len + | ||
1055 | drvr->hdrlen; | ||
1056 | |||
1057 | memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); | ||
1058 | |||
1059 | /* attach to cfg80211 for primary interface */ | ||
1060 | if (!ifidx) { | ||
1061 | drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr); | ||
1062 | if (drvr->config == NULL) { | ||
1063 | brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); | ||
1064 | goto fail; | ||
1065 | } | ||
1066 | } | ||
1067 | |||
1068 | if (register_netdev(ndev) != 0) { | ||
1069 | brcmf_dbg(ERROR, "couldn't register the net device\n"); | ||
1070 | goto fail; | ||
1071 | } | ||
1072 | |||
1073 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); | ||
1074 | |||
1075 | return 0; | ||
1076 | |||
1077 | fail: | ||
1078 | ndev->netdev_ops = NULL; | ||
1079 | return -EBADE; | ||
1080 | } | ||
1081 | |||
1082 | static void brcmf_bus_detach(struct brcmf_pub *drvr) | 1091 | static void brcmf_bus_detach(struct brcmf_pub *drvr) |
1083 | { | 1092 | { |
1084 | brcmf_dbg(TRACE, "Enter\n"); | 1093 | brcmf_dbg(TRACE, "Enter\n"); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 2bf5dda29291..a83fbea04c04 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -3948,12 +3948,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3948 | } | 3948 | } |
3949 | } | 3949 | } |
3950 | 3950 | ||
3951 | /* add interface and open for business */ | ||
3952 | if (brcmf_add_if(bus->sdiodev->dev, 0, "wlan%d", NULL)) { | ||
3953 | brcmf_dbg(ERROR, "Add primary net device interface failed!!\n"); | ||
3954 | goto fail; | ||
3955 | } | ||
3956 | |||
3957 | return bus; | 3951 | return bus; |
3958 | 3952 | ||
3959 | fail: | 3953 | fail: |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 82364223e817..1d67ecf681b7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -1383,14 +1383,6 @@ static int brcmf_usb_probe_cb(struct device *dev, const char *desc, | |||
1383 | goto fail; | 1383 | goto fail; |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | /* add interface and open for business */ | ||
1387 | ret = brcmf_add_if(dev, 0, "wlan%d", NULL); | ||
1388 | if (ret) { | ||
1389 | brcmf_dbg(ERROR, "Add primary net device interface failed!!\n"); | ||
1390 | brcmf_detach(dev); | ||
1391 | goto fail; | ||
1392 | } | ||
1393 | |||
1394 | return 0; | 1386 | return 0; |
1395 | fail: | 1387 | fail: |
1396 | /* Release resources in reverse order */ | 1388 | /* Release resources in reverse order */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 55e9f45fce22..0efe88e25a9a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
@@ -628,6 +628,40 @@ brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, | |||
628 | return false; | 628 | return false; |
629 | } | 629 | } |
630 | 630 | ||
631 | /* | ||
632 | * Indicates whether the country provided is valid to pass | ||
633 | * to cfg80211 or not. | ||
634 | * | ||
635 | * returns true if valid; false if not. | ||
636 | */ | ||
637 | static bool brcms_c_country_valid(const char *ccode) | ||
638 | { | ||
639 | /* | ||
640 | * only allow ascii alpha uppercase for the first 2 | ||
641 | * chars. | ||
642 | */ | ||
643 | if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A && | ||
644 | (0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A && | ||
645 | ccode[2] == '\0')) | ||
646 | return false; | ||
647 | |||
648 | /* | ||
649 | * do not match ISO 3166-1 user assigned country codes | ||
650 | * that may be in the driver table | ||
651 | */ | ||
652 | if (!strcmp("AA", ccode) || /* AA */ | ||
653 | !strcmp("ZZ", ccode) || /* ZZ */ | ||
654 | ccode[0] == 'X' || /* XA - XZ */ | ||
655 | (ccode[0] == 'Q' && /* QM - QZ */ | ||
656 | (ccode[1] >= 'M' && ccode[1] <= 'Z'))) | ||
657 | return false; | ||
658 | |||
659 | if (!strcmp("NA", ccode)) | ||
660 | return false; | ||
661 | |||
662 | return true; | ||
663 | } | ||
664 | |||
631 | /* Lookup a country info structure from a null terminated country | 665 | /* Lookup a country info structure from a null terminated country |
632 | * abbreviation and regrev directly with no translation. | 666 | * abbreviation and regrev directly with no translation. |
633 | */ | 667 | */ |
@@ -1089,7 +1123,7 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
1089 | 1123 | ||
1090 | /* store the country code for passing up as a regulatory hint */ | 1124 | /* store the country code for passing up as a regulatory hint */ |
1091 | ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); | 1125 | ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); |
1092 | if (ccode) | 1126 | if (ccode && brcms_c_country_valid(ccode)) |
1093 | strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); | 1127 | strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); |
1094 | 1128 | ||
1095 | /* | 1129 | /* |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 569ab8abd2a1..aa15558f75c8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -1069,11 +1069,7 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1069 | wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" | 1069 | wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" |
1070 | "%d\n", __func__, err); | 1070 | "%d\n", __func__, err); |
1071 | 1071 | ||
1072 | if (wl->pub->srom_ccode[0]) | 1072 | if (wl->pub->srom_ccode[0] && brcms_set_hint(wl, wl->pub->srom_ccode)) |
1073 | err = brcms_set_hint(wl, wl->pub->srom_ccode); | ||
1074 | else | ||
1075 | err = brcms_set_hint(wl, "US"); | ||
1076 | if (err) | ||
1077 | wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", | 1073 | wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", |
1078 | __func__, err); | 1074 | __func__, err); |
1079 | 1075 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index ce8562aa5db0..0fce56235f38 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -207,8 +207,7 @@ static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { | |||
207 | }; | 207 | }; |
208 | 208 | ||
209 | static const u16 iqcal_gainparams_numgains_lcnphy[1] = { | 209 | static const u16 iqcal_gainparams_numgains_lcnphy[1] = { |
210 | sizeof(tbl_iqcal_gainparams_lcnphy_2G) / | 210 | ARRAY_SIZE(tbl_iqcal_gainparams_lcnphy_2G), |
211 | sizeof(*tbl_iqcal_gainparams_lcnphy_2G), | ||
212 | }; | 211 | }; |
213 | 212 | ||
214 | static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { | 213 | static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 39095741fd05..812b6e38526e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -16353,11 +16353,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) | |||
16353 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, | 16353 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, |
16354 | rfseq_rx2tx_events_rev3_ipa, | 16354 | rfseq_rx2tx_events_rev3_ipa, |
16355 | rfseq_rx2tx_dlys_rev3_ipa, | 16355 | rfseq_rx2tx_dlys_rev3_ipa, |
16356 | sizeof | 16356 | ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa)); |
16357 | (rfseq_rx2tx_events_rev3_ipa) / | ||
16358 | sizeof | ||
16359 | (rfseq_rx2tx_events_rev3_ipa | ||
16360 | [0])); | ||
16361 | 16357 | ||
16362 | mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); | 16358 | mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); |
16363 | mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); | 16359 | mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); |
@@ -16858,18 +16854,13 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) | |||
16858 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, | 16854 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, |
16859 | rfseq_tx2rx_events_rev3, | 16855 | rfseq_tx2rx_events_rev3, |
16860 | rfseq_tx2rx_dlys_rev3, | 16856 | rfseq_tx2rx_dlys_rev3, |
16861 | sizeof(rfseq_tx2rx_events_rev3) / | 16857 | ARRAY_SIZE(rfseq_tx2rx_events_rev3)); |
16862 | sizeof(rfseq_tx2rx_events_rev3[0])); | ||
16863 | 16858 | ||
16864 | if (PHY_IPA(pi)) | 16859 | if (PHY_IPA(pi)) |
16865 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, | 16860 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, |
16866 | rfseq_rx2tx_events_rev3_ipa, | 16861 | rfseq_rx2tx_events_rev3_ipa, |
16867 | rfseq_rx2tx_dlys_rev3_ipa, | 16862 | rfseq_rx2tx_dlys_rev3_ipa, |
16868 | sizeof | 16863 | ARRAY_SIZE(rfseq_rx2tx_events_rev3_ipa)); |
16869 | (rfseq_rx2tx_events_rev3_ipa) / | ||
16870 | sizeof | ||
16871 | (rfseq_rx2tx_events_rev3_ipa | ||
16872 | [0])); | ||
16873 | 16864 | ||
16874 | if ((pi->sh->hw_phyrxchain != 0x3) && | 16865 | if ((pi->sh->hw_phyrxchain != 0x3) && |
16875 | (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { | 16866 | (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { |
@@ -16885,8 +16876,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) | |||
16885 | pi, NPHY_RFSEQ_RX2TX, | 16876 | pi, NPHY_RFSEQ_RX2TX, |
16886 | rfseq_rx2tx_events_rev3, | 16877 | rfseq_rx2tx_events_rev3, |
16887 | rfseq_rx2tx_dlys_rev3, | 16878 | rfseq_rx2tx_dlys_rev3, |
16888 | sizeof(rfseq_rx2tx_events_rev3) / | 16879 | ARRAY_SIZE(rfseq_rx2tx_events_rev3)); |
16889 | sizeof(rfseq_rx2tx_events_rev3[0])); | ||
16890 | } | 16880 | } |
16891 | 16881 | ||
16892 | if (CHSPEC_IS2G(pi->radio_chanspec)) | 16882 | if (CHSPEC_IS2G(pi->radio_chanspec)) |
@@ -17209,13 +17199,11 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) | |||
17209 | 17199 | ||
17210 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, | 17200 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, |
17211 | rfseq_rx2tx_dlys, | 17201 | rfseq_rx2tx_dlys, |
17212 | sizeof(rfseq_rx2tx_events) / | 17202 | ARRAY_SIZE(rfseq_rx2tx_events)); |
17213 | sizeof(rfseq_rx2tx_events[0])); | ||
17214 | 17203 | ||
17215 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, | 17204 | wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, |
17216 | rfseq_tx2rx_dlys, | 17205 | rfseq_tx2rx_dlys, |
17217 | sizeof(rfseq_tx2rx_events) / | 17206 | ARRAY_SIZE(rfseq_tx2rx_events)); |
17218 | sizeof(rfseq_tx2rx_events[0])); | ||
17219 | 17207 | ||
17220 | wlc_phy_workarounds_nphy_gainctrl(pi); | 17208 | wlc_phy_workarounds_nphy_gainctrl(pi); |
17221 | 17209 | ||
@@ -19357,8 +19345,7 @@ static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) | |||
19357 | } | 19345 | } |
19358 | 19346 | ||
19359 | if (isAdjustNoiseVar) { | 19347 | if (isAdjustNoiseVar) { |
19360 | numTonesAdjust = sizeof(nphy_adj_tone_id_buf) / | 19348 | numTonesAdjust = ARRAY_SIZE(nphy_adj_tone_id_buf); |
19361 | sizeof(nphy_adj_tone_id_buf[0]); | ||
19362 | 19349 | ||
19363 | wlc_phy_adjust_min_noisevar_nphy( | 19350 | wlc_phy_adjust_min_noisevar_nphy( |
19364 | pi, | 19351 | pi, |
@@ -25204,32 +25191,26 @@ static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) | |||
25204 | 25191 | ||
25205 | phy_a15 = pad_gain_codes_used_2057rev5; | 25192 | phy_a15 = pad_gain_codes_used_2057rev5; |
25206 | phy_a13 = | 25193 | phy_a13 = |
25207 | sizeof(pad_gain_codes_used_2057rev5) / | 25194 | ARRAY_SIZE(pad_gain_codes_used_2057rev5) - 1; |
25208 | sizeof(pad_gain_codes_used_2057rev5 | ||
25209 | [0]) - 1; | ||
25210 | 25195 | ||
25211 | } else if ((pi->pubpi.radiorev == 7) | 25196 | } else if ((pi->pubpi.radiorev == 7) |
25212 | || (pi->pubpi.radiorev == 8)) { | 25197 | || (pi->pubpi.radiorev == 8)) { |
25213 | 25198 | ||
25214 | phy_a15 = pad_gain_codes_used_2057rev7; | 25199 | phy_a15 = pad_gain_codes_used_2057rev7; |
25215 | phy_a13 = | 25200 | phy_a13 = |
25216 | sizeof(pad_gain_codes_used_2057rev7) / | 25201 | ARRAY_SIZE(pad_gain_codes_used_2057rev7) - 1; |
25217 | sizeof(pad_gain_codes_used_2057rev7 | ||
25218 | [0]) - 1; | ||
25219 | 25202 | ||
25220 | } else { | 25203 | } else { |
25221 | 25204 | ||
25222 | phy_a15 = pad_all_gain_codes_2057; | 25205 | phy_a15 = pad_all_gain_codes_2057; |
25223 | phy_a13 = sizeof(pad_all_gain_codes_2057) / | 25206 | phy_a13 = ARRAY_SIZE(pad_all_gain_codes_2057) - |
25224 | sizeof(pad_all_gain_codes_2057[0]) - | ||
25225 | 1; | 25207 | 1; |
25226 | } | 25208 | } |
25227 | 25209 | ||
25228 | } else { | 25210 | } else { |
25229 | 25211 | ||
25230 | phy_a15 = pga_all_gain_codes_2057; | 25212 | phy_a15 = pga_all_gain_codes_2057; |
25231 | phy_a13 = sizeof(pga_all_gain_codes_2057) / | 25213 | phy_a13 = ARRAY_SIZE(pga_all_gain_codes_2057) - 1; |
25232 | sizeof(pga_all_gain_codes_2057[0]) - 1; | ||
25233 | } | 25214 | } |
25234 | 25215 | ||
25235 | phy_a14 = 0; | 25216 | phy_a14 = 0; |
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 5fb17d53c9b2..333193f20e1c 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -17,17 +17,7 @@ | |||
17 | #ifndef _BRCM_HW_IDS_H_ | 17 | #ifndef _BRCM_HW_IDS_H_ |
18 | #define _BRCM_HW_IDS_H_ | 18 | #define _BRCM_HW_IDS_H_ |
19 | 19 | ||
20 | #define BCM4325_D11DUAL_ID 0x431b | 20 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ |
21 | #define BCM4325_D11G_ID 0x431c | ||
22 | #define BCM4325_D11A_ID 0x431d | ||
23 | |||
24 | #define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ | ||
25 | #define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ | ||
26 | #define BCM4329_D11NDUAL_ID 0x432e | ||
27 | |||
28 | #define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ | ||
29 | #define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ | ||
30 | #define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ | ||
31 | 21 | ||
32 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ | 22 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ |
33 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ | 23 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ |
@@ -37,23 +27,15 @@ | |||
37 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ | 27 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ |
38 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ | 28 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ |
39 | 29 | ||
40 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ | 30 | /* Chipcommon Core Chip IDs */ |
41 | 31 | #define BCM4313_CHIP_ID 0x4313 | |
42 | /* Chip IDs */ | 32 | #define BCM43224_CHIP_ID 43224 |
43 | #define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ | 33 | #define BCM43225_CHIP_ID 43225 |
44 | #define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ | 34 | #define BCM43235_CHIP_ID 43235 |
45 | 35 | #define BCM43236_CHIP_ID 43236 | |
46 | #define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ | 36 | #define BCM43238_CHIP_ID 43238 |
47 | #define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ | 37 | #define BCM4329_CHIP_ID 0x4329 |
48 | #define BCM43421_CHIP_ID 43421 /* 43421 chipcommon chipid */ | 38 | #define BCM4330_CHIP_ID 0x4330 |
49 | #define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ | 39 | #define BCM4331_CHIP_ID 0x4331 |
50 | #define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ | ||
51 | #define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ | ||
52 | #define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ | ||
53 | #define BCM4325_CHIP_ID 0x4325 /* 4325 chipcommon chipid */ | ||
54 | #define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ | ||
55 | #define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ | ||
56 | #define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ | ||
57 | #define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ | ||
58 | 40 | ||
59 | #endif /* _BRCM_HW_IDS_H_ */ | 41 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index bfa0d54221e8..627bc12074c7 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c | |||
@@ -244,8 +244,7 @@ u16 hostap_tx_callback_register(local_info_t *local, | |||
244 | unsigned long flags; | 244 | unsigned long flags; |
245 | struct hostap_tx_callback_info *entry; | 245 | struct hostap_tx_callback_info *entry; |
246 | 246 | ||
247 | entry = kmalloc(sizeof(*entry), | 247 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
248 | GFP_ATOMIC); | ||
249 | if (entry == NULL) | 248 | if (entry == NULL) |
250 | return 0; | 249 | return 0; |
251 | 250 | ||
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 972a9c3af39e..05ca3402dca7 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c | |||
@@ -457,18 +457,4 @@ static struct pci_driver prism2_pci_driver = { | |||
457 | #endif /* CONFIG_PM */ | 457 | #endif /* CONFIG_PM */ |
458 | }; | 458 | }; |
459 | 459 | ||
460 | 460 | module_pci_driver(prism2_pci_driver); | |
461 | static int __init init_prism2_pci(void) | ||
462 | { | ||
463 | return pci_register_driver(&prism2_pci_driver); | ||
464 | } | ||
465 | |||
466 | |||
467 | static void __exit exit_prism2_pci(void) | ||
468 | { | ||
469 | pci_unregister_driver(&prism2_pci_driver); | ||
470 | } | ||
471 | |||
472 | |||
473 | module_init(init_prism2_pci); | ||
474 | module_exit(exit_prism2_pci); | ||
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 33e79037770b..c3d067ee4db9 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c | |||
@@ -616,18 +616,4 @@ static struct pci_driver prism2_plx_driver = { | |||
616 | .remove = prism2_plx_remove, | 616 | .remove = prism2_plx_remove, |
617 | }; | 617 | }; |
618 | 618 | ||
619 | 619 | module_pci_driver(prism2_plx_driver); | |
620 | static int __init init_prism2_plx(void) | ||
621 | { | ||
622 | return pci_register_driver(&prism2_plx_driver); | ||
623 | } | ||
624 | |||
625 | |||
626 | static void __exit exit_prism2_plx(void) | ||
627 | { | ||
628 | pci_unregister_driver(&prism2_plx_driver); | ||
629 | } | ||
630 | |||
631 | |||
632 | module_init(init_prism2_plx); | ||
633 | module_exit(exit_prism2_plx); | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h new file mode 100644 index 000000000000..4007bf5ed6f3 --- /dev/null +++ b/drivers/net/wireless/ipw2x00/ipw.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver | ||
3 | * | ||
4 | * Copyright 2012 Stanislav Yakovlev <stas.yakovlev@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __IPW_H__ | ||
12 | #define __IPW_H__ | ||
13 | |||
14 | #include <linux/ieee80211.h> | ||
15 | |||
16 | static const u32 ipw_cipher_suites[] = { | ||
17 | WLAN_CIPHER_SUITE_WEP40, | ||
18 | WLAN_CIPHER_SUITE_WEP104, | ||
19 | WLAN_CIPHER_SUITE_TKIP, | ||
20 | WLAN_CIPHER_SUITE_CCMP, | ||
21 | }; | ||
22 | |||
23 | #endif | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 2662d46134d0..c72136c07774 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -166,6 +166,7 @@ that only one external action is invoked at a time. | |||
166 | #include <net/lib80211.h> | 166 | #include <net/lib80211.h> |
167 | 167 | ||
168 | #include "ipw2100.h" | 168 | #include "ipw2100.h" |
169 | #include "ipw.h" | ||
169 | 170 | ||
170 | #define IPW2100_VERSION "git-1.2.2" | 171 | #define IPW2100_VERSION "git-1.2.2" |
171 | 172 | ||
@@ -1958,6 +1959,9 @@ static int ipw2100_wdev_init(struct net_device *dev) | |||
1958 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; | 1959 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; |
1959 | } | 1960 | } |
1960 | 1961 | ||
1962 | wdev->wiphy->cipher_suites = ipw_cipher_suites; | ||
1963 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); | ||
1964 | |||
1961 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); | 1965 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); |
1962 | if (wiphy_register(wdev->wiphy)) { | 1966 | if (wiphy_register(wdev->wiphy)) { |
1963 | ipw2100_down(priv); | 1967 | ipw2100_down(priv); |
@@ -8503,8 +8507,7 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, | |||
8503 | struct ipw2100_fw *fw) | 8507 | struct ipw2100_fw *fw) |
8504 | { | 8508 | { |
8505 | fw->version = 0; | 8509 | fw->version = 0; |
8506 | if (fw->fw_entry) | 8510 | release_firmware(fw->fw_entry); |
8507 | release_firmware(fw->fw_entry); | ||
8508 | fw->fw_entry = NULL; | 8511 | fw->fw_entry = NULL; |
8509 | } | 8512 | } |
8510 | 8513 | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 809b7a70974b..d57522c64073 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <net/cfg80211-wext.h> | 35 | #include <net/cfg80211-wext.h> |
36 | #include "ipw2200.h" | 36 | #include "ipw2200.h" |
37 | #include "ipw.h" | ||
37 | 38 | ||
38 | 39 | ||
39 | #ifndef KBUILD_EXTMOD | 40 | #ifndef KBUILD_EXTMOD |
@@ -3657,8 +3658,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
3657 | priv->rxq = NULL; | 3658 | priv->rxq = NULL; |
3658 | } | 3659 | } |
3659 | ipw_tx_queue_free(priv); | 3660 | ipw_tx_queue_free(priv); |
3660 | if (raw) | 3661 | release_firmware(raw); |
3661 | release_firmware(raw); | ||
3662 | #ifdef CONFIG_PM | 3662 | #ifdef CONFIG_PM |
3663 | fw_loaded = 0; | 3663 | fw_loaded = 0; |
3664 | raw = NULL; | 3664 | raw = NULL; |
@@ -11533,6 +11533,9 @@ static int ipw_wdev_init(struct net_device *dev) | |||
11533 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; | 11533 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; |
11534 | } | 11534 | } |
11535 | 11535 | ||
11536 | wdev->wiphy->cipher_suites = ipw_cipher_suites; | ||
11537 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); | ||
11538 | |||
11536 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); | 11539 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); |
11537 | 11540 | ||
11538 | /* With that information in place, we can now register the wiphy... */ | 11541 | /* With that information in place, we can now register the wiphy... */ |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 565611eef0d4..db6c6e528022 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -113,20 +113,21 @@ config IWLWIFI_DEVICE_TESTMODE | |||
113 | generic netlink message via NL80211_TESTMODE channel. | 113 | generic netlink message via NL80211_TESTMODE channel. |
114 | 114 | ||
115 | config IWLWIFI_P2P | 115 | config IWLWIFI_P2P |
116 | bool "iwlwifi experimental P2P support" | 116 | def_bool y |
117 | depends on IWLWIFI | 117 | bool "iwlwifi experimental P2P support" |
118 | help | 118 | depends on IWLWIFI |
119 | This option enables experimental P2P support for some devices | 119 | help |
120 | based on microcode support. Since P2P support is still under | 120 | This option enables experimental P2P support for some devices |
121 | development, this option may even enable it for some devices | 121 | based on microcode support. Since P2P support is still under |
122 | now that turn out to not support it in the future due to | 122 | development, this option may even enable it for some devices |
123 | microcode restrictions. | 123 | now that turn out to not support it in the future due to |
124 | 124 | microcode restrictions. | |
125 | To determine if your microcode supports the experimental P2P | 125 | |
126 | offered by this option, check if the driver advertises AP | 126 | To determine if your microcode supports the experimental P2P |
127 | support when it is loaded. | 127 | offered by this option, check if the driver advertises AP |
128 | 128 | support when it is loaded. | |
129 | Say Y only if you want to experiment with P2P. | 129 | |
130 | Say Y only if you want to experiment with P2P. | ||
130 | 131 | ||
131 | config IWLWIFI_EXPERIMENTAL_MFP | 132 | config IWLWIFI_EXPERIMENTAL_MFP |
132 | bool "support MFP (802.11w) even if uCode doesn't advertise" | 133 | bool "support MFP (802.11w) even if uCode doesn't advertise" |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index c7c4a995dfe5..f2cd67874cf4 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -7,7 +7,7 @@ iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o | |||
7 | 7 | ||
8 | iwlwifi-objs += iwl-core.o iwl-eeprom.o iwl-power.o | 8 | iwlwifi-objs += iwl-core.o iwl-eeprom.o iwl-power.o |
9 | iwlwifi-objs += iwl-scan.o iwl-led.o | 9 | iwlwifi-objs += iwl-scan.o iwl-led.o |
10 | iwlwifi-objs += iwl-agn-rxon.o | 10 | iwlwifi-objs += iwl-agn-rxon.o iwl-agn-devices.o |
11 | iwlwifi-objs += iwl-5000.o | 11 | iwlwifi-objs += iwl-5000.o |
12 | iwlwifi-objs += iwl-6000.o | 12 | iwlwifi-objs += iwl-6000.o |
13 | iwlwifi-objs += iwl-1000.o | 13 | iwlwifi-objs += iwl-1000.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 95c59e39b803..e9006078f4e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -24,26 +24,11 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/netdevice.h> | ||
33 | #include <net/mac80211.h> | ||
34 | #include <linux/etherdevice.h> | ||
35 | #include <asm/unaligned.h> | ||
36 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
37 | 29 | #include "iwl-config.h" | |
38 | #include "iwl-eeprom.h" | ||
39 | #include "iwl-dev.h" | ||
40 | #include "iwl-core.h" | ||
41 | #include "iwl-io.h" | ||
42 | #include "iwl-agn.h" | ||
43 | #include "iwl-agn-hw.h" | ||
44 | #include "iwl-shared.h" | ||
45 | #include "iwl-cfg.h" | 30 | #include "iwl-cfg.h" |
46 | #include "iwl-prph.h" | 31 | #include "iwl-dev.h" /* still needed */ |
47 | 32 | ||
48 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
49 | #define IWL1000_UCODE_API_MAX 6 | 34 | #define IWL1000_UCODE_API_MAX 6 |
@@ -64,97 +49,6 @@ | |||
64 | #define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode" | 49 | #define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode" |
65 | 50 | ||
66 | 51 | ||
67 | /* | ||
68 | * For 1000, use advance thermal throttling critical temperature threshold, | ||
69 | * but legacy thermal management implementation for now. | ||
70 | * This is for the reason of 1000 uCode using advance thermal throttling API | ||
71 | * but not implement ct_kill_exit based on ct_kill exit temperature | ||
72 | * so the thermal throttling will still based on legacy thermal throttling | ||
73 | * management. | ||
74 | * The code here need to be modified once 1000 uCode has the advanced thermal | ||
75 | * throttling algorithm in place | ||
76 | */ | ||
77 | static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | ||
78 | { | ||
79 | /* want Celsius */ | ||
80 | hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | ||
81 | hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
82 | } | ||
83 | |||
84 | /* NIC configuration for 1000 series */ | ||
85 | static void iwl1000_nic_config(struct iwl_priv *priv) | ||
86 | { | ||
87 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
88 | iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, | ||
89 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
90 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
91 | |||
92 | /* Setting digital SVR for 1000 card to 1.32V */ | ||
93 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | ||
94 | iwl_set_bits_mask_prph(trans(priv), APMG_DIGITAL_SVR_REG, | ||
95 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | ||
96 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | ||
97 | } | ||
98 | |||
99 | static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { | ||
100 | .min_nrg_cck = 95, | ||
101 | .auto_corr_min_ofdm = 90, | ||
102 | .auto_corr_min_ofdm_mrc = 170, | ||
103 | .auto_corr_min_ofdm_x1 = 120, | ||
104 | .auto_corr_min_ofdm_mrc_x1 = 240, | ||
105 | |||
106 | .auto_corr_max_ofdm = 120, | ||
107 | .auto_corr_max_ofdm_mrc = 210, | ||
108 | .auto_corr_max_ofdm_x1 = 155, | ||
109 | .auto_corr_max_ofdm_mrc_x1 = 290, | ||
110 | |||
111 | .auto_corr_min_cck = 125, | ||
112 | .auto_corr_max_cck = 200, | ||
113 | .auto_corr_min_cck_mrc = 170, | ||
114 | .auto_corr_max_cck_mrc = 400, | ||
115 | .nrg_th_cck = 95, | ||
116 | .nrg_th_ofdm = 95, | ||
117 | |||
118 | .barker_corr_th_min = 190, | ||
119 | .barker_corr_th_min_mrc = 390, | ||
120 | .nrg_th_cca = 62, | ||
121 | }; | ||
122 | |||
123 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | ||
124 | { | ||
125 | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
126 | |||
127 | hw_params(priv).tx_chains_num = | ||
128 | num_of_ant(hw_params(priv).valid_tx_ant); | ||
129 | if (cfg(priv)->rx_with_siso_diversity) | ||
130 | hw_params(priv).rx_chains_num = 1; | ||
131 | else | ||
132 | hw_params(priv).rx_chains_num = | ||
133 | num_of_ant(hw_params(priv).valid_rx_ant); | ||
134 | |||
135 | iwl1000_set_ct_threshold(priv); | ||
136 | |||
137 | /* Set initial sensitivity parameters */ | ||
138 | hw_params(priv).sens = &iwl1000_sensitivity; | ||
139 | } | ||
140 | |||
141 | static struct iwl_lib_ops iwl1000_lib = { | ||
142 | .set_hw_params = iwl1000_hw_set_hw_params, | ||
143 | .nic_config = iwl1000_nic_config, | ||
144 | .eeprom_ops = { | ||
145 | .regulatory_bands = { | ||
146 | EEPROM_REG_BAND_1_CHANNELS, | ||
147 | EEPROM_REG_BAND_2_CHANNELS, | ||
148 | EEPROM_REG_BAND_3_CHANNELS, | ||
149 | EEPROM_REG_BAND_4_CHANNELS, | ||
150 | EEPROM_REG_BAND_5_CHANNELS, | ||
151 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
152 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
153 | }, | ||
154 | }, | ||
155 | .temperature = iwlagn_temperature, | ||
156 | }; | ||
157 | |||
158 | static const struct iwl_base_params iwl1000_base_params = { | 52 | static const struct iwl_base_params iwl1000_base_params = { |
159 | .num_of_queues = IWLAGN_NUM_QUEUES, | 53 | .num_of_queues = IWLAGN_NUM_QUEUES, |
160 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 54 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
@@ -165,9 +59,8 @@ static const struct iwl_base_params iwl1000_base_params = { | |||
165 | .support_ct_kill_exit = true, | 59 | .support_ct_kill_exit = true, |
166 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 60 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
167 | .chain_noise_scale = 1000, | 61 | .chain_noise_scale = 1000, |
168 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 62 | .wd_timeout = IWL_WATCHHDOG_DISABLED, |
169 | .max_event_log_size = 128, | 63 | .max_event_log_size = 128, |
170 | .wd_disable = true, | ||
171 | }; | 64 | }; |
172 | 65 | ||
173 | static const struct iwl_ht_params iwl1000_ht_params = { | 66 | static const struct iwl_ht_params iwl1000_ht_params = { |
@@ -181,11 +74,11 @@ static const struct iwl_ht_params iwl1000_ht_params = { | |||
181 | .ucode_api_max = IWL1000_UCODE_API_MAX, \ | 74 | .ucode_api_max = IWL1000_UCODE_API_MAX, \ |
182 | .ucode_api_ok = IWL1000_UCODE_API_OK, \ | 75 | .ucode_api_ok = IWL1000_UCODE_API_OK, \ |
183 | .ucode_api_min = IWL1000_UCODE_API_MIN, \ | 76 | .ucode_api_min = IWL1000_UCODE_API_MIN, \ |
77 | .device_family = IWL_DEVICE_FAMILY_1000, \ | ||
184 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ | 78 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ |
185 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ | 79 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ |
186 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 80 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
187 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 81 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
188 | .lib = &iwl1000_lib, \ | ||
189 | .base_params = &iwl1000_base_params, \ | 82 | .base_params = &iwl1000_base_params, \ |
190 | .led_mode = IWL_LED_BLINK | 83 | .led_mode = IWL_LED_BLINK |
191 | 84 | ||
@@ -205,11 +98,11 @@ const struct iwl_cfg iwl1000_bg_cfg = { | |||
205 | .ucode_api_max = IWL100_UCODE_API_MAX, \ | 98 | .ucode_api_max = IWL100_UCODE_API_MAX, \ |
206 | .ucode_api_ok = IWL100_UCODE_API_OK, \ | 99 | .ucode_api_ok = IWL100_UCODE_API_OK, \ |
207 | .ucode_api_min = IWL100_UCODE_API_MIN, \ | 100 | .ucode_api_min = IWL100_UCODE_API_MIN, \ |
101 | .device_family = IWL_DEVICE_FAMILY_100, \ | ||
208 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ | 102 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ |
209 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ | 103 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ |
210 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 104 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
211 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 105 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
212 | .lib = &iwl1000_lib, \ | ||
213 | .base_params = &iwl1000_base_params, \ | 106 | .base_params = &iwl1000_base_params, \ |
214 | .led_mode = IWL_LED_RF_STATE, \ | 107 | .led_mode = IWL_LED_RF_STATE, \ |
215 | .rx_with_siso_diversity = true | 108 | .rx_with_siso_diversity = true |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e1329a13f0fd..3d4a36cf0408 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -24,25 +24,11 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/netdevice.h> | ||
33 | #include <net/mac80211.h> | ||
34 | #include <linux/etherdevice.h> | ||
35 | #include <asm/unaligned.h> | ||
36 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
37 | 29 | #include "iwl-config.h" | |
38 | #include "iwl-eeprom.h" | ||
39 | #include "iwl-dev.h" | ||
40 | #include "iwl-core.h" | ||
41 | #include "iwl-io.h" | ||
42 | #include "iwl-agn.h" | ||
43 | #include "iwl-agn-hw.h" | ||
44 | #include "iwl-shared.h" | ||
45 | #include "iwl-cfg.h" | 30 | #include "iwl-cfg.h" |
31 | #include "iwl-dev.h" /* still needed */ | ||
46 | 32 | ||
47 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
48 | #define IWL2030_UCODE_API_MAX 6 | 34 | #define IWL2030_UCODE_API_MAX 6 |
@@ -74,100 +60,6 @@ | |||
74 | #define IWL135_FW_PRE "iwlwifi-135-" | 60 | #define IWL135_FW_PRE "iwlwifi-135-" |
75 | #define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode" | 61 | #define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode" |
76 | 62 | ||
77 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | ||
78 | { | ||
79 | /* want Celsius */ | ||
80 | hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; | ||
81 | hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
82 | } | ||
83 | |||
84 | /* NIC configuration for 2000 series */ | ||
85 | static void iwl2000_nic_config(struct iwl_priv *priv) | ||
86 | { | ||
87 | iwl_rf_config(priv); | ||
88 | |||
89 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
90 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | ||
91 | } | ||
92 | |||
93 | static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | ||
94 | .min_nrg_cck = 97, | ||
95 | .auto_corr_min_ofdm = 80, | ||
96 | .auto_corr_min_ofdm_mrc = 128, | ||
97 | .auto_corr_min_ofdm_x1 = 105, | ||
98 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
99 | |||
100 | .auto_corr_max_ofdm = 145, | ||
101 | .auto_corr_max_ofdm_mrc = 232, | ||
102 | .auto_corr_max_ofdm_x1 = 110, | ||
103 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
104 | |||
105 | .auto_corr_min_cck = 125, | ||
106 | .auto_corr_max_cck = 175, | ||
107 | .auto_corr_min_cck_mrc = 160, | ||
108 | .auto_corr_max_cck_mrc = 310, | ||
109 | .nrg_th_cck = 97, | ||
110 | .nrg_th_ofdm = 100, | ||
111 | |||
112 | .barker_corr_th_min = 190, | ||
113 | .barker_corr_th_min_mrc = 390, | ||
114 | .nrg_th_cca = 62, | ||
115 | }; | ||
116 | |||
117 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | ||
118 | { | ||
119 | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
120 | |||
121 | hw_params(priv).tx_chains_num = | ||
122 | num_of_ant(hw_params(priv).valid_tx_ant); | ||
123 | if (cfg(priv)->rx_with_siso_diversity) | ||
124 | hw_params(priv).rx_chains_num = 1; | ||
125 | else | ||
126 | hw_params(priv).rx_chains_num = | ||
127 | num_of_ant(hw_params(priv).valid_rx_ant); | ||
128 | |||
129 | iwl2000_set_ct_threshold(priv); | ||
130 | |||
131 | /* Set initial sensitivity parameters */ | ||
132 | hw_params(priv).sens = &iwl2000_sensitivity; | ||
133 | } | ||
134 | |||
135 | static struct iwl_lib_ops iwl2000_lib = { | ||
136 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
137 | .nic_config = iwl2000_nic_config, | ||
138 | .eeprom_ops = { | ||
139 | .regulatory_bands = { | ||
140 | EEPROM_REG_BAND_1_CHANNELS, | ||
141 | EEPROM_REG_BAND_2_CHANNELS, | ||
142 | EEPROM_REG_BAND_3_CHANNELS, | ||
143 | EEPROM_REG_BAND_4_CHANNELS, | ||
144 | EEPROM_REG_BAND_5_CHANNELS, | ||
145 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
146 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
147 | }, | ||
148 | .enhanced_txpower = true, | ||
149 | }, | ||
150 | .temperature = iwlagn_temperature, | ||
151 | }; | ||
152 | |||
153 | static struct iwl_lib_ops iwl2030_lib = { | ||
154 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
155 | .nic_config = iwl2000_nic_config, | ||
156 | .eeprom_ops = { | ||
157 | .regulatory_bands = { | ||
158 | EEPROM_REG_BAND_1_CHANNELS, | ||
159 | EEPROM_REG_BAND_2_CHANNELS, | ||
160 | EEPROM_REG_BAND_3_CHANNELS, | ||
161 | EEPROM_REG_BAND_4_CHANNELS, | ||
162 | EEPROM_REG_BAND_5_CHANNELS, | ||
163 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
164 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
165 | }, | ||
166 | .enhanced_txpower = true, | ||
167 | }, | ||
168 | .temperature = iwlagn_temperature, | ||
169 | }; | ||
170 | |||
171 | static const struct iwl_base_params iwl2000_base_params = { | 63 | static const struct iwl_base_params iwl2000_base_params = { |
172 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 64 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
173 | .num_of_queues = IWLAGN_NUM_QUEUES, | 65 | .num_of_queues = IWLAGN_NUM_QUEUES, |
@@ -223,11 +115,11 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
223 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ | 115 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ |
224 | .ucode_api_ok = IWL2000_UCODE_API_OK, \ | 116 | .ucode_api_ok = IWL2000_UCODE_API_OK, \ |
225 | .ucode_api_min = IWL2000_UCODE_API_MIN, \ | 117 | .ucode_api_min = IWL2000_UCODE_API_MIN, \ |
118 | .device_family = IWL_DEVICE_FAMILY_2000, \ | ||
226 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 119 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
227 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 120 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
228 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 121 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
229 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 122 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
230 | .lib = &iwl2000_lib, \ | ||
231 | .base_params = &iwl2000_base_params, \ | 123 | .base_params = &iwl2000_base_params, \ |
232 | .need_temp_offset_calib = true, \ | 124 | .need_temp_offset_calib = true, \ |
233 | .temp_offset_v2 = true, \ | 125 | .temp_offset_v2 = true, \ |
@@ -250,11 +142,11 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
250 | .ucode_api_max = IWL2030_UCODE_API_MAX, \ | 142 | .ucode_api_max = IWL2030_UCODE_API_MAX, \ |
251 | .ucode_api_ok = IWL2030_UCODE_API_OK, \ | 143 | .ucode_api_ok = IWL2030_UCODE_API_OK, \ |
252 | .ucode_api_min = IWL2030_UCODE_API_MIN, \ | 144 | .ucode_api_min = IWL2030_UCODE_API_MIN, \ |
145 | .device_family = IWL_DEVICE_FAMILY_2030, \ | ||
253 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 146 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
254 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 147 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
255 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 148 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
256 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 149 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
257 | .lib = &iwl2030_lib, \ | ||
258 | .base_params = &iwl2030_base_params, \ | 150 | .base_params = &iwl2030_base_params, \ |
259 | .bt_params = &iwl2030_bt_params, \ | 151 | .bt_params = &iwl2030_bt_params, \ |
260 | .need_temp_offset_calib = true, \ | 152 | .need_temp_offset_calib = true, \ |
@@ -273,11 +165,11 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
273 | .ucode_api_max = IWL105_UCODE_API_MAX, \ | 165 | .ucode_api_max = IWL105_UCODE_API_MAX, \ |
274 | .ucode_api_ok = IWL105_UCODE_API_OK, \ | 166 | .ucode_api_ok = IWL105_UCODE_API_OK, \ |
275 | .ucode_api_min = IWL105_UCODE_API_MIN, \ | 167 | .ucode_api_min = IWL105_UCODE_API_MIN, \ |
168 | .device_family = IWL_DEVICE_FAMILY_105, \ | ||
276 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 169 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
277 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 170 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
278 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 171 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
279 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 172 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
280 | .lib = &iwl2000_lib, \ | ||
281 | .base_params = &iwl2000_base_params, \ | 173 | .base_params = &iwl2000_base_params, \ |
282 | .need_temp_offset_calib = true, \ | 174 | .need_temp_offset_calib = true, \ |
283 | .temp_offset_v2 = true, \ | 175 | .temp_offset_v2 = true, \ |
@@ -302,11 +194,11 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
302 | .ucode_api_max = IWL135_UCODE_API_MAX, \ | 194 | .ucode_api_max = IWL135_UCODE_API_MAX, \ |
303 | .ucode_api_ok = IWL135_UCODE_API_OK, \ | 195 | .ucode_api_ok = IWL135_UCODE_API_OK, \ |
304 | .ucode_api_min = IWL135_UCODE_API_MIN, \ | 196 | .ucode_api_min = IWL135_UCODE_API_MIN, \ |
197 | .device_family = IWL_DEVICE_FAMILY_135, \ | ||
305 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 198 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
306 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 199 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
307 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 200 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
308 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 201 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
309 | .lib = &iwl2030_lib, \ | ||
310 | .base_params = &iwl2030_base_params, \ | 202 | .base_params = &iwl2030_base_params, \ |
311 | .bt_params = &iwl2030_bt_params, \ | 203 | .bt_params = &iwl2030_bt_params, \ |
312 | .need_temp_offset_calib = true, \ | 204 | .need_temp_offset_calib = true, \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 34bc8dd0064b..ffa9ac5fe086 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -24,28 +24,11 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | #include <linux/netdevice.h> | ||
34 | #include <net/mac80211.h> | ||
35 | #include <linux/etherdevice.h> | ||
36 | #include <asm/unaligned.h> | ||
37 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
38 | 29 | #include "iwl-config.h" | |
39 | #include "iwl-eeprom.h" | ||
40 | #include "iwl-dev.h" | ||
41 | #include "iwl-core.h" | ||
42 | #include "iwl-io.h" | ||
43 | #include "iwl-agn.h" | ||
44 | #include "iwl-agn-hw.h" | ||
45 | #include "iwl-trans.h" | ||
46 | #include "iwl-shared.h" | ||
47 | #include "iwl-cfg.h" | 30 | #include "iwl-cfg.h" |
48 | #include "iwl-prph.h" | 31 | #include "iwl-dev.h" /* still needed */ |
49 | 32 | ||
50 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
51 | #define IWL5000_UCODE_API_MAX 5 | 34 | #define IWL5000_UCODE_API_MAX 5 |
@@ -61,250 +44,6 @@ | |||
61 | #define IWL5150_FW_PRE "iwlwifi-5150-" | 44 | #define IWL5150_FW_PRE "iwlwifi-5150-" |
62 | #define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode" | 45 | #define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode" |
63 | 46 | ||
64 | /* NIC configuration for 5000 series */ | ||
65 | static void iwl5000_nic_config(struct iwl_priv *priv) | ||
66 | { | ||
67 | iwl_rf_config(priv); | ||
68 | |||
69 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | ||
70 | * (PCIe power is lost before PERST# is asserted), | ||
71 | * causing ME FW to lose ownership and not being able to obtain it back. | ||
72 | */ | ||
73 | iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG, | ||
74 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | ||
75 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | ||
76 | } | ||
77 | |||
78 | static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { | ||
79 | .min_nrg_cck = 100, | ||
80 | .auto_corr_min_ofdm = 90, | ||
81 | .auto_corr_min_ofdm_mrc = 170, | ||
82 | .auto_corr_min_ofdm_x1 = 105, | ||
83 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
84 | |||
85 | .auto_corr_max_ofdm = 120, | ||
86 | .auto_corr_max_ofdm_mrc = 210, | ||
87 | .auto_corr_max_ofdm_x1 = 120, | ||
88 | .auto_corr_max_ofdm_mrc_x1 = 240, | ||
89 | |||
90 | .auto_corr_min_cck = 125, | ||
91 | .auto_corr_max_cck = 200, | ||
92 | .auto_corr_min_cck_mrc = 200, | ||
93 | .auto_corr_max_cck_mrc = 400, | ||
94 | .nrg_th_cck = 100, | ||
95 | .nrg_th_ofdm = 100, | ||
96 | |||
97 | .barker_corr_th_min = 190, | ||
98 | .barker_corr_th_min_mrc = 390, | ||
99 | .nrg_th_cca = 62, | ||
100 | }; | ||
101 | |||
102 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | ||
103 | .min_nrg_cck = 95, | ||
104 | .auto_corr_min_ofdm = 90, | ||
105 | .auto_corr_min_ofdm_mrc = 170, | ||
106 | .auto_corr_min_ofdm_x1 = 105, | ||
107 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
108 | |||
109 | .auto_corr_max_ofdm = 120, | ||
110 | .auto_corr_max_ofdm_mrc = 210, | ||
111 | /* max = min for performance bug in 5150 DSP */ | ||
112 | .auto_corr_max_ofdm_x1 = 105, | ||
113 | .auto_corr_max_ofdm_mrc_x1 = 220, | ||
114 | |||
115 | .auto_corr_min_cck = 125, | ||
116 | .auto_corr_max_cck = 200, | ||
117 | .auto_corr_min_cck_mrc = 170, | ||
118 | .auto_corr_max_cck_mrc = 400, | ||
119 | .nrg_th_cck = 95, | ||
120 | .nrg_th_ofdm = 95, | ||
121 | |||
122 | .barker_corr_th_min = 190, | ||
123 | .barker_corr_th_min_mrc = 390, | ||
124 | .nrg_th_cca = 62, | ||
125 | }; | ||
126 | |||
127 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | ||
128 | |||
129 | static s32 iwl_temp_calib_to_offset(struct iwl_shared *shrd) | ||
130 | { | ||
131 | u16 temperature, voltage; | ||
132 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(shrd, | ||
133 | EEPROM_KELVIN_TEMPERATURE); | ||
134 | |||
135 | temperature = le16_to_cpu(temp_calib[0]); | ||
136 | voltage = le16_to_cpu(temp_calib[1]); | ||
137 | |||
138 | /* offset = temp - volt / coeff */ | ||
139 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | ||
140 | } | ||
141 | |||
142 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | ||
143 | { | ||
144 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | ||
145 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - | ||
146 | iwl_temp_calib_to_offset(priv->shrd); | ||
147 | |||
148 | hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; | ||
149 | } | ||
150 | |||
151 | static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | ||
152 | { | ||
153 | /* want Celsius */ | ||
154 | hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | ||
155 | } | ||
156 | |||
157 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||
158 | { | ||
159 | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
160 | BIT(IEEE80211_BAND_5GHZ); | ||
161 | |||
162 | hw_params(priv).tx_chains_num = | ||
163 | num_of_ant(hw_params(priv).valid_tx_ant); | ||
164 | hw_params(priv).rx_chains_num = | ||
165 | num_of_ant(hw_params(priv).valid_rx_ant); | ||
166 | |||
167 | iwl5000_set_ct_threshold(priv); | ||
168 | |||
169 | /* Set initial sensitivity parameters */ | ||
170 | hw_params(priv).sens = &iwl5000_sensitivity; | ||
171 | } | ||
172 | |||
173 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | ||
174 | { | ||
175 | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
176 | BIT(IEEE80211_BAND_5GHZ); | ||
177 | |||
178 | hw_params(priv).tx_chains_num = | ||
179 | num_of_ant(hw_params(priv).valid_tx_ant); | ||
180 | hw_params(priv).rx_chains_num = | ||
181 | num_of_ant(hw_params(priv).valid_rx_ant); | ||
182 | |||
183 | iwl5150_set_ct_threshold(priv); | ||
184 | |||
185 | /* Set initial sensitivity parameters */ | ||
186 | hw_params(priv).sens = &iwl5150_sensitivity; | ||
187 | } | ||
188 | |||
189 | static void iwl5150_temperature(struct iwl_priv *priv) | ||
190 | { | ||
191 | u32 vt = 0; | ||
192 | s32 offset = iwl_temp_calib_to_offset(priv->shrd); | ||
193 | |||
194 | vt = le32_to_cpu(priv->statistics.common.temperature); | ||
195 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | ||
196 | /* now vt hold the temperature in Kelvin */ | ||
197 | priv->temperature = KELVIN_TO_CELSIUS(vt); | ||
198 | iwl_tt_handler(priv); | ||
199 | } | ||
200 | |||
201 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | ||
202 | struct ieee80211_channel_switch *ch_switch) | ||
203 | { | ||
204 | /* | ||
205 | * MULTI-FIXME | ||
206 | * See iwlagn_mac_channel_switch. | ||
207 | */ | ||
208 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
209 | struct iwl5000_channel_switch_cmd cmd; | ||
210 | const struct iwl_channel_info *ch_info; | ||
211 | u32 switch_time_in_usec, ucode_switch_time; | ||
212 | u16 ch; | ||
213 | u32 tsf_low; | ||
214 | u8 switch_count; | ||
215 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
216 | struct ieee80211_vif *vif = ctx->vif; | ||
217 | struct iwl_host_cmd hcmd = { | ||
218 | .id = REPLY_CHANNEL_SWITCH, | ||
219 | .len = { sizeof(cmd), }, | ||
220 | .flags = CMD_SYNC, | ||
221 | .data = { &cmd, }, | ||
222 | }; | ||
223 | |||
224 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
225 | ch = ch_switch->channel->hw_value; | ||
226 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
227 | ctx->active.channel, ch); | ||
228 | cmd.channel = cpu_to_le16(ch); | ||
229 | cmd.rxon_flags = ctx->staging.flags; | ||
230 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
231 | switch_count = ch_switch->count; | ||
232 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
233 | /* | ||
234 | * calculate the ucode channel switch time | ||
235 | * adding TSF as one of the factor for when to switch | ||
236 | */ | ||
237 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
238 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
239 | beacon_interval)) { | ||
240 | switch_count -= (priv->ucode_beacon_time - | ||
241 | tsf_low) / beacon_interval; | ||
242 | } else | ||
243 | switch_count = 0; | ||
244 | } | ||
245 | if (switch_count <= 1) | ||
246 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
247 | else { | ||
248 | switch_time_in_usec = | ||
249 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
250 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
251 | switch_time_in_usec, | ||
252 | beacon_interval); | ||
253 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
254 | priv->ucode_beacon_time, | ||
255 | ucode_switch_time, | ||
256 | beacon_interval); | ||
257 | } | ||
258 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
259 | cmd.switch_time); | ||
260 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
261 | if (ch_info) | ||
262 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
263 | else { | ||
264 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
265 | ctx->active.channel, ch); | ||
266 | return -EFAULT; | ||
267 | } | ||
268 | |||
269 | return iwl_dvm_send_cmd(priv, &hcmd); | ||
270 | } | ||
271 | |||
272 | static struct iwl_lib_ops iwl5000_lib = { | ||
273 | .set_hw_params = iwl5000_hw_set_hw_params, | ||
274 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
275 | .nic_config = iwl5000_nic_config, | ||
276 | .eeprom_ops = { | ||
277 | .regulatory_bands = { | ||
278 | EEPROM_REG_BAND_1_CHANNELS, | ||
279 | EEPROM_REG_BAND_2_CHANNELS, | ||
280 | EEPROM_REG_BAND_3_CHANNELS, | ||
281 | EEPROM_REG_BAND_4_CHANNELS, | ||
282 | EEPROM_REG_BAND_5_CHANNELS, | ||
283 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
284 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
285 | }, | ||
286 | }, | ||
287 | .temperature = iwlagn_temperature, | ||
288 | }; | ||
289 | |||
290 | static struct iwl_lib_ops iwl5150_lib = { | ||
291 | .set_hw_params = iwl5150_hw_set_hw_params, | ||
292 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
293 | .nic_config = iwl5000_nic_config, | ||
294 | .eeprom_ops = { | ||
295 | .regulatory_bands = { | ||
296 | EEPROM_REG_BAND_1_CHANNELS, | ||
297 | EEPROM_REG_BAND_2_CHANNELS, | ||
298 | EEPROM_REG_BAND_3_CHANNELS, | ||
299 | EEPROM_REG_BAND_4_CHANNELS, | ||
300 | EEPROM_REG_BAND_5_CHANNELS, | ||
301 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
302 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
303 | }, | ||
304 | }, | ||
305 | .temperature = iwl5150_temperature, | ||
306 | }; | ||
307 | |||
308 | static const struct iwl_base_params iwl5000_base_params = { | 47 | static const struct iwl_base_params iwl5000_base_params = { |
309 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 48 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
310 | .num_of_queues = IWLAGN_NUM_QUEUES, | 49 | .num_of_queues = IWLAGN_NUM_QUEUES, |
@@ -312,10 +51,9 @@ static const struct iwl_base_params iwl5000_base_params = { | |||
312 | .led_compensation = 51, | 51 | .led_compensation = 51, |
313 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 52 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
314 | .chain_noise_scale = 1000, | 53 | .chain_noise_scale = 1000, |
315 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 54 | .wd_timeout = IWL_WATCHHDOG_DISABLED, |
316 | .max_event_log_size = 512, | 55 | .max_event_log_size = 512, |
317 | .no_idle_support = true, | 56 | .no_idle_support = true, |
318 | .wd_disable = true, | ||
319 | }; | 57 | }; |
320 | 58 | ||
321 | static const struct iwl_ht_params iwl5000_ht_params = { | 59 | static const struct iwl_ht_params iwl5000_ht_params = { |
@@ -326,11 +64,11 @@ static const struct iwl_ht_params iwl5000_ht_params = { | |||
326 | .fw_name_pre = IWL5000_FW_PRE, \ | 64 | .fw_name_pre = IWL5000_FW_PRE, \ |
327 | .ucode_api_max = IWL5000_UCODE_API_MAX, \ | 65 | .ucode_api_max = IWL5000_UCODE_API_MAX, \ |
328 | .ucode_api_min = IWL5000_UCODE_API_MIN, \ | 66 | .ucode_api_min = IWL5000_UCODE_API_MIN, \ |
67 | .device_family = IWL_DEVICE_FAMILY_5000, \ | ||
329 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ | 68 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ |
330 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ | 69 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ |
331 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ | 70 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ |
332 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ | 71 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ |
333 | .lib = &iwl5000_lib, \ | ||
334 | .base_params = &iwl5000_base_params, \ | 72 | .base_params = &iwl5000_base_params, \ |
335 | .led_mode = IWL_LED_BLINK | 73 | .led_mode = IWL_LED_BLINK |
336 | 74 | ||
@@ -371,11 +109,11 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
371 | .fw_name_pre = IWL5000_FW_PRE, | 109 | .fw_name_pre = IWL5000_FW_PRE, |
372 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 110 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
373 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 111 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
112 | .device_family = IWL_DEVICE_FAMILY_5000, | ||
374 | .max_inst_size = IWLAGN_RTC_INST_SIZE, | 113 | .max_inst_size = IWLAGN_RTC_INST_SIZE, |
375 | .max_data_size = IWLAGN_RTC_DATA_SIZE, | 114 | .max_data_size = IWLAGN_RTC_DATA_SIZE, |
376 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 115 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
377 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 116 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
378 | .lib = &iwl5000_lib, | ||
379 | .base_params = &iwl5000_base_params, | 117 | .base_params = &iwl5000_base_params, |
380 | .ht_params = &iwl5000_ht_params, | 118 | .ht_params = &iwl5000_ht_params, |
381 | .led_mode = IWL_LED_BLINK, | 119 | .led_mode = IWL_LED_BLINK, |
@@ -386,11 +124,11 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
386 | .fw_name_pre = IWL5150_FW_PRE, \ | 124 | .fw_name_pre = IWL5150_FW_PRE, \ |
387 | .ucode_api_max = IWL5150_UCODE_API_MAX, \ | 125 | .ucode_api_max = IWL5150_UCODE_API_MAX, \ |
388 | .ucode_api_min = IWL5150_UCODE_API_MIN, \ | 126 | .ucode_api_min = IWL5150_UCODE_API_MIN, \ |
127 | .device_family = IWL_DEVICE_FAMILY_5150, \ | ||
389 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ | 128 | .max_inst_size = IWLAGN_RTC_INST_SIZE, \ |
390 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ | 129 | .max_data_size = IWLAGN_RTC_DATA_SIZE, \ |
391 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ | 130 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ |
392 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ | 131 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ |
393 | .lib = &iwl5150_lib, \ | ||
394 | .base_params = &iwl5000_base_params, \ | 132 | .base_params = &iwl5000_base_params, \ |
395 | .no_xtal_calib = true, \ | 133 | .no_xtal_calib = true, \ |
396 | .led_mode = IWL_LED_BLINK, \ | 134 | .led_mode = IWL_LED_BLINK, \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7075570a0f2c..00da2520a4b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -24,26 +24,11 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | #include <linux/netdevice.h> | ||
33 | #include <net/mac80211.h> | ||
34 | #include <linux/etherdevice.h> | ||
35 | #include <asm/unaligned.h> | ||
36 | #include <linux/stringify.h> | 28 | #include <linux/stringify.h> |
37 | 29 | #include "iwl-config.h" | |
38 | #include "iwl-eeprom.h" | ||
39 | #include "iwl-dev.h" | ||
40 | #include "iwl-core.h" | ||
41 | #include "iwl-io.h" | ||
42 | #include "iwl-agn.h" | ||
43 | #include "iwl-agn-hw.h" | ||
44 | #include "iwl-trans.h" | ||
45 | #include "iwl-shared.h" | ||
46 | #include "iwl-cfg.h" | 30 | #include "iwl-cfg.h" |
31 | #include "iwl-dev.h" /* still needed */ | ||
47 | 32 | ||
48 | /* Highest firmware API version supported */ | 33 | /* Highest firmware API version supported */ |
49 | #define IWL6000_UCODE_API_MAX 6 | 34 | #define IWL6000_UCODE_API_MAX 6 |
@@ -71,201 +56,6 @@ | |||
71 | #define IWL6030_FW_PRE "iwlwifi-6000g2b-" | 56 | #define IWL6030_FW_PRE "iwlwifi-6000g2b-" |
72 | #define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode" | 57 | #define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode" |
73 | 58 | ||
74 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | ||
75 | { | ||
76 | /* want Celsius */ | ||
77 | hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; | ||
78 | hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
79 | } | ||
80 | |||
81 | static void iwl6050_additional_nic_config(struct iwl_priv *priv) | ||
82 | { | ||
83 | /* Indicate calibration version to uCode. */ | ||
84 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) | ||
85 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
86 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
87 | } | ||
88 | |||
89 | static void iwl6150_additional_nic_config(struct iwl_priv *priv) | ||
90 | { | ||
91 | /* Indicate calibration version to uCode. */ | ||
92 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) | ||
93 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
94 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
95 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
96 | CSR_GP_DRIVER_REG_BIT_6050_1x2); | ||
97 | } | ||
98 | |||
99 | static void iwl6000i_additional_nic_config(struct iwl_priv *priv) | ||
100 | { | ||
101 | /* 2x2 IPA phy type */ | ||
102 | iwl_write32(trans(priv), CSR_GP_DRIVER_REG, | ||
103 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | ||
104 | } | ||
105 | |||
106 | /* NIC configuration for 6000 series */ | ||
107 | static void iwl6000_nic_config(struct iwl_priv *priv) | ||
108 | { | ||
109 | iwl_rf_config(priv); | ||
110 | |||
111 | /* do additional nic configuration if needed */ | ||
112 | if (cfg(priv)->additional_nic_config) | ||
113 | cfg(priv)->additional_nic_config(priv); | ||
114 | } | ||
115 | |||
116 | static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | ||
117 | .min_nrg_cck = 110, | ||
118 | .auto_corr_min_ofdm = 80, | ||
119 | .auto_corr_min_ofdm_mrc = 128, | ||
120 | .auto_corr_min_ofdm_x1 = 105, | ||
121 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
122 | |||
123 | .auto_corr_max_ofdm = 145, | ||
124 | .auto_corr_max_ofdm_mrc = 232, | ||
125 | .auto_corr_max_ofdm_x1 = 110, | ||
126 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
127 | |||
128 | .auto_corr_min_cck = 125, | ||
129 | .auto_corr_max_cck = 175, | ||
130 | .auto_corr_min_cck_mrc = 160, | ||
131 | .auto_corr_max_cck_mrc = 310, | ||
132 | .nrg_th_cck = 110, | ||
133 | .nrg_th_ofdm = 110, | ||
134 | |||
135 | .barker_corr_th_min = 190, | ||
136 | .barker_corr_th_min_mrc = 336, | ||
137 | .nrg_th_cca = 62, | ||
138 | }; | ||
139 | |||
140 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | ||
141 | { | ||
142 | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
143 | BIT(IEEE80211_BAND_5GHZ); | ||
144 | |||
145 | hw_params(priv).tx_chains_num = | ||
146 | num_of_ant(hw_params(priv).valid_tx_ant); | ||
147 | if (cfg(priv)->rx_with_siso_diversity) | ||
148 | hw_params(priv).rx_chains_num = 1; | ||
149 | else | ||
150 | hw_params(priv).rx_chains_num = | ||
151 | num_of_ant(hw_params(priv).valid_rx_ant); | ||
152 | |||
153 | iwl6000_set_ct_threshold(priv); | ||
154 | |||
155 | /* Set initial sensitivity parameters */ | ||
156 | hw_params(priv).sens = &iwl6000_sensitivity; | ||
157 | |||
158 | } | ||
159 | |||
160 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | ||
161 | struct ieee80211_channel_switch *ch_switch) | ||
162 | { | ||
163 | /* | ||
164 | * MULTI-FIXME | ||
165 | * See iwlagn_mac_channel_switch. | ||
166 | */ | ||
167 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
168 | struct iwl6000_channel_switch_cmd cmd; | ||
169 | const struct iwl_channel_info *ch_info; | ||
170 | u32 switch_time_in_usec, ucode_switch_time; | ||
171 | u16 ch; | ||
172 | u32 tsf_low; | ||
173 | u8 switch_count; | ||
174 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
175 | struct ieee80211_vif *vif = ctx->vif; | ||
176 | struct iwl_host_cmd hcmd = { | ||
177 | .id = REPLY_CHANNEL_SWITCH, | ||
178 | .len = { sizeof(cmd), }, | ||
179 | .flags = CMD_SYNC, | ||
180 | .data = { &cmd, }, | ||
181 | }; | ||
182 | |||
183 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
184 | ch = ch_switch->channel->hw_value; | ||
185 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | ||
186 | ctx->active.channel, ch); | ||
187 | cmd.channel = cpu_to_le16(ch); | ||
188 | cmd.rxon_flags = ctx->staging.flags; | ||
189 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
190 | switch_count = ch_switch->count; | ||
191 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
192 | /* | ||
193 | * calculate the ucode channel switch time | ||
194 | * adding TSF as one of the factor for when to switch | ||
195 | */ | ||
196 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
197 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
198 | beacon_interval)) { | ||
199 | switch_count -= (priv->ucode_beacon_time - | ||
200 | tsf_low) / beacon_interval; | ||
201 | } else | ||
202 | switch_count = 0; | ||
203 | } | ||
204 | if (switch_count <= 1) | ||
205 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
206 | else { | ||
207 | switch_time_in_usec = | ||
208 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
209 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
210 | switch_time_in_usec, | ||
211 | beacon_interval); | ||
212 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
213 | priv->ucode_beacon_time, | ||
214 | ucode_switch_time, | ||
215 | beacon_interval); | ||
216 | } | ||
217 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
218 | cmd.switch_time); | ||
219 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
220 | if (ch_info) | ||
221 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
222 | else { | ||
223 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
224 | ctx->active.channel, ch); | ||
225 | return -EFAULT; | ||
226 | } | ||
227 | |||
228 | return iwl_dvm_send_cmd(priv, &hcmd); | ||
229 | } | ||
230 | |||
231 | static struct iwl_lib_ops iwl6000_lib = { | ||
232 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
233 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
234 | .nic_config = iwl6000_nic_config, | ||
235 | .eeprom_ops = { | ||
236 | .regulatory_bands = { | ||
237 | EEPROM_REG_BAND_1_CHANNELS, | ||
238 | EEPROM_REG_BAND_2_CHANNELS, | ||
239 | EEPROM_REG_BAND_3_CHANNELS, | ||
240 | EEPROM_REG_BAND_4_CHANNELS, | ||
241 | EEPROM_REG_BAND_5_CHANNELS, | ||
242 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
243 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
244 | }, | ||
245 | .enhanced_txpower = true, | ||
246 | }, | ||
247 | .temperature = iwlagn_temperature, | ||
248 | }; | ||
249 | |||
250 | static struct iwl_lib_ops iwl6030_lib = { | ||
251 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
252 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
253 | .nic_config = iwl6000_nic_config, | ||
254 | .eeprom_ops = { | ||
255 | .regulatory_bands = { | ||
256 | EEPROM_REG_BAND_1_CHANNELS, | ||
257 | EEPROM_REG_BAND_2_CHANNELS, | ||
258 | EEPROM_REG_BAND_3_CHANNELS, | ||
259 | EEPROM_REG_BAND_4_CHANNELS, | ||
260 | EEPROM_REG_BAND_5_CHANNELS, | ||
261 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
262 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
263 | }, | ||
264 | .enhanced_txpower = true, | ||
265 | }, | ||
266 | .temperature = iwlagn_temperature, | ||
267 | }; | ||
268 | |||
269 | static const struct iwl_base_params iwl6000_base_params = { | 59 | static const struct iwl_base_params iwl6000_base_params = { |
270 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 60 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
271 | .num_of_queues = IWLAGN_NUM_QUEUES, | 61 | .num_of_queues = IWLAGN_NUM_QUEUES, |
@@ -333,11 +123,11 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
333 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 123 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
334 | .ucode_api_ok = IWL6000G2_UCODE_API_OK, \ | 124 | .ucode_api_ok = IWL6000G2_UCODE_API_OK, \ |
335 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ | 125 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ |
126 | .device_family = IWL_DEVICE_FAMILY_6005, \ | ||
336 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 127 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
337 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 128 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
338 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ | 129 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ |
339 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ | 130 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
340 | .lib = &iwl6000_lib, \ | ||
341 | .base_params = &iwl6000_g2_base_params, \ | 131 | .base_params = &iwl6000_g2_base_params, \ |
342 | .need_temp_offset_calib = true, \ | 132 | .need_temp_offset_calib = true, \ |
343 | .led_mode = IWL_LED_RF_STATE | 133 | .led_mode = IWL_LED_RF_STATE |
@@ -387,11 +177,11 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | |||
387 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 177 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
388 | .ucode_api_ok = IWL6000G2_UCODE_API_OK, \ | 178 | .ucode_api_ok = IWL6000G2_UCODE_API_OK, \ |
389 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ | 179 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ |
180 | .device_family = IWL_DEVICE_FAMILY_6030, \ | ||
390 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 181 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
391 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 182 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
392 | .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ | 183 | .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ |
393 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 184 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
394 | .lib = &iwl6030_lib, \ | ||
395 | .base_params = &iwl6000_g2_base_params, \ | 185 | .base_params = &iwl6000_g2_base_params, \ |
396 | .bt_params = &iwl6000_bt_params, \ | 186 | .bt_params = &iwl6000_bt_params, \ |
397 | .need_temp_offset_calib = true, \ | 187 | .need_temp_offset_calib = true, \ |
@@ -458,14 +248,13 @@ const struct iwl_cfg iwl130_bg_cfg = { | |||
458 | .ucode_api_max = IWL6000_UCODE_API_MAX, \ | 248 | .ucode_api_max = IWL6000_UCODE_API_MAX, \ |
459 | .ucode_api_ok = IWL6000_UCODE_API_OK, \ | 249 | .ucode_api_ok = IWL6000_UCODE_API_OK, \ |
460 | .ucode_api_min = IWL6000_UCODE_API_MIN, \ | 250 | .ucode_api_min = IWL6000_UCODE_API_MIN, \ |
251 | .device_family = IWL_DEVICE_FAMILY_6000i, \ | ||
461 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 252 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
462 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 253 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
463 | .valid_tx_ant = ANT_BC, /* .cfg overwrite */ \ | 254 | .valid_tx_ant = ANT_BC, /* .cfg overwrite */ \ |
464 | .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ | 255 | .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ |
465 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ | 256 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ |
466 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ | 257 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ |
467 | .lib = &iwl6000_lib, \ | ||
468 | .additional_nic_config = iwl6000i_additional_nic_config,\ | ||
469 | .base_params = &iwl6000_base_params, \ | 258 | .base_params = &iwl6000_base_params, \ |
470 | .led_mode = IWL_LED_BLINK | 259 | .led_mode = IWL_LED_BLINK |
471 | 260 | ||
@@ -489,12 +278,11 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { | |||
489 | .fw_name_pre = IWL6050_FW_PRE, \ | 278 | .fw_name_pre = IWL6050_FW_PRE, \ |
490 | .ucode_api_max = IWL6050_UCODE_API_MAX, \ | 279 | .ucode_api_max = IWL6050_UCODE_API_MAX, \ |
491 | .ucode_api_min = IWL6050_UCODE_API_MIN, \ | 280 | .ucode_api_min = IWL6050_UCODE_API_MIN, \ |
281 | .device_family = IWL_DEVICE_FAMILY_6050, \ | ||
492 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 282 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
493 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 283 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
494 | .valid_tx_ant = ANT_AB, /* .cfg overwrite */ \ | 284 | .valid_tx_ant = ANT_AB, /* .cfg overwrite */ \ |
495 | .valid_rx_ant = ANT_AB, /* .cfg overwrite */ \ | 285 | .valid_rx_ant = ANT_AB, /* .cfg overwrite */ \ |
496 | .lib = &iwl6000_lib, \ | ||
497 | .additional_nic_config = iwl6050_additional_nic_config, \ | ||
498 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ | 286 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ |
499 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ | 287 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ |
500 | .base_params = &iwl6050_base_params, \ | 288 | .base_params = &iwl6050_base_params, \ |
@@ -516,10 +304,9 @@ const struct iwl_cfg iwl6050_2abg_cfg = { | |||
516 | .fw_name_pre = IWL6050_FW_PRE, \ | 304 | .fw_name_pre = IWL6050_FW_PRE, \ |
517 | .ucode_api_max = IWL6050_UCODE_API_MAX, \ | 305 | .ucode_api_max = IWL6050_UCODE_API_MAX, \ |
518 | .ucode_api_min = IWL6050_UCODE_API_MIN, \ | 306 | .ucode_api_min = IWL6050_UCODE_API_MIN, \ |
307 | .device_family = IWL_DEVICE_FAMILY_6150, \ | ||
519 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 308 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
520 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 309 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
521 | .lib = &iwl6000_lib, \ | ||
522 | .additional_nic_config = iwl6150_additional_nic_config, \ | ||
523 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ | 310 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ |
524 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ | 311 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ |
525 | .base_params = &iwl6050_base_params, \ | 312 | .base_params = &iwl6050_base_params, \ |
@@ -543,11 +330,11 @@ const struct iwl_cfg iwl6000_3agn_cfg = { | |||
543 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 330 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
544 | .ucode_api_ok = IWL6000_UCODE_API_OK, | 331 | .ucode_api_ok = IWL6000_UCODE_API_OK, |
545 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 332 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
333 | .device_family = IWL_DEVICE_FAMILY_6000, | ||
546 | .max_inst_size = IWL60_RTC_INST_SIZE, | 334 | .max_inst_size = IWL60_RTC_INST_SIZE, |
547 | .max_data_size = IWL60_RTC_DATA_SIZE, | 335 | .max_data_size = IWL60_RTC_DATA_SIZE, |
548 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 336 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
549 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 337 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
550 | .lib = &iwl6000_lib, | ||
551 | .base_params = &iwl6000_base_params, | 338 | .base_params = &iwl6000_base_params, |
552 | .ht_params = &iwl6000_ht_params, | 339 | .ht_params = &iwl6000_ht_params, |
553 | .led_mode = IWL_LED_BLINK, | 340 | .led_mode = IWL_LED_BLINK, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 84cbe7bb504c..61c243f7395f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -190,7 +190,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, | |||
190 | u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; | 190 | u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; |
191 | u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; | 191 | u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; |
192 | struct iwl_sensitivity_data *data = NULL; | 192 | struct iwl_sensitivity_data *data = NULL; |
193 | const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; | 193 | const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; |
194 | 194 | ||
195 | data = &(priv->sensitivity_data); | 195 | data = &(priv->sensitivity_data); |
196 | 196 | ||
@@ -373,7 +373,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, | |||
373 | u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; | 373 | u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; |
374 | u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; | 374 | u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; |
375 | struct iwl_sensitivity_data *data = NULL; | 375 | struct iwl_sensitivity_data *data = NULL; |
376 | const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; | 376 | const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; |
377 | 377 | ||
378 | data = &(priv->sensitivity_data); | 378 | data = &(priv->sensitivity_data); |
379 | 379 | ||
@@ -597,9 +597,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
597 | int ret = 0; | 597 | int ret = 0; |
598 | int i; | 598 | int i; |
599 | struct iwl_sensitivity_data *data = NULL; | 599 | struct iwl_sensitivity_data *data = NULL; |
600 | const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; | 600 | const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; |
601 | 601 | ||
602 | if (priv->disable_sens_cal) | 602 | if (priv->calib_disabled & IWL_SENSITIVITY_CALIB_DISABLED) |
603 | return; | 603 | return; |
604 | 604 | ||
605 | IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n"); | 605 | IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n"); |
@@ -663,7 +663,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) | |||
663 | struct statistics_rx_phy *ofdm, *cck; | 663 | struct statistics_rx_phy *ofdm, *cck; |
664 | struct statistics_general_data statis; | 664 | struct statistics_general_data statis; |
665 | 665 | ||
666 | if (priv->disable_sens_cal) | 666 | if (priv->calib_disabled & IWL_SENSITIVITY_CALIB_DISABLED) |
667 | return; | 667 | return; |
668 | 668 | ||
669 | data = &(priv->sensitivity_data); | 669 | data = &(priv->sensitivity_data); |
@@ -833,28 +833,28 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
833 | * To be safe, simply mask out any chains that we know | 833 | * To be safe, simply mask out any chains that we know |
834 | * are not on the device. | 834 | * are not on the device. |
835 | */ | 835 | */ |
836 | active_chains &= hw_params(priv).valid_rx_ant; | 836 | active_chains &= priv->hw_params.valid_rx_ant; |
837 | 837 | ||
838 | num_tx_chains = 0; | 838 | num_tx_chains = 0; |
839 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 839 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
840 | /* loops on all the bits of | 840 | /* loops on all the bits of |
841 | * priv->hw_setting.valid_tx_ant */ | 841 | * priv->hw_setting.valid_tx_ant */ |
842 | u8 ant_msk = (1 << i); | 842 | u8 ant_msk = (1 << i); |
843 | if (!(hw_params(priv).valid_tx_ant & ant_msk)) | 843 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) |
844 | continue; | 844 | continue; |
845 | 845 | ||
846 | num_tx_chains++; | 846 | num_tx_chains++; |
847 | if (data->disconn_array[i] == 0) | 847 | if (data->disconn_array[i] == 0) |
848 | /* there is a Tx antenna connected */ | 848 | /* there is a Tx antenna connected */ |
849 | break; | 849 | break; |
850 | if (num_tx_chains == hw_params(priv).tx_chains_num && | 850 | if (num_tx_chains == priv->hw_params.tx_chains_num && |
851 | data->disconn_array[i]) { | 851 | data->disconn_array[i]) { |
852 | /* | 852 | /* |
853 | * If all chains are disconnected | 853 | * If all chains are disconnected |
854 | * connect the first valid tx chain | 854 | * connect the first valid tx chain |
855 | */ | 855 | */ |
856 | first_chain = | 856 | first_chain = |
857 | find_first_chain(hw_params(priv).valid_tx_ant); | 857 | find_first_chain(priv->hw_params.valid_tx_ant); |
858 | data->disconn_array[first_chain] = 0; | 858 | data->disconn_array[first_chain] = 0; |
859 | active_chains |= BIT(first_chain); | 859 | active_chains |= BIT(first_chain); |
860 | IWL_DEBUG_CALIB(priv, | 860 | IWL_DEBUG_CALIB(priv, |
@@ -864,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
864 | } | 864 | } |
865 | } | 865 | } |
866 | 866 | ||
867 | if (active_chains != hw_params(priv).valid_rx_ant && | 867 | if (active_chains != priv->hw_params.valid_rx_ant && |
868 | active_chains != priv->chain_noise_data.active_chains) | 868 | active_chains != priv->chain_noise_data.active_chains) |
869 | IWL_DEBUG_CALIB(priv, | 869 | IWL_DEBUG_CALIB(priv, |
870 | "Detected that not all antennas are connected! " | 870 | "Detected that not all antennas are connected! " |
871 | "Connected: %#x, valid: %#x.\n", | 871 | "Connected: %#x, valid: %#x.\n", |
872 | active_chains, | 872 | active_chains, |
873 | hw_params(priv).valid_rx_ant); | 873 | priv->hw_params.valid_rx_ant); |
874 | 874 | ||
875 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 875 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
876 | data->active_chains = active_chains; | 876 | data->active_chains = active_chains; |
@@ -970,7 +970,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
970 | */ | 970 | */ |
971 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 971 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
972 | 972 | ||
973 | if (priv->disable_chain_noise_cal) | 973 | if (priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED) |
974 | return; | 974 | return; |
975 | 975 | ||
976 | data = &(priv->chain_noise_data); | 976 | data = &(priv->chain_noise_data); |
@@ -1055,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1055 | cfg(priv)->bt_params->advanced_bt_coexist) { | 1055 | cfg(priv)->bt_params->advanced_bt_coexist) { |
1056 | /* Disable disconnected antenna algorithm for advanced | 1056 | /* Disable disconnected antenna algorithm for advanced |
1057 | bt coex, assuming valid antennas are connected */ | 1057 | bt coex, assuming valid antennas are connected */ |
1058 | data->active_chains = hw_params(priv).valid_rx_ant; | 1058 | data->active_chains = priv->hw_params.valid_rx_ant; |
1059 | for (i = 0; i < NUM_RX_CHAINS; i++) | 1059 | for (i = 0; i < NUM_RX_CHAINS; i++) |
1060 | if (!(data->active_chains & (1<<i))) | 1060 | if (!(data->active_chains & (1<<i))) |
1061 | data->disconn_array[i] = 1; | 1061 | data->disconn_array[i] = 1; |
@@ -1085,7 +1085,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1085 | min_average_noise, min_average_noise_antenna_i); | 1085 | min_average_noise, min_average_noise_antenna_i); |
1086 | 1086 | ||
1087 | iwlagn_gain_computation(priv, average_noise, | 1087 | iwlagn_gain_computation(priv, average_noise, |
1088 | find_first_chain(hw_params(priv).valid_rx_ant)); | 1088 | find_first_chain(priv->hw_params.valid_rx_ant)); |
1089 | 1089 | ||
1090 | /* Some power changes may have been made during the calibration. | 1090 | /* Some power changes may have been made during the calibration. |
1091 | * Update and commit the RXON | 1091 | * Update and commit the RXON |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c new file mode 100644 index 000000000000..08718caf4aa9 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c | |||
@@ -0,0 +1,756 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | /* | ||
28 | * DVM device-specific data & functions | ||
29 | */ | ||
30 | #include "iwl-core.h" | ||
31 | #include "iwl-agn.h" | ||
32 | #include "iwl-dev.h" | ||
33 | #include "iwl-commands.h" | ||
34 | #include "iwl-io.h" | ||
35 | #include "iwl-prph.h" | ||
36 | |||
37 | /* | ||
38 | * 1000 series | ||
39 | * =========== | ||
40 | */ | ||
41 | |||
42 | /* | ||
43 | * For 1000, use advance thermal throttling critical temperature threshold, | ||
44 | * but legacy thermal management implementation for now. | ||
45 | * This is for the reason of 1000 uCode using advance thermal throttling API | ||
46 | * but not implement ct_kill_exit based on ct_kill exit temperature | ||
47 | * so the thermal throttling will still based on legacy thermal throttling | ||
48 | * management. | ||
49 | * The code here need to be modified once 1000 uCode has the advanced thermal | ||
50 | * throttling algorithm in place | ||
51 | */ | ||
52 | static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | ||
53 | { | ||
54 | /* want Celsius */ | ||
55 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | ||
56 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
57 | } | ||
58 | |||
59 | /* NIC configuration for 1000 series */ | ||
60 | static void iwl1000_nic_config(struct iwl_priv *priv) | ||
61 | { | ||
62 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
63 | iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, | ||
64 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
65 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
66 | |||
67 | /* Setting digital SVR for 1000 card to 1.32V */ | ||
68 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | ||
69 | iwl_set_bits_mask_prph(trans(priv), APMG_DIGITAL_SVR_REG, | ||
70 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | ||
71 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | ||
76 | * @priv -- pointer to iwl_priv data structure | ||
77 | * @tsf_bits -- number of bits need to shift for masking) | ||
78 | */ | ||
79 | static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, | ||
80 | u16 tsf_bits) | ||
81 | { | ||
82 | return (1 << tsf_bits) - 1; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time | ||
87 | * @priv -- pointer to iwl_priv data structure | ||
88 | * @tsf_bits -- number of bits need to shift for masking) | ||
89 | */ | ||
90 | static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, | ||
91 | u16 tsf_bits) | ||
92 | { | ||
93 | return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * extended beacon time format | ||
98 | * time in usec will be changed into a 32-bit value in extended:internal format | ||
99 | * the extended part is the beacon counts | ||
100 | * the internal part is the time in usec within one beacon interval | ||
101 | */ | ||
102 | static u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, | ||
103 | u32 beacon_interval) | ||
104 | { | ||
105 | u32 quot; | ||
106 | u32 rem; | ||
107 | u32 interval = beacon_interval * TIME_UNIT; | ||
108 | |||
109 | if (!interval || !usec) | ||
110 | return 0; | ||
111 | |||
112 | quot = (usec / interval) & | ||
113 | (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >> | ||
114 | IWLAGN_EXT_BEACON_TIME_POS); | ||
115 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | ||
116 | IWLAGN_EXT_BEACON_TIME_POS); | ||
117 | |||
118 | return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem; | ||
119 | } | ||
120 | |||
121 | /* base is usually what we get from ucode with each received frame, | ||
122 | * the same as HW timer counter counting down | ||
123 | */ | ||
124 | static __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
125 | u32 addon, u32 beacon_interval) | ||
126 | { | ||
127 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | ||
128 | IWLAGN_EXT_BEACON_TIME_POS); | ||
129 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | ||
130 | IWLAGN_EXT_BEACON_TIME_POS); | ||
131 | u32 interval = beacon_interval * TIME_UNIT; | ||
132 | u32 res = (base & iwl_beacon_time_mask_high(priv, | ||
133 | IWLAGN_EXT_BEACON_TIME_POS)) + | ||
134 | (addon & iwl_beacon_time_mask_high(priv, | ||
135 | IWLAGN_EXT_BEACON_TIME_POS)); | ||
136 | |||
137 | if (base_low > addon_low) | ||
138 | res += base_low - addon_low; | ||
139 | else if (base_low < addon_low) { | ||
140 | res += interval + base_low - addon_low; | ||
141 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | ||
142 | } else | ||
143 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | ||
144 | |||
145 | return cpu_to_le32(res); | ||
146 | } | ||
147 | |||
148 | static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { | ||
149 | .min_nrg_cck = 95, | ||
150 | .auto_corr_min_ofdm = 90, | ||
151 | .auto_corr_min_ofdm_mrc = 170, | ||
152 | .auto_corr_min_ofdm_x1 = 120, | ||
153 | .auto_corr_min_ofdm_mrc_x1 = 240, | ||
154 | |||
155 | .auto_corr_max_ofdm = 120, | ||
156 | .auto_corr_max_ofdm_mrc = 210, | ||
157 | .auto_corr_max_ofdm_x1 = 155, | ||
158 | .auto_corr_max_ofdm_mrc_x1 = 290, | ||
159 | |||
160 | .auto_corr_min_cck = 125, | ||
161 | .auto_corr_max_cck = 200, | ||
162 | .auto_corr_min_cck_mrc = 170, | ||
163 | .auto_corr_max_cck_mrc = 400, | ||
164 | .nrg_th_cck = 95, | ||
165 | .nrg_th_ofdm = 95, | ||
166 | |||
167 | .barker_corr_th_min = 190, | ||
168 | .barker_corr_th_min_mrc = 390, | ||
169 | .nrg_th_cca = 62, | ||
170 | }; | ||
171 | |||
172 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | ||
173 | { | ||
174 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
175 | |||
176 | priv->hw_params.tx_chains_num = | ||
177 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
178 | if (cfg(priv)->rx_with_siso_diversity) | ||
179 | priv->hw_params.rx_chains_num = 1; | ||
180 | else | ||
181 | priv->hw_params.rx_chains_num = | ||
182 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
183 | |||
184 | iwl1000_set_ct_threshold(priv); | ||
185 | |||
186 | /* Set initial sensitivity parameters */ | ||
187 | priv->hw_params.sens = &iwl1000_sensitivity; | ||
188 | } | ||
189 | |||
190 | struct iwl_lib_ops iwl1000_lib = { | ||
191 | .set_hw_params = iwl1000_hw_set_hw_params, | ||
192 | .nic_config = iwl1000_nic_config, | ||
193 | .eeprom_ops = { | ||
194 | .regulatory_bands = { | ||
195 | EEPROM_REG_BAND_1_CHANNELS, | ||
196 | EEPROM_REG_BAND_2_CHANNELS, | ||
197 | EEPROM_REG_BAND_3_CHANNELS, | ||
198 | EEPROM_REG_BAND_4_CHANNELS, | ||
199 | EEPROM_REG_BAND_5_CHANNELS, | ||
200 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
201 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
202 | }, | ||
203 | }, | ||
204 | .temperature = iwlagn_temperature, | ||
205 | }; | ||
206 | |||
207 | |||
208 | /* | ||
209 | * 2000 series | ||
210 | * =========== | ||
211 | */ | ||
212 | |||
213 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | ||
214 | { | ||
215 | /* want Celsius */ | ||
216 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | ||
217 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
218 | } | ||
219 | |||
220 | /* NIC configuration for 2000 series */ | ||
221 | static void iwl2000_nic_config(struct iwl_priv *priv) | ||
222 | { | ||
223 | iwl_rf_config(priv); | ||
224 | |||
225 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
226 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | ||
227 | } | ||
228 | |||
229 | static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | ||
230 | .min_nrg_cck = 97, | ||
231 | .auto_corr_min_ofdm = 80, | ||
232 | .auto_corr_min_ofdm_mrc = 128, | ||
233 | .auto_corr_min_ofdm_x1 = 105, | ||
234 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
235 | |||
236 | .auto_corr_max_ofdm = 145, | ||
237 | .auto_corr_max_ofdm_mrc = 232, | ||
238 | .auto_corr_max_ofdm_x1 = 110, | ||
239 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
240 | |||
241 | .auto_corr_min_cck = 125, | ||
242 | .auto_corr_max_cck = 175, | ||
243 | .auto_corr_min_cck_mrc = 160, | ||
244 | .auto_corr_max_cck_mrc = 310, | ||
245 | .nrg_th_cck = 97, | ||
246 | .nrg_th_ofdm = 100, | ||
247 | |||
248 | .barker_corr_th_min = 190, | ||
249 | .barker_corr_th_min_mrc = 390, | ||
250 | .nrg_th_cca = 62, | ||
251 | }; | ||
252 | |||
253 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | ||
254 | { | ||
255 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); | ||
256 | |||
257 | priv->hw_params.tx_chains_num = | ||
258 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
259 | if (cfg(priv)->rx_with_siso_diversity) | ||
260 | priv->hw_params.rx_chains_num = 1; | ||
261 | else | ||
262 | priv->hw_params.rx_chains_num = | ||
263 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
264 | |||
265 | iwl2000_set_ct_threshold(priv); | ||
266 | |||
267 | /* Set initial sensitivity parameters */ | ||
268 | priv->hw_params.sens = &iwl2000_sensitivity; | ||
269 | } | ||
270 | |||
271 | struct iwl_lib_ops iwl2000_lib = { | ||
272 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
273 | .nic_config = iwl2000_nic_config, | ||
274 | .eeprom_ops = { | ||
275 | .regulatory_bands = { | ||
276 | EEPROM_REG_BAND_1_CHANNELS, | ||
277 | EEPROM_REG_BAND_2_CHANNELS, | ||
278 | EEPROM_REG_BAND_3_CHANNELS, | ||
279 | EEPROM_REG_BAND_4_CHANNELS, | ||
280 | EEPROM_REG_BAND_5_CHANNELS, | ||
281 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
282 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
283 | }, | ||
284 | .enhanced_txpower = true, | ||
285 | }, | ||
286 | .temperature = iwlagn_temperature, | ||
287 | }; | ||
288 | |||
289 | struct iwl_lib_ops iwl2030_lib = { | ||
290 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
291 | .nic_config = iwl2000_nic_config, | ||
292 | .eeprom_ops = { | ||
293 | .regulatory_bands = { | ||
294 | EEPROM_REG_BAND_1_CHANNELS, | ||
295 | EEPROM_REG_BAND_2_CHANNELS, | ||
296 | EEPROM_REG_BAND_3_CHANNELS, | ||
297 | EEPROM_REG_BAND_4_CHANNELS, | ||
298 | EEPROM_REG_BAND_5_CHANNELS, | ||
299 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
300 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
301 | }, | ||
302 | .enhanced_txpower = true, | ||
303 | }, | ||
304 | .temperature = iwlagn_temperature, | ||
305 | }; | ||
306 | |||
307 | /* | ||
308 | * 5000 series | ||
309 | * =========== | ||
310 | */ | ||
311 | |||
312 | /* NIC configuration for 5000 series */ | ||
313 | static void iwl5000_nic_config(struct iwl_priv *priv) | ||
314 | { | ||
315 | iwl_rf_config(priv); | ||
316 | |||
317 | /* W/A : NIC is stuck in a reset state after Early PCIe power off | ||
318 | * (PCIe power is lost before PERST# is asserted), | ||
319 | * causing ME FW to lose ownership and not being able to obtain it back. | ||
320 | */ | ||
321 | iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG, | ||
322 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | ||
323 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | ||
324 | } | ||
325 | |||
326 | static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { | ||
327 | .min_nrg_cck = 100, | ||
328 | .auto_corr_min_ofdm = 90, | ||
329 | .auto_corr_min_ofdm_mrc = 170, | ||
330 | .auto_corr_min_ofdm_x1 = 105, | ||
331 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
332 | |||
333 | .auto_corr_max_ofdm = 120, | ||
334 | .auto_corr_max_ofdm_mrc = 210, | ||
335 | .auto_corr_max_ofdm_x1 = 120, | ||
336 | .auto_corr_max_ofdm_mrc_x1 = 240, | ||
337 | |||
338 | .auto_corr_min_cck = 125, | ||
339 | .auto_corr_max_cck = 200, | ||
340 | .auto_corr_min_cck_mrc = 200, | ||
341 | .auto_corr_max_cck_mrc = 400, | ||
342 | .nrg_th_cck = 100, | ||
343 | .nrg_th_ofdm = 100, | ||
344 | |||
345 | .barker_corr_th_min = 190, | ||
346 | .barker_corr_th_min_mrc = 390, | ||
347 | .nrg_th_cca = 62, | ||
348 | }; | ||
349 | |||
350 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | ||
351 | .min_nrg_cck = 95, | ||
352 | .auto_corr_min_ofdm = 90, | ||
353 | .auto_corr_min_ofdm_mrc = 170, | ||
354 | .auto_corr_min_ofdm_x1 = 105, | ||
355 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
356 | |||
357 | .auto_corr_max_ofdm = 120, | ||
358 | .auto_corr_max_ofdm_mrc = 210, | ||
359 | /* max = min for performance bug in 5150 DSP */ | ||
360 | .auto_corr_max_ofdm_x1 = 105, | ||
361 | .auto_corr_max_ofdm_mrc_x1 = 220, | ||
362 | |||
363 | .auto_corr_min_cck = 125, | ||
364 | .auto_corr_max_cck = 200, | ||
365 | .auto_corr_min_cck_mrc = 170, | ||
366 | .auto_corr_max_cck_mrc = 400, | ||
367 | .nrg_th_cck = 95, | ||
368 | .nrg_th_ofdm = 95, | ||
369 | |||
370 | .barker_corr_th_min = 190, | ||
371 | .barker_corr_th_min_mrc = 390, | ||
372 | .nrg_th_cca = 62, | ||
373 | }; | ||
374 | |||
375 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | ||
376 | |||
377 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | ||
378 | { | ||
379 | u16 temperature, voltage; | ||
380 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, | ||
381 | EEPROM_KELVIN_TEMPERATURE); | ||
382 | |||
383 | temperature = le16_to_cpu(temp_calib[0]); | ||
384 | voltage = le16_to_cpu(temp_calib[1]); | ||
385 | |||
386 | /* offset = temp - volt / coeff */ | ||
387 | return (s32)(temperature - | ||
388 | voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | ||
389 | } | ||
390 | |||
391 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | ||
392 | { | ||
393 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | ||
394 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - | ||
395 | iwl_temp_calib_to_offset(priv); | ||
396 | |||
397 | priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; | ||
398 | } | ||
399 | |||
400 | static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | ||
401 | { | ||
402 | /* want Celsius */ | ||
403 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | ||
404 | } | ||
405 | |||
406 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||
407 | { | ||
408 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
409 | BIT(IEEE80211_BAND_5GHZ); | ||
410 | |||
411 | priv->hw_params.tx_chains_num = | ||
412 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
413 | priv->hw_params.rx_chains_num = | ||
414 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
415 | |||
416 | iwl5000_set_ct_threshold(priv); | ||
417 | |||
418 | /* Set initial sensitivity parameters */ | ||
419 | priv->hw_params.sens = &iwl5000_sensitivity; | ||
420 | } | ||
421 | |||
422 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | ||
423 | { | ||
424 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
425 | BIT(IEEE80211_BAND_5GHZ); | ||
426 | |||
427 | priv->hw_params.tx_chains_num = | ||
428 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
429 | priv->hw_params.rx_chains_num = | ||
430 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
431 | |||
432 | iwl5150_set_ct_threshold(priv); | ||
433 | |||
434 | /* Set initial sensitivity parameters */ | ||
435 | priv->hw_params.sens = &iwl5150_sensitivity; | ||
436 | } | ||
437 | |||
438 | static void iwl5150_temperature(struct iwl_priv *priv) | ||
439 | { | ||
440 | u32 vt = 0; | ||
441 | s32 offset = iwl_temp_calib_to_offset(priv); | ||
442 | |||
443 | vt = le32_to_cpu(priv->statistics.common.temperature); | ||
444 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | ||
445 | /* now vt hold the temperature in Kelvin */ | ||
446 | priv->temperature = KELVIN_TO_CELSIUS(vt); | ||
447 | iwl_tt_handler(priv); | ||
448 | } | ||
449 | |||
450 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | ||
451 | struct ieee80211_channel_switch *ch_switch) | ||
452 | { | ||
453 | /* | ||
454 | * MULTI-FIXME | ||
455 | * See iwlagn_mac_channel_switch. | ||
456 | */ | ||
457 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
458 | struct iwl5000_channel_switch_cmd cmd; | ||
459 | const struct iwl_channel_info *ch_info; | ||
460 | u32 switch_time_in_usec, ucode_switch_time; | ||
461 | u16 ch; | ||
462 | u32 tsf_low; | ||
463 | u8 switch_count; | ||
464 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
465 | struct ieee80211_vif *vif = ctx->vif; | ||
466 | struct iwl_host_cmd hcmd = { | ||
467 | .id = REPLY_CHANNEL_SWITCH, | ||
468 | .len = { sizeof(cmd), }, | ||
469 | .flags = CMD_SYNC, | ||
470 | .data = { &cmd, }, | ||
471 | }; | ||
472 | |||
473 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
474 | ch = ch_switch->channel->hw_value; | ||
475 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
476 | ctx->active.channel, ch); | ||
477 | cmd.channel = cpu_to_le16(ch); | ||
478 | cmd.rxon_flags = ctx->staging.flags; | ||
479 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
480 | switch_count = ch_switch->count; | ||
481 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
482 | /* | ||
483 | * calculate the ucode channel switch time | ||
484 | * adding TSF as one of the factor for when to switch | ||
485 | */ | ||
486 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
487 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
488 | beacon_interval)) { | ||
489 | switch_count -= (priv->ucode_beacon_time - | ||
490 | tsf_low) / beacon_interval; | ||
491 | } else | ||
492 | switch_count = 0; | ||
493 | } | ||
494 | if (switch_count <= 1) | ||
495 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
496 | else { | ||
497 | switch_time_in_usec = | ||
498 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
499 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
500 | switch_time_in_usec, | ||
501 | beacon_interval); | ||
502 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
503 | priv->ucode_beacon_time, | ||
504 | ucode_switch_time, | ||
505 | beacon_interval); | ||
506 | } | ||
507 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
508 | cmd.switch_time); | ||
509 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
510 | if (ch_info) | ||
511 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
512 | else { | ||
513 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
514 | ctx->active.channel, ch); | ||
515 | return -EFAULT; | ||
516 | } | ||
517 | |||
518 | return iwl_dvm_send_cmd(priv, &hcmd); | ||
519 | } | ||
520 | |||
521 | struct iwl_lib_ops iwl5000_lib = { | ||
522 | .set_hw_params = iwl5000_hw_set_hw_params, | ||
523 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
524 | .nic_config = iwl5000_nic_config, | ||
525 | .eeprom_ops = { | ||
526 | .regulatory_bands = { | ||
527 | EEPROM_REG_BAND_1_CHANNELS, | ||
528 | EEPROM_REG_BAND_2_CHANNELS, | ||
529 | EEPROM_REG_BAND_3_CHANNELS, | ||
530 | EEPROM_REG_BAND_4_CHANNELS, | ||
531 | EEPROM_REG_BAND_5_CHANNELS, | ||
532 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
533 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
534 | }, | ||
535 | }, | ||
536 | .temperature = iwlagn_temperature, | ||
537 | }; | ||
538 | |||
539 | struct iwl_lib_ops iwl5150_lib = { | ||
540 | .set_hw_params = iwl5150_hw_set_hw_params, | ||
541 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
542 | .nic_config = iwl5000_nic_config, | ||
543 | .eeprom_ops = { | ||
544 | .regulatory_bands = { | ||
545 | EEPROM_REG_BAND_1_CHANNELS, | ||
546 | EEPROM_REG_BAND_2_CHANNELS, | ||
547 | EEPROM_REG_BAND_3_CHANNELS, | ||
548 | EEPROM_REG_BAND_4_CHANNELS, | ||
549 | EEPROM_REG_BAND_5_CHANNELS, | ||
550 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
551 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
552 | }, | ||
553 | }, | ||
554 | .temperature = iwl5150_temperature, | ||
555 | }; | ||
556 | |||
557 | |||
558 | |||
559 | /* | ||
560 | * 6000 series | ||
561 | * =========== | ||
562 | */ | ||
563 | |||
564 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | ||
565 | { | ||
566 | /* want Celsius */ | ||
567 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | ||
568 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
569 | } | ||
570 | |||
571 | /* NIC configuration for 6000 series */ | ||
572 | static void iwl6000_nic_config(struct iwl_priv *priv) | ||
573 | { | ||
574 | iwl_rf_config(priv); | ||
575 | |||
576 | switch (cfg(priv)->device_family) { | ||
577 | case IWL_DEVICE_FAMILY_6005: | ||
578 | case IWL_DEVICE_FAMILY_6030: | ||
579 | case IWL_DEVICE_FAMILY_6000: | ||
580 | break; | ||
581 | case IWL_DEVICE_FAMILY_6000i: | ||
582 | /* 2x2 IPA phy type */ | ||
583 | iwl_write32(trans(priv), CSR_GP_DRIVER_REG, | ||
584 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | ||
585 | break; | ||
586 | case IWL_DEVICE_FAMILY_6050: | ||
587 | /* Indicate calibration version to uCode. */ | ||
588 | if (iwl_eeprom_calib_version(priv) >= 6) | ||
589 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
590 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
591 | break; | ||
592 | case IWL_DEVICE_FAMILY_6150: | ||
593 | /* Indicate calibration version to uCode. */ | ||
594 | if (iwl_eeprom_calib_version(priv) >= 6) | ||
595 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
596 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
597 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | ||
598 | CSR_GP_DRIVER_REG_BIT_6050_1x2); | ||
599 | break; | ||
600 | default: | ||
601 | WARN_ON(1); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | ||
606 | .min_nrg_cck = 110, | ||
607 | .auto_corr_min_ofdm = 80, | ||
608 | .auto_corr_min_ofdm_mrc = 128, | ||
609 | .auto_corr_min_ofdm_x1 = 105, | ||
610 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
611 | |||
612 | .auto_corr_max_ofdm = 145, | ||
613 | .auto_corr_max_ofdm_mrc = 232, | ||
614 | .auto_corr_max_ofdm_x1 = 110, | ||
615 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
616 | |||
617 | .auto_corr_min_cck = 125, | ||
618 | .auto_corr_max_cck = 175, | ||
619 | .auto_corr_min_cck_mrc = 160, | ||
620 | .auto_corr_max_cck_mrc = 310, | ||
621 | .nrg_th_cck = 110, | ||
622 | .nrg_th_ofdm = 110, | ||
623 | |||
624 | .barker_corr_th_min = 190, | ||
625 | .barker_corr_th_min_mrc = 336, | ||
626 | .nrg_th_cca = 62, | ||
627 | }; | ||
628 | |||
629 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | ||
630 | { | ||
631 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
632 | BIT(IEEE80211_BAND_5GHZ); | ||
633 | |||
634 | priv->hw_params.tx_chains_num = | ||
635 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
636 | if (cfg(priv)->rx_with_siso_diversity) | ||
637 | priv->hw_params.rx_chains_num = 1; | ||
638 | else | ||
639 | priv->hw_params.rx_chains_num = | ||
640 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
641 | |||
642 | iwl6000_set_ct_threshold(priv); | ||
643 | |||
644 | /* Set initial sensitivity parameters */ | ||
645 | priv->hw_params.sens = &iwl6000_sensitivity; | ||
646 | |||
647 | } | ||
648 | |||
649 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | ||
650 | struct ieee80211_channel_switch *ch_switch) | ||
651 | { | ||
652 | /* | ||
653 | * MULTI-FIXME | ||
654 | * See iwlagn_mac_channel_switch. | ||
655 | */ | ||
656 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
657 | struct iwl6000_channel_switch_cmd cmd; | ||
658 | const struct iwl_channel_info *ch_info; | ||
659 | u32 switch_time_in_usec, ucode_switch_time; | ||
660 | u16 ch; | ||
661 | u32 tsf_low; | ||
662 | u8 switch_count; | ||
663 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
664 | struct ieee80211_vif *vif = ctx->vif; | ||
665 | struct iwl_host_cmd hcmd = { | ||
666 | .id = REPLY_CHANNEL_SWITCH, | ||
667 | .len = { sizeof(cmd), }, | ||
668 | .flags = CMD_SYNC, | ||
669 | .data = { &cmd, }, | ||
670 | }; | ||
671 | |||
672 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
673 | ch = ch_switch->channel->hw_value; | ||
674 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | ||
675 | ctx->active.channel, ch); | ||
676 | cmd.channel = cpu_to_le16(ch); | ||
677 | cmd.rxon_flags = ctx->staging.flags; | ||
678 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
679 | switch_count = ch_switch->count; | ||
680 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
681 | /* | ||
682 | * calculate the ucode channel switch time | ||
683 | * adding TSF as one of the factor for when to switch | ||
684 | */ | ||
685 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
686 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
687 | beacon_interval)) { | ||
688 | switch_count -= (priv->ucode_beacon_time - | ||
689 | tsf_low) / beacon_interval; | ||
690 | } else | ||
691 | switch_count = 0; | ||
692 | } | ||
693 | if (switch_count <= 1) | ||
694 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
695 | else { | ||
696 | switch_time_in_usec = | ||
697 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
698 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
699 | switch_time_in_usec, | ||
700 | beacon_interval); | ||
701 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
702 | priv->ucode_beacon_time, | ||
703 | ucode_switch_time, | ||
704 | beacon_interval); | ||
705 | } | ||
706 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
707 | cmd.switch_time); | ||
708 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
709 | if (ch_info) | ||
710 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
711 | else { | ||
712 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
713 | ctx->active.channel, ch); | ||
714 | return -EFAULT; | ||
715 | } | ||
716 | |||
717 | return iwl_dvm_send_cmd(priv, &hcmd); | ||
718 | } | ||
719 | |||
720 | struct iwl_lib_ops iwl6000_lib = { | ||
721 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
722 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
723 | .nic_config = iwl6000_nic_config, | ||
724 | .eeprom_ops = { | ||
725 | .regulatory_bands = { | ||
726 | EEPROM_REG_BAND_1_CHANNELS, | ||
727 | EEPROM_REG_BAND_2_CHANNELS, | ||
728 | EEPROM_REG_BAND_3_CHANNELS, | ||
729 | EEPROM_REG_BAND_4_CHANNELS, | ||
730 | EEPROM_REG_BAND_5_CHANNELS, | ||
731 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
732 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
733 | }, | ||
734 | .enhanced_txpower = true, | ||
735 | }, | ||
736 | .temperature = iwlagn_temperature, | ||
737 | }; | ||
738 | |||
739 | struct iwl_lib_ops iwl6030_lib = { | ||
740 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
741 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
742 | .nic_config = iwl6000_nic_config, | ||
743 | .eeprom_ops = { | ||
744 | .regulatory_bands = { | ||
745 | EEPROM_REG_BAND_1_CHANNELS, | ||
746 | EEPROM_REG_BAND_2_CHANNELS, | ||
747 | EEPROM_REG_BAND_3_CHANNELS, | ||
748 | EEPROM_REG_BAND_4_CHANNELS, | ||
749 | EEPROM_REG_BAND_5_CHANNELS, | ||
750 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
751 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
752 | }, | ||
753 | .enhanced_txpower = true, | ||
754 | }, | ||
755 | .temperature = iwlagn_temperature, | ||
756 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 4da4ab23cce7..4e0c248a0050 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -94,77 +94,13 @@ void iwlagn_temperature(struct iwl_priv *priv) | |||
94 | iwl_tt_handler(priv); | 94 | iwl_tt_handler(priv); |
95 | } | 95 | } |
96 | 96 | ||
97 | u16 iwl_eeprom_calib_version(struct iwl_shared *shrd) | ||
98 | { | ||
99 | struct iwl_eeprom_calib_hdr *hdr; | ||
100 | |||
101 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(shrd, | ||
102 | EEPROM_CALIB_ALL); | ||
103 | return hdr->version; | ||
104 | |||
105 | } | ||
106 | |||
107 | /* | ||
108 | * EEPROM | ||
109 | */ | ||
110 | static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address) | ||
111 | { | ||
112 | u16 offset = 0; | ||
113 | |||
114 | if ((address & INDIRECT_ADDRESS) == 0) | ||
115 | return address; | ||
116 | |||
117 | switch (address & INDIRECT_TYPE_MSK) { | ||
118 | case INDIRECT_HOST: | ||
119 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_HOST); | ||
120 | break; | ||
121 | case INDIRECT_GENERAL: | ||
122 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_GENERAL); | ||
123 | break; | ||
124 | case INDIRECT_REGULATORY: | ||
125 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_REGULATORY); | ||
126 | break; | ||
127 | case INDIRECT_TXP_LIMIT: | ||
128 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT); | ||
129 | break; | ||
130 | case INDIRECT_TXP_LIMIT_SIZE: | ||
131 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT_SIZE); | ||
132 | break; | ||
133 | case INDIRECT_CALIBRATION: | ||
134 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_CALIBRATION); | ||
135 | break; | ||
136 | case INDIRECT_PROCESS_ADJST: | ||
137 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_PROCESS_ADJST); | ||
138 | break; | ||
139 | case INDIRECT_OTHERS: | ||
140 | offset = iwl_eeprom_query16(shrd, EEPROM_LINK_OTHERS); | ||
141 | break; | ||
142 | default: | ||
143 | IWL_ERR(shrd->trans, "illegal indirect type: 0x%X\n", | ||
144 | address & INDIRECT_TYPE_MSK); | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | /* translate the offset from words to byte */ | ||
149 | return (address & ADDRESS_MSK) + (offset << 1); | ||
150 | } | ||
151 | |||
152 | const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset) | ||
153 | { | ||
154 | u32 address = eeprom_indirect_address(shrd, offset); | ||
155 | BUG_ON(address >= shrd->cfg->base_params->eeprom_size); | ||
156 | return &shrd->eeprom[address]; | ||
157 | } | ||
158 | |||
159 | struct iwl_mod_params iwlagn_mod_params = { | 97 | struct iwl_mod_params iwlagn_mod_params = { |
160 | .amsdu_size_8K = 1, | 98 | .amsdu_size_8K = 1, |
161 | .restart_fw = 1, | 99 | .restart_fw = 1, |
162 | .plcp_check = true, | 100 | .plcp_check = true, |
163 | .bt_coex_active = true, | 101 | .bt_coex_active = true, |
164 | .no_sleep_autoadjust = true, | ||
165 | .power_level = IWL_POWER_INDEX_1, | 102 | .power_level = IWL_POWER_INDEX_1, |
166 | .bt_ch_announce = true, | 103 | .bt_ch_announce = true, |
167 | .wanted_ucode_alternative = 1, | ||
168 | .auto_agg = true, | 104 | .auto_agg = true, |
169 | /* the rest are 0 by default */ | 105 | /* the rest are 0 by default */ |
170 | }; | 106 | }; |
@@ -234,7 +170,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | |||
234 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | | 170 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | |
235 | IWL_PAN_SCD_MULTICAST_MSK; | 171 | IWL_PAN_SCD_MULTICAST_MSK; |
236 | 172 | ||
237 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | 173 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |
238 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; | 174 | flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; |
239 | 175 | ||
240 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", | 176 | IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", |
@@ -369,24 +305,30 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
369 | .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT, | 305 | .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT, |
370 | .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT, | 306 | .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT, |
371 | }; | 307 | }; |
372 | struct iwl6000_bt_cmd bt_cmd_6000; | 308 | struct iwl_bt_cmd_v1 bt_cmd_v1; |
373 | struct iwl2000_bt_cmd bt_cmd_2000; | 309 | struct iwl_bt_cmd_v2 bt_cmd_v2; |
374 | int ret; | 310 | int ret; |
375 | 311 | ||
376 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != | 312 | BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != |
377 | sizeof(basic.bt3_lookup_table)); | 313 | sizeof(basic.bt3_lookup_table)); |
378 | 314 | ||
379 | if (cfg(priv)->bt_params) { | 315 | if (cfg(priv)->bt_params) { |
316 | /* | ||
317 | * newer generation of devices (2000 series and newer) | ||
318 | * use the version 2 of the bt command | ||
319 | * we need to make sure sending the host command | ||
320 | * with correct data structure to avoid uCode assert | ||
321 | */ | ||
380 | if (cfg(priv)->bt_params->bt_session_2) { | 322 | if (cfg(priv)->bt_params->bt_session_2) { |
381 | bt_cmd_2000.prio_boost = cpu_to_le32( | 323 | bt_cmd_v2.prio_boost = cpu_to_le32( |
382 | cfg(priv)->bt_params->bt_prio_boost); | 324 | cfg(priv)->bt_params->bt_prio_boost); |
383 | bt_cmd_2000.tx_prio_boost = 0; | 325 | bt_cmd_v2.tx_prio_boost = 0; |
384 | bt_cmd_2000.rx_prio_boost = 0; | 326 | bt_cmd_v2.rx_prio_boost = 0; |
385 | } else { | 327 | } else { |
386 | bt_cmd_6000.prio_boost = | 328 | bt_cmd_v1.prio_boost = |
387 | cfg(priv)->bt_params->bt_prio_boost; | 329 | cfg(priv)->bt_params->bt_prio_boost; |
388 | bt_cmd_6000.tx_prio_boost = 0; | 330 | bt_cmd_v1.tx_prio_boost = 0; |
389 | bt_cmd_6000.rx_prio_boost = 0; | 331 | bt_cmd_v1.rx_prio_boost = 0; |
390 | } | 332 | } |
391 | } else { | 333 | } else { |
392 | IWL_ERR(priv, "failed to construct BT Coex Config\n"); | 334 | IWL_ERR(priv, "failed to construct BT Coex Config\n"); |
@@ -433,15 +375,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
433 | "full concurrency" : "3-wire"); | 375 | "full concurrency" : "3-wire"); |
434 | 376 | ||
435 | if (cfg(priv)->bt_params->bt_session_2) { | 377 | if (cfg(priv)->bt_params->bt_session_2) { |
436 | memcpy(&bt_cmd_2000.basic, &basic, | 378 | memcpy(&bt_cmd_v2.basic, &basic, |
437 | sizeof(basic)); | 379 | sizeof(basic)); |
438 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 380 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
439 | CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); | 381 | CMD_SYNC, sizeof(bt_cmd_v2), &bt_cmd_v2); |
440 | } else { | 382 | } else { |
441 | memcpy(&bt_cmd_6000.basic, &basic, | 383 | memcpy(&bt_cmd_v1.basic, &basic, |
442 | sizeof(basic)); | 384 | sizeof(basic)); |
443 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 385 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
444 | CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); | 386 | CMD_SYNC, sizeof(bt_cmd_v1), &bt_cmd_v1); |
445 | } | 387 | } |
446 | if (ret) | 388 | if (ret) |
447 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | 389 | IWL_ERR(priv, "failed to send BT Coex Config\n"); |
@@ -868,7 +810,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
868 | if (priv->chain_noise_data.active_chains) | 810 | if (priv->chain_noise_data.active_chains) |
869 | active_chains = priv->chain_noise_data.active_chains; | 811 | active_chains = priv->chain_noise_data.active_chains; |
870 | else | 812 | else |
871 | active_chains = hw_params(priv).valid_rx_ant; | 813 | active_chains = priv->hw_params.valid_rx_ant; |
872 | 814 | ||
873 | if (cfg(priv)->bt_params && | 815 | if (cfg(priv)->bt_params && |
874 | cfg(priv)->bt_params->advanced_bt_coexist && | 816 | cfg(priv)->bt_params->advanced_bt_coexist && |
@@ -1300,7 +1242,7 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1300 | 1242 | ||
1301 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { | 1243 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { |
1302 | IWL_ERR(priv, "Command %s failed: FW Error\n", | 1244 | IWL_ERR(priv, "Command %s failed: FW Error\n", |
1303 | get_cmd_string(cmd->id)); | 1245 | iwl_dvm_get_cmd_string(cmd->id)); |
1304 | return -EIO; | 1246 | return -EIO; |
1305 | } | 1247 | } |
1306 | 1248 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index b936ae7e00a3..8b13b6cf940a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -819,7 +819,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
819 | 819 | ||
820 | if (num_of_ant(tbl->ant_type) > 1) | 820 | if (num_of_ant(tbl->ant_type) > 1) |
821 | tbl->ant_type = | 821 | tbl->ant_type = |
822 | first_antenna(hw_params(priv).valid_tx_ant); | 822 | first_antenna(priv->hw_params.valid_tx_ant); |
823 | 823 | ||
824 | tbl->is_ht40 = 0; | 824 | tbl->is_ht40 = 0; |
825 | tbl->is_SGI = 0; | 825 | tbl->is_SGI = 0; |
@@ -1291,7 +1291,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1291 | return -1; | 1291 | return -1; |
1292 | 1292 | ||
1293 | /* Need both Tx chains/antennas to support MIMO */ | 1293 | /* Need both Tx chains/antennas to support MIMO */ |
1294 | if (hw_params(priv).tx_chains_num < 2) | 1294 | if (priv->hw_params.tx_chains_num < 2) |
1295 | return -1; | 1295 | return -1; |
1296 | 1296 | ||
1297 | IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); | 1297 | IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); |
@@ -1347,7 +1347,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1347 | return -1; | 1347 | return -1; |
1348 | 1348 | ||
1349 | /* Need both Tx chains/antennas to support MIMO */ | 1349 | /* Need both Tx chains/antennas to support MIMO */ |
1350 | if (hw_params(priv).tx_chains_num < 3) | 1350 | if (priv->hw_params.tx_chains_num < 3) |
1351 | return -1; | 1351 | return -1; |
1352 | 1352 | ||
1353 | IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); | 1353 | IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); |
@@ -1446,8 +1446,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1446 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1446 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1447 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1447 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1448 | u8 start_action; | 1448 | u8 start_action; |
1449 | u8 valid_tx_ant = hw_params(priv).valid_tx_ant; | 1449 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1450 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | 1450 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1451 | int ret = 0; | 1451 | int ret = 0; |
1452 | u8 update_search_tbl_counter = 0; | 1452 | u8 update_search_tbl_counter = 0; |
1453 | 1453 | ||
@@ -1464,7 +1464,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1464 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1464 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1465 | /* avoid antenna B and MIMO */ | 1465 | /* avoid antenna B and MIMO */ |
1466 | valid_tx_ant = | 1466 | valid_tx_ant = |
1467 | first_antenna(hw_params(priv).valid_tx_ant); | 1467 | first_antenna(priv->hw_params.valid_tx_ant); |
1468 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | 1468 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && |
1469 | tbl->action != IWL_LEGACY_SWITCH_SISO) | 1469 | tbl->action != IWL_LEGACY_SWITCH_SISO) |
1470 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1470 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
@@ -1488,7 +1488,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1488 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1488 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1489 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1489 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1490 | valid_tx_ant = | 1490 | valid_tx_ant = |
1491 | first_antenna(hw_params(priv).valid_tx_ant); | 1491 | first_antenna(priv->hw_params.valid_tx_ant); |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | start_action = tbl->action; | 1494 | start_action = tbl->action; |
@@ -1622,8 +1622,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1622 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1622 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1623 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1623 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1624 | u8 start_action; | 1624 | u8 start_action; |
1625 | u8 valid_tx_ant = hw_params(priv).valid_tx_ant; | 1625 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1626 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | 1626 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1627 | u8 update_search_tbl_counter = 0; | 1627 | u8 update_search_tbl_counter = 0; |
1628 | int ret; | 1628 | int ret; |
1629 | 1629 | ||
@@ -1640,7 +1640,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1640 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1640 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1641 | /* avoid antenna B and MIMO */ | 1641 | /* avoid antenna B and MIMO */ |
1642 | valid_tx_ant = | 1642 | valid_tx_ant = |
1643 | first_antenna(hw_params(priv).valid_tx_ant); | 1643 | first_antenna(priv->hw_params.valid_tx_ant); |
1644 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | 1644 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) |
1645 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1645 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1646 | break; | 1646 | break; |
@@ -1658,7 +1658,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1658 | /* configure as 1x1 if bt full concurrency */ | 1658 | /* configure as 1x1 if bt full concurrency */ |
1659 | if (priv->bt_full_concurrent) { | 1659 | if (priv->bt_full_concurrent) { |
1660 | valid_tx_ant = | 1660 | valid_tx_ant = |
1661 | first_antenna(hw_params(priv).valid_tx_ant); | 1661 | first_antenna(priv->hw_params.valid_tx_ant); |
1662 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1662 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1663 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1663 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1664 | } | 1664 | } |
@@ -1794,8 +1794,8 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1794 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1794 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1795 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1795 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1796 | u8 start_action; | 1796 | u8 start_action; |
1797 | u8 valid_tx_ant = hw_params(priv).valid_tx_ant; | 1797 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1798 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | 1798 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1799 | u8 update_search_tbl_counter = 0; | 1799 | u8 update_search_tbl_counter = 0; |
1800 | int ret; | 1800 | int ret; |
1801 | 1801 | ||
@@ -1964,8 +1964,8 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1964 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1964 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1965 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1965 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1966 | u8 start_action; | 1966 | u8 start_action; |
1967 | u8 valid_tx_ant = hw_params(priv).valid_tx_ant; | 1967 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1968 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | 1968 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1969 | int ret; | 1969 | int ret; |
1970 | u8 update_search_tbl_counter = 0; | 1970 | u8 update_search_tbl_counter = 0; |
1971 | 1971 | ||
@@ -2698,7 +2698,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2698 | 2698 | ||
2699 | i = lq_sta->last_txrate_idx; | 2699 | i = lq_sta->last_txrate_idx; |
2700 | 2700 | ||
2701 | valid_tx_ant = hw_params(priv).valid_tx_ant; | 2701 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2702 | 2702 | ||
2703 | if (!lq_sta->search_better_tbl) | 2703 | if (!lq_sta->search_better_tbl) |
2704 | active_tbl = lq_sta->active_tbl; | 2704 | active_tbl = lq_sta->active_tbl; |
@@ -2826,6 +2826,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2826 | struct iwl_station_priv *sta_priv; | 2826 | struct iwl_station_priv *sta_priv; |
2827 | struct iwl_lq_sta *lq_sta; | 2827 | struct iwl_lq_sta *lq_sta; |
2828 | struct ieee80211_supported_band *sband; | 2828 | struct ieee80211_supported_band *sband; |
2829 | unsigned long supp; /* must be unsigned long for for_each_set_bit */ | ||
2829 | 2830 | ||
2830 | sta_priv = (struct iwl_station_priv *) sta->drv_priv; | 2831 | sta_priv = (struct iwl_station_priv *) sta->drv_priv; |
2831 | lq_sta = &sta_priv->lq_sta; | 2832 | lq_sta = &sta_priv->lq_sta; |
@@ -2855,8 +2856,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2855 | lq_sta->max_rate_idx = -1; | 2856 | lq_sta->max_rate_idx = -1; |
2856 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2857 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
2857 | lq_sta->is_green = rs_use_green(sta); | 2858 | lq_sta->is_green = rs_use_green(sta); |
2858 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2859 | lq_sta->band = sband->band; |
2859 | lq_sta->band = priv->band; | 2860 | /* |
2861 | * active legacy rates as per supported rates bitmap | ||
2862 | */ | ||
2863 | supp = sta->supp_rates[sband->band]; | ||
2864 | lq_sta->active_legacy_rate = 0; | ||
2865 | for_each_set_bit(i, &supp, BITS_PER_LONG) | ||
2866 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); | ||
2867 | |||
2860 | /* | 2868 | /* |
2861 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2869 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), |
2862 | * supp_rates[] does not; shift to convert format, force 9 MBits off. | 2870 | * supp_rates[] does not; shift to convert format, force 9 MBits off. |
@@ -2884,15 +2892,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2884 | 2892 | ||
2885 | /* These values will be overridden later */ | 2893 | /* These values will be overridden later */ |
2886 | lq_sta->lq.general_params.single_stream_ant_msk = | 2894 | lq_sta->lq.general_params.single_stream_ant_msk = |
2887 | first_antenna(hw_params(priv).valid_tx_ant); | 2895 | first_antenna(priv->hw_params.valid_tx_ant); |
2888 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2896 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2889 | hw_params(priv).valid_tx_ant & | 2897 | priv->hw_params.valid_tx_ant & |
2890 | ~first_antenna(hw_params(priv).valid_tx_ant); | 2898 | ~first_antenna(priv->hw_params.valid_tx_ant); |
2891 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | 2899 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { |
2892 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2900 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; |
2893 | } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { | 2901 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { |
2894 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2902 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2895 | hw_params(priv).valid_tx_ant; | 2903 | priv->hw_params.valid_tx_ant; |
2896 | } | 2904 | } |
2897 | 2905 | ||
2898 | /* as default allow aggregation for all tids */ | 2906 | /* as default allow aggregation for all tids */ |
@@ -2938,7 +2946,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2938 | if (priv && priv->bt_full_concurrent) { | 2946 | if (priv && priv->bt_full_concurrent) { |
2939 | /* 1x1 only */ | 2947 | /* 1x1 only */ |
2940 | tbl_type.ant_type = | 2948 | tbl_type.ant_type = |
2941 | first_antenna(hw_params(priv).valid_tx_ant); | 2949 | first_antenna(priv->hw_params.valid_tx_ant); |
2942 | } | 2950 | } |
2943 | 2951 | ||
2944 | /* How many times should we repeat the initial rate? */ | 2952 | /* How many times should we repeat the initial rate? */ |
@@ -2970,7 +2978,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2970 | if (priv->bt_full_concurrent) | 2978 | if (priv->bt_full_concurrent) |
2971 | valid_tx_ant = ANT_A; | 2979 | valid_tx_ant = ANT_A; |
2972 | else | 2980 | else |
2973 | valid_tx_ant = hw_params(priv).valid_tx_ant; | 2981 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2974 | } | 2982 | } |
2975 | 2983 | ||
2976 | /* Fill rest of rate table */ | 2984 | /* Fill rest of rate table */ |
@@ -3004,7 +3012,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3004 | if (priv && priv->bt_full_concurrent) { | 3012 | if (priv && priv->bt_full_concurrent) { |
3005 | /* 1x1 only */ | 3013 | /* 1x1 only */ |
3006 | tbl_type.ant_type = | 3014 | tbl_type.ant_type = |
3007 | first_antenna(hw_params(priv).valid_tx_ant); | 3015 | first_antenna(priv->hw_params.valid_tx_ant); |
3008 | } | 3016 | } |
3009 | 3017 | ||
3010 | /* Indicate to uCode which entries might be MIMO. | 3018 | /* Indicate to uCode which entries might be MIMO. |
@@ -3091,7 +3099,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
3091 | u8 ant_sel_tx; | 3099 | u8 ant_sel_tx; |
3092 | 3100 | ||
3093 | priv = lq_sta->drv; | 3101 | priv = lq_sta->drv; |
3094 | valid_tx_ant = hw_params(priv).valid_tx_ant; | 3102 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
3095 | if (lq_sta->dbg_fixed_rate) { | 3103 | if (lq_sta->dbg_fixed_rate) { |
3096 | ant_sel_tx = | 3104 | ant_sel_tx = |
3097 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 3105 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) |
@@ -3162,9 +3170,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3162 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 3170 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
3163 | lq_sta->dbg_fixed_rate); | 3171 | lq_sta->dbg_fixed_rate); |
3164 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 3172 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
3165 | (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "", | 3173 | (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", |
3166 | (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "", | 3174 | (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", |
3167 | (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 3175 | (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); |
3168 | desc += sprintf(buff+desc, "lq type %s\n", | 3176 | desc += sprintf(buff+desc, "lq type %s\n", |
3169 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 3177 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
3170 | if (is_Ht(tbl->lq_type)) { | 3178 | if (is_Ht(tbl->lq_type)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index e12f11d50b88..db6c90f6affe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -40,89 +40,86 @@ | |||
40 | #include "iwl-agn.h" | 40 | #include "iwl-agn.h" |
41 | #include "iwl-shared.h" | 41 | #include "iwl-shared.h" |
42 | 42 | ||
43 | const char *get_cmd_string(u8 cmd) | 43 | #define IWL_CMD_ENTRY(x) [x] = #x |
44 | { | 44 | |
45 | switch (cmd) { | 45 | const char *iwl_dvm_cmd_strings[REPLY_MAX] = { |
46 | IWL_CMD(REPLY_ALIVE); | 46 | IWL_CMD_ENTRY(REPLY_ALIVE), |
47 | IWL_CMD(REPLY_ERROR); | 47 | IWL_CMD_ENTRY(REPLY_ERROR), |
48 | IWL_CMD(REPLY_ECHO); | 48 | IWL_CMD_ENTRY(REPLY_ECHO), |
49 | IWL_CMD(REPLY_RXON); | 49 | IWL_CMD_ENTRY(REPLY_RXON), |
50 | IWL_CMD(REPLY_RXON_ASSOC); | 50 | IWL_CMD_ENTRY(REPLY_RXON_ASSOC), |
51 | IWL_CMD(REPLY_QOS_PARAM); | 51 | IWL_CMD_ENTRY(REPLY_QOS_PARAM), |
52 | IWL_CMD(REPLY_RXON_TIMING); | 52 | IWL_CMD_ENTRY(REPLY_RXON_TIMING), |
53 | IWL_CMD(REPLY_ADD_STA); | 53 | IWL_CMD_ENTRY(REPLY_ADD_STA), |
54 | IWL_CMD(REPLY_REMOVE_STA); | 54 | IWL_CMD_ENTRY(REPLY_REMOVE_STA), |
55 | IWL_CMD(REPLY_REMOVE_ALL_STA); | 55 | IWL_CMD_ENTRY(REPLY_REMOVE_ALL_STA), |
56 | IWL_CMD(REPLY_TXFIFO_FLUSH); | 56 | IWL_CMD_ENTRY(REPLY_TXFIFO_FLUSH), |
57 | IWL_CMD(REPLY_WEPKEY); | 57 | IWL_CMD_ENTRY(REPLY_WEPKEY), |
58 | IWL_CMD(REPLY_TX); | 58 | IWL_CMD_ENTRY(REPLY_TX), |
59 | IWL_CMD(REPLY_LEDS_CMD); | 59 | IWL_CMD_ENTRY(REPLY_LEDS_CMD), |
60 | IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); | 60 | IWL_CMD_ENTRY(REPLY_TX_LINK_QUALITY_CMD), |
61 | IWL_CMD(COEX_PRIORITY_TABLE_CMD); | 61 | IWL_CMD_ENTRY(COEX_PRIORITY_TABLE_CMD), |
62 | IWL_CMD(COEX_MEDIUM_NOTIFICATION); | 62 | IWL_CMD_ENTRY(COEX_MEDIUM_NOTIFICATION), |
63 | IWL_CMD(COEX_EVENT_CMD); | 63 | IWL_CMD_ENTRY(COEX_EVENT_CMD), |
64 | IWL_CMD(REPLY_QUIET_CMD); | 64 | IWL_CMD_ENTRY(REPLY_QUIET_CMD), |
65 | IWL_CMD(REPLY_CHANNEL_SWITCH); | 65 | IWL_CMD_ENTRY(REPLY_CHANNEL_SWITCH), |
66 | IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); | 66 | IWL_CMD_ENTRY(CHANNEL_SWITCH_NOTIFICATION), |
67 | IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); | 67 | IWL_CMD_ENTRY(REPLY_SPECTRUM_MEASUREMENT_CMD), |
68 | IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); | 68 | IWL_CMD_ENTRY(SPECTRUM_MEASURE_NOTIFICATION), |
69 | IWL_CMD(POWER_TABLE_CMD); | 69 | IWL_CMD_ENTRY(POWER_TABLE_CMD), |
70 | IWL_CMD(PM_SLEEP_NOTIFICATION); | 70 | IWL_CMD_ENTRY(PM_SLEEP_NOTIFICATION), |
71 | IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); | 71 | IWL_CMD_ENTRY(PM_DEBUG_STATISTIC_NOTIFIC), |
72 | IWL_CMD(REPLY_SCAN_CMD); | 72 | IWL_CMD_ENTRY(REPLY_SCAN_CMD), |
73 | IWL_CMD(REPLY_SCAN_ABORT_CMD); | 73 | IWL_CMD_ENTRY(REPLY_SCAN_ABORT_CMD), |
74 | IWL_CMD(SCAN_START_NOTIFICATION); | 74 | IWL_CMD_ENTRY(SCAN_START_NOTIFICATION), |
75 | IWL_CMD(SCAN_RESULTS_NOTIFICATION); | 75 | IWL_CMD_ENTRY(SCAN_RESULTS_NOTIFICATION), |
76 | IWL_CMD(SCAN_COMPLETE_NOTIFICATION); | 76 | IWL_CMD_ENTRY(SCAN_COMPLETE_NOTIFICATION), |
77 | IWL_CMD(BEACON_NOTIFICATION); | 77 | IWL_CMD_ENTRY(BEACON_NOTIFICATION), |
78 | IWL_CMD(REPLY_TX_BEACON); | 78 | IWL_CMD_ENTRY(REPLY_TX_BEACON), |
79 | IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); | 79 | IWL_CMD_ENTRY(WHO_IS_AWAKE_NOTIFICATION), |
80 | IWL_CMD(QUIET_NOTIFICATION); | 80 | IWL_CMD_ENTRY(QUIET_NOTIFICATION), |
81 | IWL_CMD(REPLY_TX_PWR_TABLE_CMD); | 81 | IWL_CMD_ENTRY(REPLY_TX_PWR_TABLE_CMD), |
82 | IWL_CMD(MEASURE_ABORT_NOTIFICATION); | 82 | IWL_CMD_ENTRY(MEASURE_ABORT_NOTIFICATION), |
83 | IWL_CMD(REPLY_BT_CONFIG); | 83 | IWL_CMD_ENTRY(REPLY_BT_CONFIG), |
84 | IWL_CMD(REPLY_STATISTICS_CMD); | 84 | IWL_CMD_ENTRY(REPLY_STATISTICS_CMD), |
85 | IWL_CMD(STATISTICS_NOTIFICATION); | 85 | IWL_CMD_ENTRY(STATISTICS_NOTIFICATION), |
86 | IWL_CMD(REPLY_CARD_STATE_CMD); | 86 | IWL_CMD_ENTRY(REPLY_CARD_STATE_CMD), |
87 | IWL_CMD(CARD_STATE_NOTIFICATION); | 87 | IWL_CMD_ENTRY(CARD_STATE_NOTIFICATION), |
88 | IWL_CMD(MISSED_BEACONS_NOTIFICATION); | 88 | IWL_CMD_ENTRY(MISSED_BEACONS_NOTIFICATION), |
89 | IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); | 89 | IWL_CMD_ENTRY(REPLY_CT_KILL_CONFIG_CMD), |
90 | IWL_CMD(SENSITIVITY_CMD); | 90 | IWL_CMD_ENTRY(SENSITIVITY_CMD), |
91 | IWL_CMD(REPLY_PHY_CALIBRATION_CMD); | 91 | IWL_CMD_ENTRY(REPLY_PHY_CALIBRATION_CMD), |
92 | IWL_CMD(REPLY_RX_PHY_CMD); | 92 | IWL_CMD_ENTRY(REPLY_RX_PHY_CMD), |
93 | IWL_CMD(REPLY_RX_MPDU_CMD); | 93 | IWL_CMD_ENTRY(REPLY_RX_MPDU_CMD), |
94 | IWL_CMD(REPLY_RX); | 94 | IWL_CMD_ENTRY(REPLY_RX), |
95 | IWL_CMD(REPLY_COMPRESSED_BA); | 95 | IWL_CMD_ENTRY(REPLY_COMPRESSED_BA), |
96 | IWL_CMD(CALIBRATION_CFG_CMD); | 96 | IWL_CMD_ENTRY(CALIBRATION_CFG_CMD), |
97 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); | 97 | IWL_CMD_ENTRY(CALIBRATION_RES_NOTIFICATION), |
98 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); | 98 | IWL_CMD_ENTRY(CALIBRATION_COMPLETE_NOTIFICATION), |
99 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); | 99 | IWL_CMD_ENTRY(REPLY_TX_POWER_DBM_CMD), |
100 | IWL_CMD(TEMPERATURE_NOTIFICATION); | 100 | IWL_CMD_ENTRY(TEMPERATURE_NOTIFICATION), |
101 | IWL_CMD(TX_ANT_CONFIGURATION_CMD); | 101 | IWL_CMD_ENTRY(TX_ANT_CONFIGURATION_CMD), |
102 | IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); | 102 | IWL_CMD_ENTRY(REPLY_BT_COEX_PROFILE_NOTIF), |
103 | IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); | 103 | IWL_CMD_ENTRY(REPLY_BT_COEX_PRIO_TABLE), |
104 | IWL_CMD(REPLY_BT_COEX_PROT_ENV); | 104 | IWL_CMD_ENTRY(REPLY_BT_COEX_PROT_ENV), |
105 | IWL_CMD(REPLY_WIPAN_PARAMS); | 105 | IWL_CMD_ENTRY(REPLY_WIPAN_PARAMS), |
106 | IWL_CMD(REPLY_WIPAN_RXON); | 106 | IWL_CMD_ENTRY(REPLY_WIPAN_RXON), |
107 | IWL_CMD(REPLY_WIPAN_RXON_TIMING); | 107 | IWL_CMD_ENTRY(REPLY_WIPAN_RXON_TIMING), |
108 | IWL_CMD(REPLY_WIPAN_RXON_ASSOC); | 108 | IWL_CMD_ENTRY(REPLY_WIPAN_RXON_ASSOC), |
109 | IWL_CMD(REPLY_WIPAN_QOS_PARAM); | 109 | IWL_CMD_ENTRY(REPLY_WIPAN_QOS_PARAM), |
110 | IWL_CMD(REPLY_WIPAN_WEPKEY); | 110 | IWL_CMD_ENTRY(REPLY_WIPAN_WEPKEY), |
111 | IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); | 111 | IWL_CMD_ENTRY(REPLY_WIPAN_P2P_CHANNEL_SWITCH), |
112 | IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); | 112 | IWL_CMD_ENTRY(REPLY_WIPAN_NOA_NOTIFICATION), |
113 | IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); | 113 | IWL_CMD_ENTRY(REPLY_WIPAN_DEACTIVATION_COMPLETE), |
114 | IWL_CMD(REPLY_WOWLAN_PATTERNS); | 114 | IWL_CMD_ENTRY(REPLY_WOWLAN_PATTERNS), |
115 | IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER); | 115 | IWL_CMD_ENTRY(REPLY_WOWLAN_WAKEUP_FILTER), |
116 | IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS); | 116 | IWL_CMD_ENTRY(REPLY_WOWLAN_TSC_RSC_PARAMS), |
117 | IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); | 117 | IWL_CMD_ENTRY(REPLY_WOWLAN_TKIP_PARAMS), |
118 | IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); | 118 | IWL_CMD_ENTRY(REPLY_WOWLAN_KEK_KCK_MATERIAL), |
119 | IWL_CMD(REPLY_WOWLAN_GET_STATUS); | 119 | IWL_CMD_ENTRY(REPLY_WOWLAN_GET_STATUS), |
120 | IWL_CMD(REPLY_D3_CONFIG); | 120 | IWL_CMD_ENTRY(REPLY_D3_CONFIG), |
121 | default: | 121 | }; |
122 | return "UNKNOWN"; | 122 | #undef IWL_CMD_ENTRY |
123 | |||
124 | } | ||
125 | } | ||
126 | 123 | ||
127 | /****************************************************************************** | 124 | /****************************************************************************** |
128 | * | 125 | * |
@@ -137,10 +134,9 @@ static int iwlagn_rx_reply_error(struct iwl_priv *priv, | |||
137 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 134 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
138 | struct iwl_error_resp *err_resp = (void *)pkt->data; | 135 | struct iwl_error_resp *err_resp = (void *)pkt->data; |
139 | 136 | ||
140 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | 137 | IWL_ERR(priv, "Error Reply type 0x%08X cmd REPLY_ERROR (0x%02X) " |
141 | "seq 0x%04X ser 0x%08X\n", | 138 | "seq 0x%04X ser 0x%08X\n", |
142 | le32_to_cpu(err_resp->error_type), | 139 | le32_to_cpu(err_resp->error_type), |
143 | get_cmd_string(err_resp->cmd_id), | ||
144 | err_resp->cmd_id, | 140 | err_resp->cmd_id, |
145 | le16_to_cpu(err_resp->bad_cmd_seq_num), | 141 | le16_to_cpu(err_resp->bad_cmd_seq_num), |
146 | le32_to_cpu(err_resp->error_info)); | 142 | le32_to_cpu(err_resp->error_info)); |
@@ -216,8 +212,7 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
216 | u32 __maybe_unused len = | 212 | u32 __maybe_unused len = |
217 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 213 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
218 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 214 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
219 | "notification for %s:\n", len, | 215 | "notification for PM_DEBUG_STATISTIC_NOTIFIC:\n", len); |
220 | get_cmd_string(pkt->hdr.cmd)); | ||
221 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len); | 216 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len); |
222 | return 0; | 217 | return 0; |
223 | } | 218 | } |
@@ -246,69 +241,6 @@ static int iwlagn_rx_beacon_notif(struct iwl_priv *priv, | |||
246 | return 0; | 241 | return 0; |
247 | } | 242 | } |
248 | 243 | ||
249 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
250 | #define ACK_CNT_RATIO (50) | ||
251 | #define BA_TIMEOUT_CNT (5) | ||
252 | #define BA_TIMEOUT_MAX (16) | ||
253 | |||
254 | /** | ||
255 | * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. | ||
256 | * | ||
257 | * When the ACK count ratio is low and aggregated BA timeout retries exceeding | ||
258 | * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal | ||
259 | * operation state. | ||
260 | */ | ||
261 | static bool iwlagn_good_ack_health(struct iwl_priv *priv, | ||
262 | struct statistics_tx *cur) | ||
263 | { | ||
264 | int actual_delta, expected_delta, ba_timeout_delta; | ||
265 | struct statistics_tx *old; | ||
266 | |||
267 | if (priv->agg_tids_count) | ||
268 | return true; | ||
269 | |||
270 | lockdep_assert_held(&priv->statistics.lock); | ||
271 | |||
272 | old = &priv->statistics.tx; | ||
273 | |||
274 | actual_delta = le32_to_cpu(cur->actual_ack_cnt) - | ||
275 | le32_to_cpu(old->actual_ack_cnt); | ||
276 | expected_delta = le32_to_cpu(cur->expected_ack_cnt) - | ||
277 | le32_to_cpu(old->expected_ack_cnt); | ||
278 | |||
279 | /* Values should not be negative, but we do not trust the firmware */ | ||
280 | if (actual_delta <= 0 || expected_delta <= 0) | ||
281 | return true; | ||
282 | |||
283 | ba_timeout_delta = le32_to_cpu(cur->agg.ba_timeout) - | ||
284 | le32_to_cpu(old->agg.ba_timeout); | ||
285 | |||
286 | if ((actual_delta * 100 / expected_delta) < ACK_CNT_RATIO && | ||
287 | ba_timeout_delta > BA_TIMEOUT_CNT) { | ||
288 | IWL_DEBUG_RADIO(priv, | ||
289 | "deltas: actual %d expected %d ba_timeout %d\n", | ||
290 | actual_delta, expected_delta, ba_timeout_delta); | ||
291 | |||
292 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
293 | /* | ||
294 | * This is ifdef'ed on DEBUGFS because otherwise the | ||
295 | * statistics aren't available. If DEBUGFS is set but | ||
296 | * DEBUG is not, these will just compile out. | ||
297 | */ | ||
298 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n", | ||
299 | priv->delta_stats.tx.rx_detected_cnt); | ||
300 | IWL_DEBUG_RADIO(priv, | ||
301 | "ack_or_ba_timeout_collision delta %d\n", | ||
302 | priv->delta_stats.tx.ack_or_ba_timeout_collision); | ||
303 | #endif | ||
304 | |||
305 | if (ba_timeout_delta >= BA_TIMEOUT_MAX) | ||
306 | return false; | ||
307 | } | ||
308 | |||
309 | return true; | ||
310 | } | ||
311 | |||
312 | /** | 244 | /** |
313 | * iwl_good_plcp_health - checks for plcp error. | 245 | * iwl_good_plcp_health - checks for plcp error. |
314 | * | 246 | * |
@@ -347,6 +279,45 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv, | |||
347 | return true; | 279 | return true; |
348 | } | 280 | } |
349 | 281 | ||
282 | int iwl_force_rf_reset(struct iwl_priv *priv, bool external) | ||
283 | { | ||
284 | struct iwl_rf_reset *rf_reset; | ||
285 | |||
286 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
287 | return -EAGAIN; | ||
288 | |||
289 | if (!iwl_is_any_associated(priv)) { | ||
290 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); | ||
291 | return -ENOLINK; | ||
292 | } | ||
293 | |||
294 | rf_reset = &priv->rf_reset; | ||
295 | rf_reset->reset_request_count++; | ||
296 | if (!external && rf_reset->last_reset_jiffies && | ||
297 | time_after(rf_reset->last_reset_jiffies + | ||
298 | IWL_DELAY_NEXT_FORCE_RF_RESET, jiffies)) { | ||
299 | IWL_DEBUG_INFO(priv, "RF reset rejected\n"); | ||
300 | rf_reset->reset_reject_count++; | ||
301 | return -EAGAIN; | ||
302 | } | ||
303 | rf_reset->reset_success_count++; | ||
304 | rf_reset->last_reset_jiffies = jiffies; | ||
305 | |||
306 | /* | ||
307 | * There is no easy and better way to force reset the radio, | ||
308 | * the only known method is switching channel which will force to | ||
309 | * reset and tune the radio. | ||
310 | * Use internal short scan (single channel) operation to should | ||
311 | * achieve this objective. | ||
312 | * Driver should reset the radio when number of consecutive missed | ||
313 | * beacon, or any other uCode error condition detected. | ||
314 | */ | ||
315 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); | ||
316 | iwl_internal_short_hw_scan(priv); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | |||
350 | static void iwlagn_recover_from_statistics(struct iwl_priv *priv, | 321 | static void iwlagn_recover_from_statistics(struct iwl_priv *priv, |
351 | struct statistics_rx_phy *cur_ofdm, | 322 | struct statistics_rx_phy *cur_ofdm, |
352 | struct statistics_rx_ht_phy *cur_ofdm_ht, | 323 | struct statistics_rx_ht_phy *cur_ofdm_ht, |
@@ -368,15 +339,9 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv, | |||
368 | if (msecs < 99) | 339 | if (msecs < 99) |
369 | return; | 340 | return; |
370 | 341 | ||
371 | if (iwlagn_mod_params.ack_check && !iwlagn_good_ack_health(priv, tx)) { | ||
372 | IWL_ERR(priv, "low ack count detected, restart firmware\n"); | ||
373 | if (!iwl_force_reset(priv, IWL_FW_RESET, false)) | ||
374 | return; | ||
375 | } | ||
376 | |||
377 | if (iwlagn_mod_params.plcp_check && | 342 | if (iwlagn_mod_params.plcp_check && |
378 | !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) | 343 | !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) |
379 | iwl_force_reset(priv, IWL_RF_RESET, false); | 344 | iwl_force_rf_reset(priv, false); |
380 | } | 345 | } |
381 | 346 | ||
382 | /* Calculate noise level, based on measurements during network silence just | 347 | /* Calculate noise level, based on measurements during network silence just |
@@ -589,8 +554,8 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
589 | iwlagn_rx_calc_noise(priv); | 554 | iwlagn_rx_calc_noise(priv); |
590 | queue_work(priv->workqueue, &priv->run_time_calib_work); | 555 | queue_work(priv->workqueue, &priv->run_time_calib_work); |
591 | } | 556 | } |
592 | if (cfg(priv)->lib->temperature && change) | 557 | if (priv->lib->temperature && change) |
593 | cfg(priv)->lib->temperature(priv); | 558 | priv->lib->temperature(priv); |
594 | 559 | ||
595 | spin_unlock(&priv->statistics.lock); | 560 | spin_unlock(&priv->statistics.lock); |
596 | 561 | ||
@@ -1182,9 +1147,9 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | |||
1182 | err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); | 1147 | err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); |
1183 | } else { | 1148 | } else { |
1184 | /* No handling needed */ | 1149 | /* No handling needed */ |
1185 | IWL_DEBUG_RX(priv, | 1150 | IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n", |
1186 | "No handler needed for %s, 0x%02x\n", | 1151 | iwl_dvm_get_cmd_string(pkt->hdr.cmd), |
1187 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 1152 | pkt->hdr.cmd); |
1188 | } | 1153 | } |
1189 | } | 1154 | } |
1190 | return err; | 1155 | return err; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 79d857d81b41..5c7bddd5cfef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -32,6 +32,78 @@ | |||
32 | #include "iwl-trans.h" | 32 | #include "iwl-trans.h" |
33 | #include "iwl-shared.h" | 33 | #include "iwl-shared.h" |
34 | 34 | ||
35 | /* | ||
36 | * initialize rxon structure with default values from eeprom | ||
37 | */ | ||
38 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||
39 | struct iwl_rxon_context *ctx) | ||
40 | { | ||
41 | const struct iwl_channel_info *ch_info; | ||
42 | |||
43 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | ||
44 | |||
45 | if (!ctx->vif) { | ||
46 | ctx->staging.dev_type = ctx->unused_devtype; | ||
47 | } else | ||
48 | switch (ctx->vif->type) { | ||
49 | case NL80211_IFTYPE_AP: | ||
50 | ctx->staging.dev_type = ctx->ap_devtype; | ||
51 | break; | ||
52 | |||
53 | case NL80211_IFTYPE_STATION: | ||
54 | ctx->staging.dev_type = ctx->station_devtype; | ||
55 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | ||
56 | break; | ||
57 | |||
58 | case NL80211_IFTYPE_ADHOC: | ||
59 | ctx->staging.dev_type = ctx->ibss_devtype; | ||
60 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | ||
61 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | | ||
62 | RXON_FILTER_ACCEPT_GRP_MSK; | ||
63 | break; | ||
64 | |||
65 | default: | ||
66 | IWL_ERR(priv, "Unsupported interface type %d\n", | ||
67 | ctx->vif->type); | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | #if 0 | ||
72 | /* TODO: Figure out when short_preamble would be set and cache from | ||
73 | * that */ | ||
74 | if (!hw_to_local(priv->hw)->short_preamble) | ||
75 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
76 | else | ||
77 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
78 | #endif | ||
79 | |||
80 | ch_info = iwl_get_channel_info(priv, priv->band, | ||
81 | le16_to_cpu(ctx->active.channel)); | ||
82 | |||
83 | if (!ch_info) | ||
84 | ch_info = &priv->channel_info[0]; | ||
85 | |||
86 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | ||
87 | priv->band = ch_info->band; | ||
88 | |||
89 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | ||
90 | |||
91 | ctx->staging.ofdm_basic_rates = | ||
92 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
93 | ctx->staging.cck_basic_rates = | ||
94 | (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
95 | |||
96 | /* clear both MIX and PURE40 mode flag */ | ||
97 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | ||
98 | RXON_FLG_CHANNEL_MODE_PURE_40); | ||
99 | if (ctx->vif) | ||
100 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); | ||
101 | |||
102 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; | ||
103 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | ||
104 | ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; | ||
105 | } | ||
106 | |||
35 | static int iwlagn_disable_bss(struct iwl_priv *priv, | 107 | static int iwlagn_disable_bss(struct iwl_priv *priv, |
36 | struct iwl_rxon_context *ctx, | 108 | struct iwl_rxon_context *ctx, |
37 | struct iwl_rxon_cmd *send) | 109 | struct iwl_rxon_cmd *send) |
@@ -105,8 +177,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, | |||
105 | return ret; | 177 | return ret; |
106 | } | 178 | } |
107 | 179 | ||
108 | static void iwlagn_update_qos(struct iwl_priv *priv, | 180 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
109 | struct iwl_rxon_context *ctx) | ||
110 | { | 181 | { |
111 | int ret; | 182 | int ret; |
112 | 183 | ||
@@ -133,8 +204,8 @@ static void iwlagn_update_qos(struct iwl_priv *priv, | |||
133 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); | 204 | IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); |
134 | } | 205 | } |
135 | 206 | ||
136 | static int iwlagn_update_beacon(struct iwl_priv *priv, | 207 | int iwlagn_update_beacon(struct iwl_priv *priv, |
137 | struct ieee80211_vif *vif) | 208 | struct ieee80211_vif *vif) |
138 | { | 209 | { |
139 | lockdep_assert_held(&priv->mutex); | 210 | lockdep_assert_held(&priv->mutex); |
140 | 211 | ||
@@ -335,6 +406,64 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv, | |||
335 | return 0; | 406 | return 0; |
336 | } | 407 | } |
337 | 408 | ||
409 | static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | ||
410 | { | ||
411 | int ret; | ||
412 | s8 prev_tx_power; | ||
413 | bool defer; | ||
414 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
415 | |||
416 | if (priv->calib_disabled & IWL_TX_POWER_CALIB_DISABLED) | ||
417 | return 0; | ||
418 | |||
419 | lockdep_assert_held(&priv->mutex); | ||
420 | |||
421 | if (priv->tx_power_user_lmt == tx_power && !force) | ||
422 | return 0; | ||
423 | |||
424 | if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { | ||
425 | IWL_WARN(priv, | ||
426 | "Requested user TXPOWER %d below lower limit %d.\n", | ||
427 | tx_power, | ||
428 | IWLAGN_TX_POWER_TARGET_POWER_MIN); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | |||
432 | if (tx_power > priv->tx_power_device_lmt) { | ||
433 | IWL_WARN(priv, | ||
434 | "Requested user TXPOWER %d above upper limit %d.\n", | ||
435 | tx_power, priv->tx_power_device_lmt); | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | |||
439 | if (!iwl_is_ready_rf(priv)) | ||
440 | return -EIO; | ||
441 | |||
442 | /* scan complete and commit_rxon use tx_power_next value, | ||
443 | * it always need to be updated for newest request */ | ||
444 | priv->tx_power_next = tx_power; | ||
445 | |||
446 | /* do not set tx power when scanning or channel changing */ | ||
447 | defer = test_bit(STATUS_SCANNING, &priv->status) || | ||
448 | memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); | ||
449 | if (defer && !force) { | ||
450 | IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | prev_tx_power = priv->tx_power_user_lmt; | ||
455 | priv->tx_power_user_lmt = tx_power; | ||
456 | |||
457 | ret = iwlagn_send_tx_power(priv); | ||
458 | |||
459 | /* if fail to set tx_power, restore the orig. tx power */ | ||
460 | if (ret) { | ||
461 | priv->tx_power_user_lmt = prev_tx_power; | ||
462 | priv->tx_power_next = prev_tx_power; | ||
463 | } | ||
464 | return ret; | ||
465 | } | ||
466 | |||
338 | static int iwlagn_rxon_connect(struct iwl_priv *priv, | 467 | static int iwlagn_rxon_connect(struct iwl_priv *priv, |
339 | struct iwl_rxon_context *ctx) | 468 | struct iwl_rxon_context *ctx) |
340 | { | 469 | { |
@@ -501,6 +630,161 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
501 | return ret; | 630 | return ret; |
502 | } | 631 | } |
503 | 632 | ||
633 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, | ||
634 | struct iwl_ht_config *ht_conf, | ||
635 | struct iwl_rxon_context *ctx) | ||
636 | { | ||
637 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
638 | |||
639 | if (!ctx->ht.enabled) { | ||
640 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
641 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
642 | RXON_FLG_HT40_PROT_MSK | | ||
643 | RXON_FLG_HT_PROT_MSK); | ||
644 | return; | ||
645 | } | ||
646 | |||
647 | /* FIXME: if the definition of ht.protection changed, the "translation" | ||
648 | * will be needed for rxon->flags | ||
649 | */ | ||
650 | rxon->flags |= cpu_to_le32(ctx->ht.protection << | ||
651 | RXON_FLG_HT_OPERATING_MODE_POS); | ||
652 | |||
653 | /* Set up channel bandwidth: | ||
654 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | ||
655 | /* clear the HT channel mode before set the mode */ | ||
656 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
657 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
658 | if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) { | ||
659 | /* pure ht40 */ | ||
660 | if (ctx->ht.protection == | ||
661 | IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | ||
662 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | ||
663 | /* | ||
664 | * Note: control channel is opposite of extension | ||
665 | * channel | ||
666 | */ | ||
667 | switch (ctx->ht.extension_chan_offset) { | ||
668 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
669 | rxon->flags &= | ||
670 | ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
671 | break; | ||
672 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
673 | rxon->flags |= | ||
674 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
675 | break; | ||
676 | } | ||
677 | } else { | ||
678 | /* | ||
679 | * Note: control channel is opposite of extension | ||
680 | * channel | ||
681 | */ | ||
682 | switch (ctx->ht.extension_chan_offset) { | ||
683 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
684 | rxon->flags &= | ||
685 | ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
686 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
687 | break; | ||
688 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
689 | rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
690 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
691 | break; | ||
692 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
693 | default: | ||
694 | /* | ||
695 | * channel location only valid if in Mixed | ||
696 | * mode | ||
697 | */ | ||
698 | IWL_ERR(priv, | ||
699 | "invalid extension channel offset\n"); | ||
700 | break; | ||
701 | } | ||
702 | } | ||
703 | } else { | ||
704 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; | ||
705 | } | ||
706 | |||
707 | iwlagn_set_rxon_chain(priv, ctx); | ||
708 | |||
709 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " | ||
710 | "extension channel offset 0x%x\n", | ||
711 | le32_to_cpu(rxon->flags), ctx->ht.protection, | ||
712 | ctx->ht.extension_chan_offset); | ||
713 | } | ||
714 | |||
715 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | ||
716 | { | ||
717 | struct iwl_rxon_context *ctx; | ||
718 | |||
719 | for_each_context(priv, ctx) | ||
720 | _iwl_set_rxon_ht(priv, ht_conf, ctx); | ||
721 | } | ||
722 | |||
723 | /** | ||
724 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON | ||
725 | * @ch: requested channel as a pointer to struct ieee80211_channel | ||
726 | |||
727 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | ||
728 | * in the staging RXON flag structure based on the ch->band | ||
729 | */ | ||
730 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | ||
731 | struct iwl_rxon_context *ctx) | ||
732 | { | ||
733 | enum ieee80211_band band = ch->band; | ||
734 | u16 channel = ch->hw_value; | ||
735 | |||
736 | if ((le16_to_cpu(ctx->staging.channel) == channel) && | ||
737 | (priv->band == band)) | ||
738 | return; | ||
739 | |||
740 | ctx->staging.channel = cpu_to_le16(channel); | ||
741 | if (band == IEEE80211_BAND_5GHZ) | ||
742 | ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; | ||
743 | else | ||
744 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
745 | |||
746 | priv->band = band; | ||
747 | |||
748 | IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band); | ||
749 | |||
750 | } | ||
751 | |||
752 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
753 | struct iwl_rxon_context *ctx, | ||
754 | enum ieee80211_band band, | ||
755 | struct ieee80211_vif *vif) | ||
756 | { | ||
757 | if (band == IEEE80211_BAND_5GHZ) { | ||
758 | ctx->staging.flags &= | ||
759 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | ||
760 | | RXON_FLG_CCK_MSK); | ||
761 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
762 | } else { | ||
763 | /* Copied from iwl_post_associate() */ | ||
764 | if (vif && vif->bss_conf.use_short_slot) | ||
765 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
766 | else | ||
767 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
768 | |||
769 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
770 | ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; | ||
771 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | void iwl_set_rate(struct iwl_priv *priv) | ||
776 | { | ||
777 | struct iwl_rxon_context *ctx; | ||
778 | |||
779 | for_each_context(priv, ctx) { | ||
780 | ctx->staging.cck_basic_rates = | ||
781 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
782 | |||
783 | ctx->staging.ofdm_basic_rates = | ||
784 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
785 | } | ||
786 | } | ||
787 | |||
504 | static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, | 788 | static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, |
505 | struct iwl_rxon_context *ctx, int hw_decrypt) | 789 | struct iwl_rxon_context *ctx, int hw_decrypt) |
506 | { | 790 | { |
@@ -594,8 +878,8 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv, | |||
594 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | 878 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that |
595 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | 879 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |
596 | */ | 880 | */ |
597 | static int iwl_full_rxon_required(struct iwl_priv *priv, | 881 | int iwl_full_rxon_required(struct iwl_priv *priv, |
598 | struct iwl_rxon_context *ctx) | 882 | struct iwl_rxon_context *ctx) |
599 | { | 883 | { |
600 | const struct iwl_rxon_cmd *staging = &ctx->staging; | 884 | const struct iwl_rxon_cmd *staging = &ctx->staging; |
601 | const struct iwl_rxon_cmd *active = &ctx->active; | 885 | const struct iwl_rxon_cmd *active = &ctx->active; |
@@ -649,6 +933,33 @@ static int iwl_full_rxon_required(struct iwl_priv *priv, | |||
649 | return 0; | 933 | return 0; |
650 | } | 934 | } |
651 | 935 | ||
936 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
937 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | ||
938 | enum iwl_rxon_context_id ctxid) | ||
939 | { | ||
940 | struct iwl_rxon_context *ctx = &priv->contexts[ctxid]; | ||
941 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
942 | |||
943 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); | ||
944 | iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | ||
945 | IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", | ||
946 | le16_to_cpu(rxon->channel)); | ||
947 | IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", | ||
948 | le32_to_cpu(rxon->flags)); | ||
949 | IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", | ||
950 | le32_to_cpu(rxon->filter_flags)); | ||
951 | IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type); | ||
952 | IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n", | ||
953 | rxon->ofdm_basic_rates); | ||
954 | IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", | ||
955 | rxon->cck_basic_rates); | ||
956 | IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr); | ||
957 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | ||
958 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", | ||
959 | le16_to_cpu(rxon->assoc_id)); | ||
960 | } | ||
961 | #endif | ||
962 | |||
652 | /** | 963 | /** |
653 | * iwlagn_commit_rxon - commit staging_rxon to hardware | 964 | * iwlagn_commit_rxon - commit staging_rxon to hardware |
654 | * | 965 | * |
@@ -692,7 +1003,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
692 | * force CTS-to-self frames protection if RTS-CTS is not preferred | 1003 | * force CTS-to-self frames protection if RTS-CTS is not preferred |
693 | * one aggregation protection method | 1004 | * one aggregation protection method |
694 | */ | 1005 | */ |
695 | if (!hw_params(priv).use_rts_for_aggregation) | 1006 | if (!priv->hw_params.use_rts_for_aggregation) |
696 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; | 1007 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; |
697 | 1008 | ||
698 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || | 1009 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || |
@@ -911,9 +1222,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
911 | return ret; | 1222 | return ret; |
912 | } | 1223 | } |
913 | 1224 | ||
914 | static void iwlagn_check_needed_chains(struct iwl_priv *priv, | 1225 | void iwlagn_check_needed_chains(struct iwl_priv *priv, |
915 | struct iwl_rxon_context *ctx, | 1226 | struct iwl_rxon_context *ctx, |
916 | struct ieee80211_bss_conf *bss_conf) | 1227 | struct ieee80211_bss_conf *bss_conf) |
917 | { | 1228 | { |
918 | struct ieee80211_vif *vif = ctx->vif; | 1229 | struct ieee80211_vif *vif = ctx->vif; |
919 | struct iwl_rxon_context *tmp; | 1230 | struct iwl_rxon_context *tmp; |
@@ -1005,11 +1316,14 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, | |||
1005 | ht_conf->single_chain_sufficient = !need_multiple; | 1316 | ht_conf->single_chain_sufficient = !need_multiple; |
1006 | } | 1317 | } |
1007 | 1318 | ||
1008 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | 1319 | void iwlagn_chain_noise_reset(struct iwl_priv *priv) |
1009 | { | 1320 | { |
1010 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 1321 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
1011 | int ret; | 1322 | int ret; |
1012 | 1323 | ||
1324 | if (!(priv->calib_disabled & IWL_CHAIN_NOISE_CALIB_DISABLED)) | ||
1325 | return; | ||
1326 | |||
1013 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && | 1327 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
1014 | iwl_is_any_associated(priv)) { | 1328 | iwl_is_any_associated(priv)) { |
1015 | struct iwl_calib_chain_noise_reset_cmd cmd; | 1329 | struct iwl_calib_chain_noise_reset_cmd cmd; |
@@ -1162,8 +1476,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
1162 | iwl_power_update_mode(priv, false); | 1476 | iwl_power_update_mode(priv, false); |
1163 | 1477 | ||
1164 | /* Enable RX differential gain and sensitivity calibrations */ | 1478 | /* Enable RX differential gain and sensitivity calibrations */ |
1165 | if (!priv->disable_chain_noise_cal) | 1479 | iwlagn_chain_noise_reset(priv); |
1166 | iwlagn_chain_noise_reset(priv); | ||
1167 | priv->start_calib = 1; | 1480 | priv->start_calib = 1; |
1168 | } | 1481 | } |
1169 | 1482 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index c4175603864b..0119e7a7b78d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "iwl-agn.h" | 34 | #include "iwl-agn.h" |
35 | #include "iwl-trans.h" | 35 | #include "iwl-trans.h" |
36 | 36 | ||
37 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
38 | |||
37 | static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 39 | static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
38 | { | 40 | { |
39 | lockdep_assert_held(&priv->sta_lock); | 41 | lockdep_assert_held(&priv->sta_lock); |
@@ -170,6 +172,50 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
170 | return cmd.handler_status; | 172 | return cmd.handler_status; |
171 | } | 173 | } |
172 | 174 | ||
175 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | ||
176 | enum ieee80211_band band, | ||
177 | u16 channel, u8 extension_chan_offset) | ||
178 | { | ||
179 | const struct iwl_channel_info *ch_info; | ||
180 | |||
181 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
182 | if (!is_channel_valid(ch_info)) | ||
183 | return false; | ||
184 | |||
185 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
186 | return !(ch_info->ht40_extension_channel & | ||
187 | IEEE80211_CHAN_NO_HT40PLUS); | ||
188 | else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
189 | return !(ch_info->ht40_extension_channel & | ||
190 | IEEE80211_CHAN_NO_HT40MINUS); | ||
191 | |||
192 | return false; | ||
193 | } | ||
194 | |||
195 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||
196 | struct iwl_rxon_context *ctx, | ||
197 | struct ieee80211_sta_ht_cap *ht_cap) | ||
198 | { | ||
199 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | ||
200 | return false; | ||
201 | |||
202 | /* | ||
203 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | ||
204 | * the bit will not set if it is pure 40MHz case | ||
205 | */ | ||
206 | if (ht_cap && !ht_cap->ht_supported) | ||
207 | return false; | ||
208 | |||
209 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
210 | if (priv->disable_ht40) | ||
211 | return false; | ||
212 | #endif | ||
213 | |||
214 | return iwl_is_channel_extension(priv, priv->band, | ||
215 | le16_to_cpu(ctx->staging.channel), | ||
216 | ctx->ht.extension_chan_offset); | ||
217 | } | ||
218 | |||
173 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | 219 | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, |
174 | struct ieee80211_sta *sta, | 220 | struct ieee80211_sta *sta, |
175 | struct iwl_rxon_context *ctx, | 221 | struct iwl_rxon_context *ctx, |
@@ -581,6 +627,56 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id, | |||
581 | spin_unlock_bh(&priv->sta_lock); | 627 | spin_unlock_bh(&priv->sta_lock); |
582 | } | 628 | } |
583 | 629 | ||
630 | static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
631 | u8 sta_id, struct iwl_link_quality_cmd *link_cmd) | ||
632 | { | ||
633 | int i, r; | ||
634 | u32 rate_flags = 0; | ||
635 | __le32 rate_n_flags; | ||
636 | |||
637 | lockdep_assert_held(&priv->mutex); | ||
638 | |||
639 | memset(link_cmd, 0, sizeof(*link_cmd)); | ||
640 | |||
641 | /* Set up the rate scaling to start at selected rate, fall back | ||
642 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
643 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
644 | r = IWL_RATE_6M_INDEX; | ||
645 | else if (ctx && ctx->vif && ctx->vif->p2p) | ||
646 | r = IWL_RATE_6M_INDEX; | ||
647 | else | ||
648 | r = IWL_RATE_1M_INDEX; | ||
649 | |||
650 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
651 | rate_flags |= RATE_MCS_CCK_MSK; | ||
652 | |||
653 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
654 | RATE_MCS_ANT_POS; | ||
655 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
656 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | ||
657 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | ||
658 | |||
659 | link_cmd->general_params.single_stream_ant_msk = | ||
660 | first_antenna(priv->hw_params.valid_tx_ant); | ||
661 | |||
662 | link_cmd->general_params.dual_stream_ant_msk = | ||
663 | priv->hw_params.valid_tx_ant & | ||
664 | ~first_antenna(priv->hw_params.valid_tx_ant); | ||
665 | if (!link_cmd->general_params.dual_stream_ant_msk) { | ||
666 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | ||
667 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | ||
668 | link_cmd->general_params.dual_stream_ant_msk = | ||
669 | priv->hw_params.valid_tx_ant; | ||
670 | } | ||
671 | |||
672 | link_cmd->agg_params.agg_dis_start_th = | ||
673 | LINK_QUAL_AGG_DISABLE_START_DEF; | ||
674 | link_cmd->agg_params.agg_time_limit = | ||
675 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
676 | |||
677 | link_cmd->sta_id = sta_id; | ||
678 | } | ||
679 | |||
584 | /** | 680 | /** |
585 | * iwl_clear_ucode_stations - clear ucode station table bits | 681 | * iwl_clear_ucode_stations - clear ucode station table bits |
586 | * | 682 | * |
@@ -841,56 +937,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
841 | } | 937 | } |
842 | 938 | ||
843 | 939 | ||
844 | void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
845 | u8 sta_id, struct iwl_link_quality_cmd *link_cmd) | ||
846 | { | ||
847 | int i, r; | ||
848 | u32 rate_flags = 0; | ||
849 | __le32 rate_n_flags; | ||
850 | |||
851 | lockdep_assert_held(&priv->mutex); | ||
852 | |||
853 | memset(link_cmd, 0, sizeof(*link_cmd)); | ||
854 | |||
855 | /* Set up the rate scaling to start at selected rate, fall back | ||
856 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
857 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
858 | r = IWL_RATE_6M_INDEX; | ||
859 | else if (ctx && ctx->vif && ctx->vif->p2p) | ||
860 | r = IWL_RATE_6M_INDEX; | ||
861 | else | ||
862 | r = IWL_RATE_1M_INDEX; | ||
863 | |||
864 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
865 | rate_flags |= RATE_MCS_CCK_MSK; | ||
866 | |||
867 | rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) << | ||
868 | RATE_MCS_ANT_POS; | ||
869 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
870 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | ||
871 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | ||
872 | |||
873 | link_cmd->general_params.single_stream_ant_msk = | ||
874 | first_antenna(hw_params(priv).valid_tx_ant); | ||
875 | |||
876 | link_cmd->general_params.dual_stream_ant_msk = | ||
877 | hw_params(priv).valid_tx_ant & | ||
878 | ~first_antenna(hw_params(priv).valid_tx_ant); | ||
879 | if (!link_cmd->general_params.dual_stream_ant_msk) { | ||
880 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | ||
881 | } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { | ||
882 | link_cmd->general_params.dual_stream_ant_msk = | ||
883 | hw_params(priv).valid_tx_ant; | ||
884 | } | ||
885 | |||
886 | link_cmd->agg_params.agg_dis_start_th = | ||
887 | LINK_QUAL_AGG_DISABLE_START_DEF; | ||
888 | link_cmd->agg_params.agg_time_limit = | ||
889 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
890 | |||
891 | link_cmd->sta_id = sta_id; | ||
892 | } | ||
893 | |||
894 | static struct iwl_link_quality_cmd * | 940 | static struct iwl_link_quality_cmd * |
895 | iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 941 | iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
896 | u8 sta_id) | 942 | u8 sta_id) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 697f2032bfd6..ad21b5ddf59d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -208,10 +208,10 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
208 | priv->bt_full_concurrent) { | 208 | priv->bt_full_concurrent) { |
209 | /* operated as 1x1 in full concurrency mode */ | 209 | /* operated as 1x1 in full concurrency mode */ |
210 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 210 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
211 | first_antenna(hw_params(priv).valid_tx_ant)); | 211 | first_antenna(priv->hw_params.valid_tx_ant)); |
212 | } else | 212 | } else |
213 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 213 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
214 | hw_params(priv).valid_tx_ant); | 214 | priv->hw_params.valid_tx_ant); |
215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
216 | 216 | ||
217 | /* Set the rate in the TX cmd */ | 217 | /* Set the rate in the TX cmd */ |
@@ -689,7 +689,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
689 | sta_priv->max_agg_bufsize = | 689 | sta_priv->max_agg_bufsize = |
690 | min(sta_priv->max_agg_bufsize, buf_size); | 690 | min(sta_priv->max_agg_bufsize, buf_size); |
691 | 691 | ||
692 | if (hw_params(priv).use_rts_for_aggregation) { | 692 | if (priv->hw_params.use_rts_for_aggregation) { |
693 | /* | 693 | /* |
694 | * switch to RTS/CTS if it is the prefer protection | 694 | * switch to RTS/CTS if it is the prefer protection |
695 | * method for HT traffic | 695 | * method for HT traffic |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 22c953d65be5..7db39866bdc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -180,7 +180,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
180 | rate = info->control.rates[0].idx; | 180 | rate = info->control.rates[0].idx; |
181 | 181 | ||
182 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 182 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
183 | hw_params(priv).valid_tx_ant); | 183 | priv->hw_params.valid_tx_ant); |
184 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 184 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
185 | 185 | ||
186 | /* In mac80211, rates for 5 GHz start at 0 */ | 186 | /* In mac80211, rates for 5 GHz start at 0 */ |
@@ -289,6 +289,25 @@ out: | |||
289 | mutex_unlock(&priv->mutex); | 289 | mutex_unlock(&priv->mutex); |
290 | } | 290 | } |
291 | 291 | ||
292 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | ||
293 | { | ||
294 | struct iwl_statistics_cmd statistics_cmd = { | ||
295 | .configuration_flags = | ||
296 | clear ? IWL_STATS_CONF_CLEAR_STATS : 0, | ||
297 | }; | ||
298 | |||
299 | if (flags & CMD_ASYNC) | ||
300 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
301 | CMD_ASYNC, | ||
302 | sizeof(struct iwl_statistics_cmd), | ||
303 | &statistics_cmd); | ||
304 | else | ||
305 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
306 | CMD_SYNC, | ||
307 | sizeof(struct iwl_statistics_cmd), | ||
308 | &statistics_cmd); | ||
309 | } | ||
310 | |||
292 | /** | 311 | /** |
293 | * iwl_bg_statistics_periodic - Timer callback to queue statistics | 312 | * iwl_bg_statistics_periodic - Timer callback to queue statistics |
294 | * | 313 | * |
@@ -578,7 +597,7 @@ static const u8 iwlagn_pan_queue_to_ac[] = { | |||
578 | IEEE80211_AC_VO, | 597 | IEEE80211_AC_VO, |
579 | }; | 598 | }; |
580 | 599 | ||
581 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 600 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
582 | { | 601 | { |
583 | int i; | 602 | int i; |
584 | 603 | ||
@@ -645,7 +664,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
645 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 664 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
646 | } | 665 | } |
647 | 666 | ||
648 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 667 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
649 | { | 668 | { |
650 | struct iwl_ct_kill_config cmd; | 669 | struct iwl_ct_kill_config cmd; |
651 | struct iwl_ct_kill_throttling_config adv_cmd; | 670 | struct iwl_ct_kill_throttling_config adv_cmd; |
@@ -658,9 +677,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
658 | 677 | ||
659 | if (cfg(priv)->base_params->support_ct_kill_exit) { | 678 | if (cfg(priv)->base_params->support_ct_kill_exit) { |
660 | adv_cmd.critical_temperature_enter = | 679 | adv_cmd.critical_temperature_enter = |
661 | cpu_to_le32(hw_params(priv).ct_kill_threshold); | 680 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
662 | adv_cmd.critical_temperature_exit = | 681 | adv_cmd.critical_temperature_exit = |
663 | cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); | 682 | cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); |
664 | 683 | ||
665 | ret = iwl_dvm_send_cmd_pdu(priv, | 684 | ret = iwl_dvm_send_cmd_pdu(priv, |
666 | REPLY_CT_KILL_CONFIG_CMD, | 685 | REPLY_CT_KILL_CONFIG_CMD, |
@@ -671,11 +690,11 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
671 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | 690 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " |
672 | "succeeded, critical temperature enter is %d," | 691 | "succeeded, critical temperature enter is %d," |
673 | "exit is %d\n", | 692 | "exit is %d\n", |
674 | hw_params(priv).ct_kill_threshold, | 693 | priv->hw_params.ct_kill_threshold, |
675 | hw_params(priv).ct_kill_exit_threshold); | 694 | priv->hw_params.ct_kill_exit_threshold); |
676 | } else { | 695 | } else { |
677 | cmd.critical_temperature_R = | 696 | cmd.critical_temperature_R = |
678 | cpu_to_le32(hw_params(priv).ct_kill_threshold); | 697 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
679 | 698 | ||
680 | ret = iwl_dvm_send_cmd_pdu(priv, | 699 | ret = iwl_dvm_send_cmd_pdu(priv, |
681 | REPLY_CT_KILL_CONFIG_CMD, | 700 | REPLY_CT_KILL_CONFIG_CMD, |
@@ -686,7 +705,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
686 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | 705 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " |
687 | "succeeded, " | 706 | "succeeded, " |
688 | "critical temperature is %d\n", | 707 | "critical temperature is %d\n", |
689 | hw_params(priv).ct_kill_threshold); | 708 | priv->hw_params.ct_kill_threshold); |
690 | } | 709 | } |
691 | } | 710 | } |
692 | 711 | ||
@@ -726,6 +745,29 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
726 | } | 745 | } |
727 | } | 746 | } |
728 | 747 | ||
748 | void iwl_send_bt_config(struct iwl_priv *priv) | ||
749 | { | ||
750 | struct iwl_bt_cmd bt_cmd = { | ||
751 | .lead_time = BT_LEAD_TIME_DEF, | ||
752 | .max_kill = BT_MAX_KILL_DEF, | ||
753 | .kill_ack_mask = 0, | ||
754 | .kill_cts_mask = 0, | ||
755 | }; | ||
756 | |||
757 | if (!iwlagn_mod_params.bt_coex_active) | ||
758 | bt_cmd.flags = BT_COEX_DISABLE; | ||
759 | else | ||
760 | bt_cmd.flags = BT_COEX_ENABLE; | ||
761 | |||
762 | priv->bt_enable_flag = bt_cmd.flags; | ||
763 | IWL_DEBUG_INFO(priv, "BT coex %s\n", | ||
764 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | ||
765 | |||
766 | if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | ||
767 | CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) | ||
768 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | ||
769 | } | ||
770 | |||
729 | /** | 771 | /** |
730 | * iwl_alive_start - called after REPLY_ALIVE notification received | 772 | * iwl_alive_start - called after REPLY_ALIVE notification received |
731 | * from protocol/runtime uCode (initialization uCode's | 773 | * from protocol/runtime uCode (initialization uCode's |
@@ -741,9 +783,6 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
741 | /* After the ALIVE response, we can send host commands to the uCode */ | 783 | /* After the ALIVE response, we can send host commands to the uCode */ |
742 | set_bit(STATUS_ALIVE, &priv->status); | 784 | set_bit(STATUS_ALIVE, &priv->status); |
743 | 785 | ||
744 | /* Enable watchdog to monitor the driver tx queues */ | ||
745 | iwl_setup_watchdog(priv); | ||
746 | |||
747 | if (iwl_is_rfkill(priv)) | 786 | if (iwl_is_rfkill(priv)) |
748 | return -ERFKILL; | 787 | return -ERFKILL; |
749 | 788 | ||
@@ -793,10 +832,8 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
793 | 832 | ||
794 | ieee80211_wake_queues(priv->hw); | 833 | ieee80211_wake_queues(priv->hw); |
795 | 834 | ||
796 | priv->active_rate = IWL_RATES_MASK; | ||
797 | |||
798 | /* Configure Tx antenna selection based on H/W config */ | 835 | /* Configure Tx antenna selection based on H/W config */ |
799 | iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant); | 836 | iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant); |
800 | 837 | ||
801 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | 838 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { |
802 | struct iwl_rxon_cmd *active_rxon = | 839 | struct iwl_rxon_cmd *active_rxon = |
@@ -887,10 +924,6 @@ void iwl_down(struct iwl_priv *priv) | |||
887 | exit_pending = | 924 | exit_pending = |
888 | test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); | 925 | test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); |
889 | 926 | ||
890 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set | ||
891 | * to prevent rearm timer */ | ||
892 | del_timer_sync(&priv->watchdog); | ||
893 | |||
894 | iwl_clear_ucode_stations(priv, NULL); | 927 | iwl_clear_ucode_stations(priv, NULL); |
895 | iwl_dealloc_bcast_stations(priv); | 928 | iwl_dealloc_bcast_stations(priv); |
896 | iwl_clear_driver_stations(priv); | 929 | iwl_clear_driver_stations(priv); |
@@ -1067,7 +1100,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work) | |||
1067 | * | 1100 | * |
1068 | *****************************************************************************/ | 1101 | *****************************************************************************/ |
1069 | 1102 | ||
1070 | static void iwl_setup_deferred_work(struct iwl_priv *priv) | 1103 | void iwl_setup_deferred_work(struct iwl_priv *priv) |
1071 | { | 1104 | { |
1072 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); | 1105 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); |
1073 | 1106 | ||
@@ -1092,10 +1125,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
1092 | init_timer(&priv->ucode_trace); | 1125 | init_timer(&priv->ucode_trace); |
1093 | priv->ucode_trace.data = (unsigned long)priv; | 1126 | priv->ucode_trace.data = (unsigned long)priv; |
1094 | priv->ucode_trace.function = iwl_bg_ucode_trace; | 1127 | priv->ucode_trace.function = iwl_bg_ucode_trace; |
1095 | |||
1096 | init_timer(&priv->watchdog); | ||
1097 | priv->watchdog.data = (unsigned long)priv; | ||
1098 | priv->watchdog.function = iwl_bg_watchdog; | ||
1099 | } | 1128 | } |
1100 | 1129 | ||
1101 | void iwl_cancel_deferred_work(struct iwl_priv *priv) | 1130 | void iwl_cancel_deferred_work(struct iwl_priv *priv) |
@@ -1143,8 +1172,8 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | |||
1143 | enum ieee80211_band band) | 1172 | enum ieee80211_band band) |
1144 | { | 1173 | { |
1145 | u16 max_bit_rate = 0; | 1174 | u16 max_bit_rate = 0; |
1146 | u8 rx_chains_num = hw_params(priv).rx_chains_num; | 1175 | u8 rx_chains_num = priv->hw_params.rx_chains_num; |
1147 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | 1176 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1148 | 1177 | ||
1149 | ht_info->cap = 0; | 1178 | ht_info->cap = 0; |
1150 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 1179 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
@@ -1156,7 +1185,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | |||
1156 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 1185 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
1157 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 1186 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
1158 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 1187 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
1159 | if (hw_params(priv).ht40_channel & BIT(band)) { | 1188 | if (priv->hw_params.ht40_channel & BIT(band)) { |
1160 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 1189 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
1161 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | 1190 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; |
1162 | ht_info->mcs.rx_mask[4] = 0x01; | 1191 | ht_info->mcs.rx_mask[4] = 0x01; |
@@ -1228,7 +1257,7 @@ static int iwl_init_geos(struct iwl_priv *priv) | |||
1228 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | 1257 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; |
1229 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | 1258 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; |
1230 | 1259 | ||
1231 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | 1260 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |
1232 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | 1261 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, |
1233 | IEEE80211_BAND_5GHZ); | 1262 | IEEE80211_BAND_5GHZ); |
1234 | 1263 | ||
@@ -1238,7 +1267,7 @@ static int iwl_init_geos(struct iwl_priv *priv) | |||
1238 | sband->bitrates = rates; | 1267 | sband->bitrates = rates; |
1239 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | 1268 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; |
1240 | 1269 | ||
1241 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | 1270 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |
1242 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | 1271 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, |
1243 | IEEE80211_BAND_2GHZ); | 1272 | IEEE80211_BAND_2GHZ); |
1244 | 1273 | ||
@@ -1293,11 +1322,11 @@ static int iwl_init_geos(struct iwl_priv *priv) | |||
1293 | priv->tx_power_next = max_tx_power; | 1322 | priv->tx_power_next = max_tx_power; |
1294 | 1323 | ||
1295 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | 1324 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |
1296 | hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) { | 1325 | priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) { |
1297 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | 1326 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " |
1298 | "Please send your %s to maintainer.\n", | 1327 | "Please send your %s to maintainer.\n", |
1299 | trans(priv)->hw_id_str); | 1328 | trans(priv)->hw_id_str); |
1300 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | 1329 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; |
1301 | } | 1330 | } |
1302 | 1331 | ||
1303 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | 1332 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", |
@@ -1319,7 +1348,7 @@ static void iwl_free_geos(struct iwl_priv *priv) | |||
1319 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | 1348 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); |
1320 | } | 1349 | } |
1321 | 1350 | ||
1322 | static int iwl_init_drv(struct iwl_priv *priv) | 1351 | int iwl_init_drv(struct iwl_priv *priv) |
1323 | { | 1352 | { |
1324 | int ret; | 1353 | int ret; |
1325 | 1354 | ||
@@ -1343,12 +1372,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
1343 | 1372 | ||
1344 | priv->ucode_owner = IWL_OWNERSHIP_DRIVER; | 1373 | priv->ucode_owner = IWL_OWNERSHIP_DRIVER; |
1345 | 1374 | ||
1346 | /* initialize force reset */ | ||
1347 | priv->force_reset[IWL_RF_RESET].reset_duration = | ||
1348 | IWL_DELAY_NEXT_FORCE_RF_RESET; | ||
1349 | priv->force_reset[IWL_FW_RESET].reset_duration = | ||
1350 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | ||
1351 | |||
1352 | priv->rx_statistics_jiffies = jiffies; | 1375 | priv->rx_statistics_jiffies = jiffies; |
1353 | 1376 | ||
1354 | /* Choose which receivers/antennas to use */ | 1377 | /* Choose which receivers/antennas to use */ |
@@ -1388,7 +1411,7 @@ err: | |||
1388 | return ret; | 1411 | return ret; |
1389 | } | 1412 | } |
1390 | 1413 | ||
1391 | static void iwl_uninit_drv(struct iwl_priv *priv) | 1414 | void iwl_uninit_drv(struct iwl_priv *priv) |
1392 | { | 1415 | { |
1393 | iwl_free_geos(priv); | 1416 | iwl_free_geos(priv); |
1394 | iwl_free_channel_map(priv); | 1417 | iwl_free_channel_map(priv); |
@@ -1401,35 +1424,22 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
1401 | #endif | 1424 | #endif |
1402 | } | 1425 | } |
1403 | 1426 | ||
1404 | /* Size of one Rx buffer in host DRAM */ | 1427 | void iwl_set_hw_params(struct iwl_priv *priv) |
1405 | #define IWL_RX_BUF_SIZE_4K (4 * 1024) | ||
1406 | #define IWL_RX_BUF_SIZE_8K (8 * 1024) | ||
1407 | |||
1408 | static void iwl_set_hw_params(struct iwl_priv *priv) | ||
1409 | { | 1428 | { |
1410 | if (cfg(priv)->ht_params) | 1429 | if (cfg(priv)->ht_params) |
1411 | hw_params(priv).use_rts_for_aggregation = | 1430 | priv->hw_params.use_rts_for_aggregation = |
1412 | cfg(priv)->ht_params->use_rts_for_aggregation; | 1431 | cfg(priv)->ht_params->use_rts_for_aggregation; |
1413 | 1432 | ||
1414 | if (iwlagn_mod_params.amsdu_size_8K) | ||
1415 | hw_params(priv).rx_page_order = | ||
1416 | get_order(IWL_RX_BUF_SIZE_8K); | ||
1417 | else | ||
1418 | hw_params(priv).rx_page_order = | ||
1419 | get_order(IWL_RX_BUF_SIZE_4K); | ||
1420 | |||
1421 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | 1433 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) |
1422 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE; | 1434 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_11N_ENABLE; |
1423 | |||
1424 | hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout; | ||
1425 | 1435 | ||
1426 | /* Device-specific setup */ | 1436 | /* Device-specific setup */ |
1427 | cfg(priv)->lib->set_hw_params(priv); | 1437 | priv->lib->set_hw_params(priv); |
1428 | } | 1438 | } |
1429 | 1439 | ||
1430 | 1440 | ||
1431 | 1441 | ||
1432 | static void iwl_debug_config(struct iwl_priv *priv) | 1442 | void iwl_debug_config(struct iwl_priv *priv) |
1433 | { | 1443 | { |
1434 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUG " | 1444 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUG " |
1435 | #ifdef CONFIG_IWLWIFI_DEBUG | 1445 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1501,6 +1511,42 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1501 | priv->shrd = trans->shrd; | 1511 | priv->shrd = trans->shrd; |
1502 | priv->fw = fw; | 1512 | priv->fw = fw; |
1503 | 1513 | ||
1514 | switch (cfg(priv)->device_family) { | ||
1515 | case IWL_DEVICE_FAMILY_1000: | ||
1516 | case IWL_DEVICE_FAMILY_100: | ||
1517 | priv->lib = &iwl1000_lib; | ||
1518 | break; | ||
1519 | case IWL_DEVICE_FAMILY_2000: | ||
1520 | case IWL_DEVICE_FAMILY_105: | ||
1521 | priv->lib = &iwl2000_lib; | ||
1522 | break; | ||
1523 | case IWL_DEVICE_FAMILY_2030: | ||
1524 | case IWL_DEVICE_FAMILY_135: | ||
1525 | priv->lib = &iwl2030_lib; | ||
1526 | break; | ||
1527 | case IWL_DEVICE_FAMILY_5000: | ||
1528 | priv->lib = &iwl5000_lib; | ||
1529 | break; | ||
1530 | case IWL_DEVICE_FAMILY_5150: | ||
1531 | priv->lib = &iwl5150_lib; | ||
1532 | break; | ||
1533 | case IWL_DEVICE_FAMILY_6000: | ||
1534 | case IWL_DEVICE_FAMILY_6005: | ||
1535 | case IWL_DEVICE_FAMILY_6000i: | ||
1536 | case IWL_DEVICE_FAMILY_6050: | ||
1537 | case IWL_DEVICE_FAMILY_6150: | ||
1538 | priv->lib = &iwl6000_lib; | ||
1539 | break; | ||
1540 | case IWL_DEVICE_FAMILY_6030: | ||
1541 | priv->lib = &iwl6030_lib; | ||
1542 | break; | ||
1543 | default: | ||
1544 | break; | ||
1545 | } | ||
1546 | |||
1547 | if (WARN_ON(!priv->lib)) | ||
1548 | goto out_free_traffic_mem; | ||
1549 | |||
1504 | /* | 1550 | /* |
1505 | * Populate the state variables that the transport layer needs | 1551 | * Populate the state variables that the transport layer needs |
1506 | * to know about. | 1552 | * to know about. |
@@ -1508,11 +1554,18 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1508 | trans_cfg.op_mode = op_mode; | 1554 | trans_cfg.op_mode = op_mode; |
1509 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; | 1555 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; |
1510 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | 1556 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); |
1557 | trans_cfg.rx_buf_size_8k = iwlagn_mod_params.amsdu_size_8K; | ||
1558 | if (!iwlagn_mod_params.wd_disable) | ||
1559 | trans_cfg.queue_watchdog_timeout = | ||
1560 | cfg(priv)->base_params->wd_timeout; | ||
1561 | else | ||
1562 | trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED; | ||
1563 | trans_cfg.command_names = iwl_dvm_cmd_strings; | ||
1511 | 1564 | ||
1512 | ucode_flags = fw->ucode_capa.flags; | 1565 | ucode_flags = fw->ucode_capa.flags; |
1513 | 1566 | ||
1514 | #ifndef CONFIG_IWLWIFI_P2P | 1567 | #ifndef CONFIG_IWLWIFI_P2P |
1515 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | 1568 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; |
1516 | #endif | 1569 | #endif |
1517 | 1570 | ||
1518 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { | 1571 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { |
@@ -1574,11 +1627,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1574 | if (iwl_trans_start_hw(trans(priv))) | 1627 | if (iwl_trans_start_hw(trans(priv))) |
1575 | goto out_free_traffic_mem; | 1628 | goto out_free_traffic_mem; |
1576 | 1629 | ||
1577 | /***************** | ||
1578 | * 3. Read EEPROM | ||
1579 | *****************/ | ||
1580 | /* Read the EEPROM */ | 1630 | /* Read the EEPROM */ |
1581 | if (iwl_eeprom_init(trans(priv), trans(priv)->hw_rev)) { | 1631 | if (iwl_eeprom_init(priv, trans(priv)->hw_rev)) { |
1582 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1632 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1583 | goto out_free_traffic_mem; | 1633 | goto out_free_traffic_mem; |
1584 | } | 1634 | } |
@@ -1592,11 +1642,11 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1592 | goto out_free_eeprom; | 1642 | goto out_free_eeprom; |
1593 | 1643 | ||
1594 | /* extract MAC Address */ | 1644 | /* extract MAC Address */ |
1595 | iwl_eeprom_get_mac(priv->shrd, priv->addresses[0].addr); | 1645 | iwl_eeprom_get_mac(priv, priv->addresses[0].addr); |
1596 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 1646 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); |
1597 | priv->hw->wiphy->addresses = priv->addresses; | 1647 | priv->hw->wiphy->addresses = priv->addresses; |
1598 | priv->hw->wiphy->n_addresses = 1; | 1648 | priv->hw->wiphy->n_addresses = 1; |
1599 | num_mac = iwl_eeprom_query16(priv->shrd, EEPROM_NUM_MAC_ADDRESS); | 1649 | num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); |
1600 | if (num_mac > 1) { | 1650 | if (num_mac > 1) { |
1601 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 1651 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, |
1602 | ETH_ALEN); | 1652 | ETH_ALEN); |
@@ -1609,7 +1659,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1609 | ************************/ | 1659 | ************************/ |
1610 | iwl_set_hw_params(priv); | 1660 | iwl_set_hw_params(priv); |
1611 | 1661 | ||
1612 | if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) { | 1662 | if (!(priv->hw_params.sku & EEPROM_SKU_CAP_IPAN_ENABLE)) { |
1613 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); | 1663 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); |
1614 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | 1664 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; |
1615 | /* | 1665 | /* |
@@ -1694,7 +1744,7 @@ out_destroy_workqueue: | |||
1694 | priv->workqueue = NULL; | 1744 | priv->workqueue = NULL; |
1695 | iwl_uninit_drv(priv); | 1745 | iwl_uninit_drv(priv); |
1696 | out_free_eeprom: | 1746 | out_free_eeprom: |
1697 | iwl_eeprom_free(priv->shrd); | 1747 | iwl_eeprom_free(priv); |
1698 | out_free_traffic_mem: | 1748 | out_free_traffic_mem: |
1699 | iwl_free_traffic_mem(priv); | 1749 | iwl_free_traffic_mem(priv); |
1700 | ieee80211_free_hw(priv->hw); | 1750 | ieee80211_free_hw(priv->hw); |
@@ -1703,7 +1753,7 @@ out: | |||
1703 | return op_mode; | 1753 | return op_mode; |
1704 | } | 1754 | } |
1705 | 1755 | ||
1706 | static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | 1756 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) |
1707 | { | 1757 | { |
1708 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 1758 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
1709 | 1759 | ||
@@ -1720,7 +1770,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1720 | priv->ucode_loaded = false; | 1770 | priv->ucode_loaded = false; |
1721 | iwl_trans_stop_device(trans(priv)); | 1771 | iwl_trans_stop_device(trans(priv)); |
1722 | 1772 | ||
1723 | iwl_eeprom_free(priv->shrd); | 1773 | iwl_eeprom_free(priv); |
1724 | 1774 | ||
1725 | /*netif_stop_queue(dev); */ | 1775 | /*netif_stop_queue(dev); */ |
1726 | flush_workqueue(priv->workqueue); | 1776 | flush_workqueue(priv->workqueue); |
@@ -1838,7 +1888,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1838 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | 1888 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { |
1839 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | 1889 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); |
1840 | IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", | 1890 | IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", |
1841 | priv->shrd->status, table.valid); | 1891 | priv->status, table.valid); |
1842 | } | 1892 | } |
1843 | 1893 | ||
1844 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | 1894 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, |
@@ -2112,7 +2162,63 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2112 | return pos; | 2162 | return pos; |
2113 | } | 2163 | } |
2114 | 2164 | ||
2115 | static void iwl_nic_error(struct iwl_op_mode *op_mode) | 2165 | static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) |
2166 | { | ||
2167 | unsigned int reload_msec; | ||
2168 | unsigned long reload_jiffies; | ||
2169 | |||
2170 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2171 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) | ||
2172 | iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); | ||
2173 | #endif | ||
2174 | |||
2175 | /* uCode is no longer loaded. */ | ||
2176 | priv->ucode_loaded = false; | ||
2177 | |||
2178 | /* Set the FW error flag -- cleared on iwl_down */ | ||
2179 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
2180 | |||
2181 | iwl_abort_notification_waits(&priv->notif_wait); | ||
2182 | |||
2183 | /* Keep the restart process from trying to send host | ||
2184 | * commands by clearing the ready bit */ | ||
2185 | clear_bit(STATUS_READY, &priv->status); | ||
2186 | |||
2187 | wake_up(&trans(priv)->wait_command_queue); | ||
2188 | |||
2189 | if (!ondemand) { | ||
2190 | /* | ||
2191 | * If firmware keep reloading, then it indicate something | ||
2192 | * serious wrong and firmware having problem to recover | ||
2193 | * from it. Instead of keep trying which will fill the syslog | ||
2194 | * and hang the system, let's just stop it | ||
2195 | */ | ||
2196 | reload_jiffies = jiffies; | ||
2197 | reload_msec = jiffies_to_msecs((long) reload_jiffies - | ||
2198 | (long) priv->reload_jiffies); | ||
2199 | priv->reload_jiffies = reload_jiffies; | ||
2200 | if (reload_msec <= IWL_MIN_RELOAD_DURATION) { | ||
2201 | priv->reload_count++; | ||
2202 | if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { | ||
2203 | IWL_ERR(priv, "BUG_ON, Stop restarting\n"); | ||
2204 | return; | ||
2205 | } | ||
2206 | } else | ||
2207 | priv->reload_count = 0; | ||
2208 | } | ||
2209 | |||
2210 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
2211 | if (iwlagn_mod_params.restart_fw) { | ||
2212 | IWL_DEBUG_FW_ERRORS(priv, | ||
2213 | "Restarting adapter due to uCode error.\n"); | ||
2214 | queue_work(priv->workqueue, &priv->restart); | ||
2215 | } else | ||
2216 | IWL_DEBUG_FW_ERRORS(priv, | ||
2217 | "Detected FW error, but not restarting\n"); | ||
2218 | } | ||
2219 | } | ||
2220 | |||
2221 | void iwl_nic_error(struct iwl_op_mode *op_mode) | ||
2116 | { | 2222 | { |
2117 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2223 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2118 | 2224 | ||
@@ -2125,7 +2231,7 @@ static void iwl_nic_error(struct iwl_op_mode *op_mode) | |||
2125 | iwlagn_fw_error(priv, false); | 2231 | iwlagn_fw_error(priv, false); |
2126 | } | 2232 | } |
2127 | 2233 | ||
2128 | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | 2234 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) |
2129 | { | 2235 | { |
2130 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2236 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2131 | 2237 | ||
@@ -2135,14 +2241,22 @@ static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | |||
2135 | } | 2241 | } |
2136 | } | 2242 | } |
2137 | 2243 | ||
2138 | static void iwl_nic_config(struct iwl_op_mode *op_mode) | 2244 | void iwl_nic_config(struct iwl_op_mode *op_mode) |
2139 | { | 2245 | { |
2140 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2246 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2141 | 2247 | ||
2142 | cfg(priv)->lib->nic_config(priv); | 2248 | priv->lib->nic_config(priv); |
2143 | } | 2249 | } |
2144 | 2250 | ||
2145 | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2251 | static void iwl_wimax_active(struct iwl_op_mode *op_mode) |
2252 | { | ||
2253 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2254 | |||
2255 | clear_bit(STATUS_READY, &priv->status); | ||
2256 | IWL_ERR(priv, "RF is used by WiMAX\n"); | ||
2257 | } | ||
2258 | |||
2259 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | ||
2146 | { | 2260 | { |
2147 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2261 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2148 | int ac = priv->queue_to_ac[queue]; | 2262 | int ac = priv->queue_to_ac[queue]; |
@@ -2161,7 +2275,7 @@ static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | |||
2161 | ieee80211_stop_queue(priv->hw, ac); | 2275 | ieee80211_stop_queue(priv->hw, ac); |
2162 | } | 2276 | } |
2163 | 2277 | ||
2164 | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | 2278 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) |
2165 | { | 2279 | { |
2166 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2280 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2167 | int ac = priv->queue_to_ac[queue]; | 2281 | int ac = priv->queue_to_ac[queue]; |
@@ -2201,6 +2315,27 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) | |||
2201 | priv->passive_no_rx = false; | 2315 | priv->passive_no_rx = false; |
2202 | } | 2316 | } |
2203 | 2317 | ||
2318 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||
2319 | { | ||
2320 | struct ieee80211_tx_info *info; | ||
2321 | |||
2322 | info = IEEE80211_SKB_CB(skb); | ||
2323 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | ||
2324 | dev_kfree_skb_any(skb); | ||
2325 | } | ||
2326 | |||
2327 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | ||
2328 | { | ||
2329 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2330 | |||
2331 | if (state) | ||
2332 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2333 | else | ||
2334 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2335 | |||
2336 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | ||
2337 | } | ||
2338 | |||
2204 | const struct iwl_op_mode_ops iwl_dvm_ops = { | 2339 | const struct iwl_op_mode_ops iwl_dvm_ops = { |
2205 | .start = iwl_op_mode_dvm_start, | 2340 | .start = iwl_op_mode_dvm_start, |
2206 | .stop = iwl_op_mode_dvm_stop, | 2341 | .stop = iwl_op_mode_dvm_stop, |
@@ -2212,6 +2347,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { | |||
2212 | .nic_error = iwl_nic_error, | 2347 | .nic_error = iwl_nic_error, |
2213 | .cmd_queue_full = iwl_cmd_queue_full, | 2348 | .cmd_queue_full = iwl_cmd_queue_full, |
2214 | .nic_config = iwl_nic_config, | 2349 | .nic_config = iwl_nic_config, |
2350 | .wimax_active = iwl_wimax_active, | ||
2215 | }; | 2351 | }; |
2216 | 2352 | ||
2217 | /***************************************************************************** | 2353 | /***************************************************************************** |
@@ -2280,12 +2416,6 @@ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | |||
2280 | module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); | 2416 | module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); |
2281 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | 2417 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); |
2282 | 2418 | ||
2283 | module_param_named(ucode_alternative, | ||
2284 | iwlagn_mod_params.wanted_ucode_alternative, | ||
2285 | int, S_IRUGO); | ||
2286 | MODULE_PARM_DESC(ucode_alternative, | ||
2287 | "specify ucode alternative to use from ucode file"); | ||
2288 | |||
2289 | module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling, | 2419 | module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling, |
2290 | int, S_IRUGO); | 2420 | int, S_IRUGO); |
2291 | MODULE_PARM_DESC(antenna_coupling, | 2421 | MODULE_PARM_DESC(antenna_coupling, |
@@ -2299,9 +2429,6 @@ MODULE_PARM_DESC(bt_ch_inhibition, | |||
2299 | module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); | 2429 | module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); |
2300 | MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); | 2430 | MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); |
2301 | 2431 | ||
2302 | module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); | ||
2303 | MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); | ||
2304 | |||
2305 | module_param_named(wd_disable, iwlagn_mod_params.wd_disable, int, S_IRUGO); | 2432 | module_param_named(wd_disable, iwlagn_mod_params.wd_disable, int, S_IRUGO); |
2306 | MODULE_PARM_DESC(wd_disable, | 2433 | MODULE_PARM_DESC(wd_disable, |
2307 | "Disable stuck queue watchdog timer 0=system default, " | 2434 | "Disable stuck queue watchdog timer 0=system default, " |
@@ -2345,13 +2472,3 @@ module_param_named(auto_agg, iwlagn_mod_params.auto_agg, | |||
2345 | bool, S_IRUGO); | 2472 | bool, S_IRUGO); |
2346 | MODULE_PARM_DESC(auto_agg, | 2473 | MODULE_PARM_DESC(auto_agg, |
2347 | "enable agg w/o check traffic load (default: enable)"); | 2474 | "enable agg w/o check traffic load (default: enable)"); |
2348 | |||
2349 | /* | ||
2350 | * For now, keep using power level 1 instead of automatically | ||
2351 | * adjusting ... | ||
2352 | */ | ||
2353 | module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust, | ||
2354 | bool, S_IRUGO); | ||
2355 | MODULE_PARM_DESC(no_sleep_autoadjust, | ||
2356 | "don't automatically adjust sleep level " | ||
2357 | "according to maximum network latency (default: true)"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 51001622430b..20100c72ec6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -71,6 +71,34 @@ | |||
71 | /* AUX (TX during scan dwell) queue */ | 71 | /* AUX (TX during scan dwell) queue */ |
72 | #define IWL_AUX_QUEUE 10 | 72 | #define IWL_AUX_QUEUE 10 |
73 | 73 | ||
74 | /* device operations */ | ||
75 | extern struct iwl_lib_ops iwl1000_lib; | ||
76 | extern struct iwl_lib_ops iwl2000_lib; | ||
77 | extern struct iwl_lib_ops iwl2030_lib; | ||
78 | extern struct iwl_lib_ops iwl5000_lib; | ||
79 | extern struct iwl_lib_ops iwl5150_lib; | ||
80 | extern struct iwl_lib_ops iwl6000_lib; | ||
81 | extern struct iwl_lib_ops iwl6030_lib; | ||
82 | |||
83 | |||
84 | |||
85 | /***************************************************** | ||
86 | * DRIVER STATUS FUNCTIONS | ||
87 | ******************************************************/ | ||
88 | #define STATUS_RF_KILL_HW 0 | ||
89 | #define STATUS_CT_KILL 1 | ||
90 | #define STATUS_ALIVE 2 | ||
91 | #define STATUS_READY 3 | ||
92 | #define STATUS_GEO_CONFIGURED 4 | ||
93 | #define STATUS_EXIT_PENDING 5 | ||
94 | #define STATUS_STATISTICS 6 | ||
95 | #define STATUS_SCANNING 7 | ||
96 | #define STATUS_SCAN_ABORTING 8 | ||
97 | #define STATUS_SCAN_HW 9 | ||
98 | #define STATUS_FW_ERROR 10 | ||
99 | #define STATUS_CHANNEL_SWITCH_PENDING 11 | ||
100 | #define STATUS_SCAN_COMPLETE 12 | ||
101 | #define STATUS_POWER_PMI 13 | ||
74 | 102 | ||
75 | struct iwl_ucode_capabilities; | 103 | struct iwl_ucode_capabilities; |
76 | 104 | ||
@@ -87,11 +115,9 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) | |||
87 | void iwl_down(struct iwl_priv *priv); | 115 | void iwl_down(struct iwl_priv *priv); |
88 | void iwl_cancel_deferred_work(struct iwl_priv *priv); | 116 | void iwl_cancel_deferred_work(struct iwl_priv *priv); |
89 | void iwlagn_prepare_restart(struct iwl_priv *priv); | 117 | void iwlagn_prepare_restart(struct iwl_priv *priv); |
90 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
91 | int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode, | 118 | int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode, |
92 | struct iwl_rx_cmd_buffer *rxb, | 119 | struct iwl_rx_cmd_buffer *rxb, |
93 | struct iwl_device_cmd *cmd); | 120 | struct iwl_device_cmd *cmd); |
94 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); | ||
95 | 121 | ||
96 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | 122 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); |
97 | 123 | ||
@@ -109,6 +135,8 @@ int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id, | |||
109 | u32 flags, u16 len, const void *data); | 135 | u32 flags, u16 len, const void *data); |
110 | 136 | ||
111 | /* RXON */ | 137 | /* RXON */ |
138 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||
139 | struct iwl_rxon_context *ctx); | ||
112 | int iwlagn_set_pan_params(struct iwl_priv *priv); | 140 | int iwlagn_set_pan_params(struct iwl_priv *priv); |
113 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 141 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
114 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 142 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
@@ -119,6 +147,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
119 | u32 changes); | 147 | u32 changes); |
120 | void iwlagn_config_ht40(struct ieee80211_conf *conf, | 148 | void iwlagn_config_ht40(struct ieee80211_conf *conf, |
121 | struct iwl_rxon_context *ctx); | 149 | struct iwl_rxon_context *ctx); |
150 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | ||
151 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | ||
152 | struct iwl_rxon_context *ctx); | ||
153 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
154 | struct iwl_rxon_context *ctx, | ||
155 | enum ieee80211_band band, | ||
156 | struct ieee80211_vif *vif); | ||
157 | void iwl_set_rate(struct iwl_priv *priv); | ||
122 | 158 | ||
123 | /* uCode */ | 159 | /* uCode */ |
124 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | 160 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); |
@@ -131,17 +167,25 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
131 | int iwl_calib_set(struct iwl_priv *priv, | 167 | int iwl_calib_set(struct iwl_priv *priv, |
132 | const struct iwl_calib_hdr *cmd, int len); | 168 | const struct iwl_calib_hdr *cmd, int len); |
133 | void iwl_calib_free_results(struct iwl_priv *priv); | 169 | void iwl_calib_free_results(struct iwl_priv *priv); |
134 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); | ||
135 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | 170 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
136 | char **buf, bool display); | 171 | char **buf, bool display); |
172 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | ||
137 | 173 | ||
138 | /* lib */ | 174 | /* lib */ |
139 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 175 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
140 | void iwlagn_temperature(struct iwl_priv *priv); | 176 | void iwlagn_temperature(struct iwl_priv *priv); |
141 | u16 iwl_eeprom_calib_version(struct iwl_shared *shrd); | ||
142 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 177 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
143 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 178 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
144 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 179 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
180 | int iwl_send_statistics_request(struct iwl_priv *priv, | ||
181 | u8 flags, bool clear); | ||
182 | |||
183 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | ||
184 | struct iwl_priv *priv, enum ieee80211_band band) | ||
185 | { | ||
186 | return priv->hw->wiphy->bands[band]; | ||
187 | } | ||
188 | |||
145 | #ifdef CONFIG_PM_SLEEP | 189 | #ifdef CONFIG_PM_SLEEP |
146 | int iwlagn_send_patterns(struct iwl_priv *priv, | 190 | int iwlagn_send_patterns(struct iwl_priv *priv, |
147 | struct cfg80211_wowlan *wowlan); | 191 | struct cfg80211_wowlan *wowlan); |
@@ -151,6 +195,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan); | |||
151 | /* rx */ | 195 | /* rx */ |
152 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | 196 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); |
153 | void iwl_setup_rx_handlers(struct iwl_priv *priv); | 197 | void iwl_setup_rx_handlers(struct iwl_priv *priv); |
198 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | ||
154 | 199 | ||
155 | 200 | ||
156 | /* tx */ | 201 | /* tx */ |
@@ -195,6 +240,31 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); | |||
195 | /* scan */ | 240 | /* scan */ |
196 | void iwlagn_post_scan(struct iwl_priv *priv); | 241 | void iwlagn_post_scan(struct iwl_priv *priv); |
197 | void iwlagn_disable_roc(struct iwl_priv *priv); | 242 | void iwlagn_disable_roc(struct iwl_priv *priv); |
243 | int iwl_force_rf_reset(struct iwl_priv *priv, bool external); | ||
244 | void iwl_init_scan_params(struct iwl_priv *priv); | ||
245 | int iwl_scan_cancel(struct iwl_priv *priv); | ||
246 | void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | ||
247 | void iwl_force_scan_end(struct iwl_priv *priv); | ||
248 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
249 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | ||
250 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | ||
251 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); | ||
252 | int __must_check iwl_scan_initiate(struct iwl_priv *priv, | ||
253 | struct ieee80211_vif *vif, | ||
254 | enum iwl_scan_type scan_type, | ||
255 | enum ieee80211_band band); | ||
256 | |||
257 | /* For faster active scanning, scan will move to the next channel if fewer than | ||
258 | * PLCP_QUIET_THRESH packets are heard on this channel within | ||
259 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell | ||
260 | * time if it's a quiet channel (nothing responded to our probe, and there's | ||
261 | * no other traffic). | ||
262 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ | ||
263 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ | ||
264 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ | ||
265 | |||
266 | #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) | ||
267 | |||
198 | 268 | ||
199 | /* bt coex */ | 269 | /* bt coex */ |
200 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); | 270 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); |
@@ -207,6 +277,12 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); | |||
207 | void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv); | 277 | void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv); |
208 | void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena); | 278 | void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena); |
209 | 279 | ||
280 | static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) | ||
281 | { | ||
282 | return cfg(priv)->bt_params && | ||
283 | cfg(priv)->bt_params->advanced_bt_coexist; | ||
284 | } | ||
285 | |||
210 | #ifdef CONFIG_IWLWIFI_DEBUG | 286 | #ifdef CONFIG_IWLWIFI_DEBUG |
211 | const char *iwl_get_tx_fail_reason(u32 status); | 287 | const char *iwl_get_tx_fail_reason(u32 status); |
212 | const char *iwl_get_agg_tx_fail_reason(u16 status); | 288 | const char *iwl_get_agg_tx_fail_reason(u16 status); |
@@ -245,8 +321,6 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id, | |||
245 | u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 321 | u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
246 | const u8 *addr, bool is_ap, struct ieee80211_sta *sta); | 322 | const u8 *addr, bool is_ap, struct ieee80211_sta *sta); |
247 | 323 | ||
248 | void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
249 | u8 sta_id, struct iwl_link_quality_cmd *link_cmd); | ||
250 | int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 324 | int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
251 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); | 325 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
252 | int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | 326 | int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, |
@@ -254,6 +328,9 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
254 | int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 328 | int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
255 | struct ieee80211_sta *sta); | 329 | struct ieee80211_sta *sta); |
256 | 330 | ||
331 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||
332 | struct iwl_rxon_context *ctx, | ||
333 | struct ieee80211_sta_ht_cap *ht_cap); | ||
257 | 334 | ||
258 | static inline int iwl_sta_id(struct ieee80211_sta *sta) | 335 | static inline int iwl_sta_id(struct ieee80211_sta *sta) |
259 | { | 336 | { |
@@ -311,9 +388,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
311 | return cpu_to_le32(flags|(u32)rate); | 388 | return cpu_to_le32(flags|(u32)rate); |
312 | } | 389 | } |
313 | 390 | ||
314 | /* eeprom */ | ||
315 | void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac); | ||
316 | |||
317 | extern int iwl_alive_start(struct iwl_priv *priv); | 391 | extern int iwl_alive_start(struct iwl_priv *priv); |
318 | /* svtool */ | 392 | /* svtool */ |
319 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | 393 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
@@ -421,4 +495,95 @@ do { \ | |||
421 | } while (0) | 495 | } while (0) |
422 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 496 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
423 | 497 | ||
498 | extern const char *iwl_dvm_cmd_strings[REPLY_MAX]; | ||
499 | |||
500 | static inline const char *iwl_dvm_get_cmd_string(u8 cmd) | ||
501 | { | ||
502 | const char *s = iwl_dvm_cmd_strings[cmd]; | ||
503 | if (s) | ||
504 | return s; | ||
505 | return "UNKNOWN"; | ||
506 | } | ||
507 | |||
508 | /* API method exported for mvm hybrid state */ | ||
509 | void iwl_setup_deferred_work(struct iwl_priv *priv); | ||
510 | int iwl_send_wimax_coex(struct iwl_priv *priv); | ||
511 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | ||
512 | void iwl_debug_config(struct iwl_priv *priv); | ||
513 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | ||
514 | void iwl_set_hw_params(struct iwl_priv *priv); | ||
515 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); | ||
516 | int iwl_init_drv(struct iwl_priv *priv); | ||
517 | void iwl_uninit_drv(struct iwl_priv *priv); | ||
518 | void iwl_send_bt_config(struct iwl_priv *priv); | ||
519 | void iwl_rf_kill_ct_config(struct iwl_priv *priv); | ||
520 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
521 | void iwl_teardown_interface(struct iwl_priv *priv, | ||
522 | struct ieee80211_vif *vif, | ||
523 | bool mode_change); | ||
524 | int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
525 | void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
526 | void iwlagn_check_needed_chains(struct iwl_priv *priv, | ||
527 | struct iwl_rxon_context *ctx, | ||
528 | struct ieee80211_bss_conf *bss_conf); | ||
529 | void iwlagn_chain_noise_reset(struct iwl_priv *priv); | ||
530 | int iwlagn_update_beacon(struct iwl_priv *priv, | ||
531 | struct ieee80211_vif *vif); | ||
532 | void iwl_tt_handler(struct iwl_priv *priv); | ||
533 | void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode); | ||
534 | void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
535 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); | ||
536 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); | ||
537 | void iwl_nic_error(struct iwl_op_mode *op_mode); | ||
538 | void iwl_cmd_queue_full(struct iwl_op_mode *op_mode); | ||
539 | void iwl_nic_config(struct iwl_op_mode *op_mode); | ||
540 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||
541 | struct ieee80211_sta *sta, bool set); | ||
542 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||
543 | enum ieee80211_rssi_event rssi_event); | ||
544 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw); | ||
545 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw); | ||
546 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); | ||
547 | void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue); | ||
548 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
549 | struct ieee80211_channel_switch *ch_switch); | ||
550 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | ||
551 | struct ieee80211_vif *vif, | ||
552 | struct ieee80211_sta *sta, | ||
553 | enum ieee80211_sta_state old_state, | ||
554 | enum ieee80211_sta_state new_state); | ||
555 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||
556 | struct ieee80211_vif *vif, | ||
557 | enum ieee80211_ampdu_mlme_action action, | ||
558 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
559 | u8 buf_size); | ||
560 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | ||
561 | struct ieee80211_vif *vif, | ||
562 | struct cfg80211_scan_request *req); | ||
563 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | ||
564 | struct ieee80211_vif *vif, | ||
565 | enum sta_notify_cmd cmd, | ||
566 | struct ieee80211_sta *sta); | ||
567 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
568 | unsigned int changed_flags, | ||
569 | unsigned int *total_flags, | ||
570 | u64 multicast); | ||
571 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | ||
572 | struct ieee80211_vif *vif, u16 queue, | ||
573 | const struct ieee80211_tx_queue_params *params); | ||
574 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||
575 | struct ieee80211_vif *vif, | ||
576 | struct cfg80211_gtk_rekey_data *data); | ||
577 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||
578 | struct ieee80211_vif *vif, | ||
579 | struct ieee80211_key_conf *keyconf, | ||
580 | struct ieee80211_sta *sta, | ||
581 | u32 iv32, u16 *phase1key); | ||
582 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
583 | struct ieee80211_vif *vif, | ||
584 | struct ieee80211_sta *sta, | ||
585 | struct ieee80211_key_conf *key); | ||
586 | void iwlagn_mac_stop(struct ieee80211_hw *hw); | ||
587 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
588 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | ||
424 | #endif /* __iwl_agn_h__ */ | 589 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9ed73e5154be..296347a8290f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1918,7 +1918,7 @@ struct iwl_basic_bt_cmd { | |||
1918 | __le16 valid; | 1918 | __le16 valid; |
1919 | }; | 1919 | }; |
1920 | 1920 | ||
1921 | struct iwl6000_bt_cmd { | 1921 | struct iwl_bt_cmd_v1 { |
1922 | struct iwl_basic_bt_cmd basic; | 1922 | struct iwl_basic_bt_cmd basic; |
1923 | u8 prio_boost; | 1923 | u8 prio_boost; |
1924 | /* | 1924 | /* |
@@ -1929,7 +1929,7 @@ struct iwl6000_bt_cmd { | |||
1929 | __le16 rx_prio_boost; /* SW boost of WiFi rx priority */ | 1929 | __le16 rx_prio_boost; /* SW boost of WiFi rx priority */ |
1930 | }; | 1930 | }; |
1931 | 1931 | ||
1932 | struct iwl2000_bt_cmd { | 1932 | struct iwl_bt_cmd_v2 { |
1933 | struct iwl_basic_bt_cmd basic; | 1933 | struct iwl_basic_bt_cmd basic; |
1934 | __le32 prio_boost; | 1934 | __le32 prio_boost; |
1935 | /* | 1935 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h new file mode 100644 index 000000000000..47bfd5e59575 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -0,0 +1,227 @@ | |||
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) 2007 - 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_CONFIG_H__ | ||
64 | #define __IWL_CONFIG_H__ | ||
65 | |||
66 | #include <linux/types.h> | ||
67 | #include <net/mac80211.h> | ||
68 | |||
69 | |||
70 | enum iwl_device_family { | ||
71 | IWL_DEVICE_FAMILY_UNDEFINED, | ||
72 | IWL_DEVICE_FAMILY_1000, | ||
73 | IWL_DEVICE_FAMILY_100, | ||
74 | IWL_DEVICE_FAMILY_2000, | ||
75 | IWL_DEVICE_FAMILY_2030, | ||
76 | IWL_DEVICE_FAMILY_105, | ||
77 | IWL_DEVICE_FAMILY_135, | ||
78 | IWL_DEVICE_FAMILY_5000, | ||
79 | IWL_DEVICE_FAMILY_5150, | ||
80 | IWL_DEVICE_FAMILY_6000, | ||
81 | IWL_DEVICE_FAMILY_6000i, | ||
82 | IWL_DEVICE_FAMILY_6005, | ||
83 | IWL_DEVICE_FAMILY_6030, | ||
84 | IWL_DEVICE_FAMILY_6050, | ||
85 | IWL_DEVICE_FAMILY_6150, | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * LED mode | ||
90 | * IWL_LED_DEFAULT: use device default | ||
91 | * IWL_LED_RF_STATE: turn LED on/off based on RF state | ||
92 | * LED ON = RF ON | ||
93 | * LED OFF = RF OFF | ||
94 | * IWL_LED_BLINK: adjust led blink rate based on blink table | ||
95 | * IWL_LED_DISABLE: led disabled | ||
96 | */ | ||
97 | enum iwl_led_mode { | ||
98 | IWL_LED_DEFAULT, | ||
99 | IWL_LED_RF_STATE, | ||
100 | IWL_LED_BLINK, | ||
101 | IWL_LED_DISABLE, | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * @max_ll_items: max number of OTP blocks | ||
106 | * @shadow_ram_support: shadow support for OTP memory | ||
107 | * @led_compensation: compensate on the led on/off time per HW according | ||
108 | * to the deviation to achieve the desired led frequency. | ||
109 | * The detail algorithm is described in iwl-led.c | ||
110 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | ||
111 | * @adv_thermal_throttle: support advance thermal throttle | ||
112 | * @support_ct_kill_exit: support ct kill exit condition | ||
113 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
114 | * radio tuning when there is a high receiving plcp error rate | ||
115 | * @chain_noise_scale: default chain noise scale used for gain computation | ||
116 | * @wd_timeout: TX queues watchdog timeout | ||
117 | * @max_event_log_size: size of event log buffer size for ucode event logging | ||
118 | * @shadow_reg_enable: HW shadhow register bit | ||
119 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up | ||
120 | * @no_idle_support: do not support idle mode | ||
121 | */ | ||
122 | struct iwl_base_params { | ||
123 | int eeprom_size; | ||
124 | int num_of_queues; /* def: HW dependent */ | ||
125 | /* for iwl_apm_init() */ | ||
126 | u32 pll_cfg_val; | ||
127 | |||
128 | const u16 max_ll_items; | ||
129 | const bool shadow_ram_support; | ||
130 | u16 led_compensation; | ||
131 | bool adv_thermal_throttle; | ||
132 | bool support_ct_kill_exit; | ||
133 | u8 plcp_delta_threshold; | ||
134 | s32 chain_noise_scale; | ||
135 | unsigned int wd_timeout; | ||
136 | u32 max_event_log_size; | ||
137 | const bool shadow_reg_enable; | ||
138 | const bool hd_v2; | ||
139 | const bool no_idle_support; | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * @advanced_bt_coexist: support advanced bt coexist | ||
144 | * @bt_init_traffic_load: specify initial bt traffic load | ||
145 | * @bt_prio_boost: default bt priority boost value | ||
146 | * @agg_time_limit: maximum number of uSec in aggregation | ||
147 | * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode | ||
148 | */ | ||
149 | struct iwl_bt_params { | ||
150 | bool advanced_bt_coexist; | ||
151 | u8 bt_init_traffic_load; | ||
152 | u8 bt_prio_boost; | ||
153 | u16 agg_time_limit; | ||
154 | bool bt_sco_disable; | ||
155 | bool bt_session_2; | ||
156 | }; | ||
157 | /* | ||
158 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
159 | */ | ||
160 | struct iwl_ht_params { | ||
161 | const bool ht_greenfield_support; /* if used set to true */ | ||
162 | bool use_rts_for_aggregation; | ||
163 | enum ieee80211_smps_mode smps_mode; | ||
164 | }; | ||
165 | |||
166 | /** | ||
167 | * struct iwl_cfg | ||
168 | * @name: Offical name of the device | ||
169 | * @fw_name_pre: Firmware filename prefix. The api version and extension | ||
170 | * (.ucode) will be added to filename before loading from disk. The | ||
171 | * filename is constructed as fw_name_pre<api>.ucode. | ||
172 | * @ucode_api_max: Highest version of uCode API supported by driver. | ||
173 | * @ucode_api_ok: oldest version of the uCode API that is OK to load | ||
174 | * without a warning, for use in transitions | ||
175 | * @ucode_api_min: Lowest version of uCode API supported by driver. | ||
176 | * @max_inst_size: The maximal length of the fw inst section | ||
177 | * @max_data_size: The maximal length of the fw data section | ||
178 | * @valid_tx_ant: valid transmit antenna | ||
179 | * @valid_rx_ant: valid receive antenna | ||
180 | * @eeprom_ver: EEPROM version | ||
181 | * @eeprom_calib_ver: EEPROM calibration version | ||
182 | * @lib: pointer to the lib ops | ||
183 | * @base_params: pointer to basic parameters | ||
184 | * @ht_params: point to ht patameters | ||
185 | * @bt_params: pointer to bt parameters | ||
186 | * @need_temp_offset_calib: need to perform temperature offset calibration | ||
187 | * @no_xtal_calib: some devices do not need crystal calibration data, | ||
188 | * don't send it to those | ||
189 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) | ||
190 | * @adv_pm: advance power management | ||
191 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | ||
192 | * @internal_wimax_coex: internal wifi/wimax combo device | ||
193 | * @temp_offset_v2: support v2 of temperature offset calibration | ||
194 | * | ||
195 | * We enable the driver to be backward compatible wrt. hardware features. | ||
196 | * API differences in uCode shouldn't be handled here but through TLVs | ||
197 | * and/or the uCode API version instead. | ||
198 | */ | ||
199 | struct iwl_cfg { | ||
200 | /* params specific to an individual device within a device family */ | ||
201 | const char *name; | ||
202 | const char *fw_name_pre; | ||
203 | const unsigned int ucode_api_max; | ||
204 | const unsigned int ucode_api_ok; | ||
205 | const unsigned int ucode_api_min; | ||
206 | const enum iwl_device_family device_family; | ||
207 | const u32 max_data_size; | ||
208 | const u32 max_inst_size; | ||
209 | u8 valid_tx_ant; | ||
210 | u8 valid_rx_ant; | ||
211 | u16 eeprom_ver; | ||
212 | u16 eeprom_calib_ver; | ||
213 | /* params not likely to change within a device family */ | ||
214 | const struct iwl_base_params *base_params; | ||
215 | /* params likely to change within a device family */ | ||
216 | const struct iwl_ht_params *ht_params; | ||
217 | const struct iwl_bt_params *bt_params; | ||
218 | const bool need_temp_offset_calib; /* if used set to true */ | ||
219 | const bool no_xtal_calib; | ||
220 | enum iwl_led_mode led_mode; | ||
221 | const bool adv_pm; | ||
222 | const bool rx_with_siso_diversity; | ||
223 | const bool internal_wimax_coex; | ||
224 | const bool temp_offset_v2; | ||
225 | }; | ||
226 | |||
227 | #endif /* __IWL_CONFIG_H__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 88ea31d9eb75..d7a8cde249ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -41,477 +41,6 @@ | |||
41 | #include "iwl-agn.h" | 41 | #include "iwl-agn.h" |
42 | #include "iwl-trans.h" | 42 | #include "iwl-trans.h" |
43 | 43 | ||
44 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
45 | |||
46 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | ||
47 | enum ieee80211_band band, | ||
48 | u16 channel, u8 extension_chan_offset) | ||
49 | { | ||
50 | const struct iwl_channel_info *ch_info; | ||
51 | |||
52 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
53 | if (!is_channel_valid(ch_info)) | ||
54 | return false; | ||
55 | |||
56 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
57 | return !(ch_info->ht40_extension_channel & | ||
58 | IEEE80211_CHAN_NO_HT40PLUS); | ||
59 | else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
60 | return !(ch_info->ht40_extension_channel & | ||
61 | IEEE80211_CHAN_NO_HT40MINUS); | ||
62 | |||
63 | return false; | ||
64 | } | ||
65 | |||
66 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||
67 | struct iwl_rxon_context *ctx, | ||
68 | struct ieee80211_sta_ht_cap *ht_cap) | ||
69 | { | ||
70 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | ||
71 | return false; | ||
72 | |||
73 | /* | ||
74 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | ||
75 | * the bit will not set if it is pure 40MHz case | ||
76 | */ | ||
77 | if (ht_cap && !ht_cap->ht_supported) | ||
78 | return false; | ||
79 | |||
80 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
81 | if (priv->disable_ht40) | ||
82 | return false; | ||
83 | #endif | ||
84 | |||
85 | return iwl_is_channel_extension(priv, priv->band, | ||
86 | le16_to_cpu(ctx->staging.channel), | ||
87 | ctx->ht.extension_chan_offset); | ||
88 | } | ||
89 | |||
90 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, | ||
91 | struct iwl_ht_config *ht_conf, | ||
92 | struct iwl_rxon_context *ctx) | ||
93 | { | ||
94 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
95 | |||
96 | if (!ctx->ht.enabled) { | ||
97 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
98 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
99 | RXON_FLG_HT40_PROT_MSK | | ||
100 | RXON_FLG_HT_PROT_MSK); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | /* FIXME: if the definition of ht.protection changed, the "translation" | ||
105 | * will be needed for rxon->flags | ||
106 | */ | ||
107 | rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); | ||
108 | |||
109 | /* Set up channel bandwidth: | ||
110 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | ||
111 | /* clear the HT channel mode before set the mode */ | ||
112 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
113 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
114 | if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) { | ||
115 | /* pure ht40 */ | ||
116 | if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | ||
117 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | ||
118 | /* Note: control channel is opposite of extension channel */ | ||
119 | switch (ctx->ht.extension_chan_offset) { | ||
120 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
121 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
122 | break; | ||
123 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
124 | rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
125 | break; | ||
126 | } | ||
127 | } else { | ||
128 | /* Note: control channel is opposite of extension channel */ | ||
129 | switch (ctx->ht.extension_chan_offset) { | ||
130 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
131 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
132 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
133 | break; | ||
134 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
135 | rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
136 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
137 | break; | ||
138 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
139 | default: | ||
140 | /* channel location only valid if in Mixed mode */ | ||
141 | IWL_ERR(priv, "invalid extension channel offset\n"); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | } else { | ||
146 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; | ||
147 | } | ||
148 | |||
149 | iwlagn_set_rxon_chain(priv, ctx); | ||
150 | |||
151 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " | ||
152 | "extension channel offset 0x%x\n", | ||
153 | le32_to_cpu(rxon->flags), ctx->ht.protection, | ||
154 | ctx->ht.extension_chan_offset); | ||
155 | } | ||
156 | |||
157 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | ||
158 | { | ||
159 | struct iwl_rxon_context *ctx; | ||
160 | |||
161 | for_each_context(priv, ctx) | ||
162 | _iwl_set_rxon_ht(priv, ht_conf, ctx); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON | ||
167 | * @ch: requested channel as a pointer to struct ieee80211_channel | ||
168 | |||
169 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | ||
170 | * in the staging RXON flag structure based on the ch->band | ||
171 | */ | ||
172 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | ||
173 | struct iwl_rxon_context *ctx) | ||
174 | { | ||
175 | enum ieee80211_band band = ch->band; | ||
176 | u16 channel = ch->hw_value; | ||
177 | |||
178 | if ((le16_to_cpu(ctx->staging.channel) == channel) && | ||
179 | (priv->band == band)) | ||
180 | return; | ||
181 | |||
182 | ctx->staging.channel = cpu_to_le16(channel); | ||
183 | if (band == IEEE80211_BAND_5GHZ) | ||
184 | ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; | ||
185 | else | ||
186 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
187 | |||
188 | priv->band = band; | ||
189 | |||
190 | IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band); | ||
191 | |||
192 | } | ||
193 | |||
194 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
195 | struct iwl_rxon_context *ctx, | ||
196 | enum ieee80211_band band, | ||
197 | struct ieee80211_vif *vif) | ||
198 | { | ||
199 | if (band == IEEE80211_BAND_5GHZ) { | ||
200 | ctx->staging.flags &= | ||
201 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | ||
202 | | RXON_FLG_CCK_MSK); | ||
203 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
204 | } else { | ||
205 | /* Copied from iwl_post_associate() */ | ||
206 | if (vif && vif->bss_conf.use_short_slot) | ||
207 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
208 | else | ||
209 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
210 | |||
211 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
212 | ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; | ||
213 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * initialize rxon structure with default values from eeprom | ||
219 | */ | ||
220 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||
221 | struct iwl_rxon_context *ctx) | ||
222 | { | ||
223 | const struct iwl_channel_info *ch_info; | ||
224 | |||
225 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | ||
226 | |||
227 | if (!ctx->vif) { | ||
228 | ctx->staging.dev_type = ctx->unused_devtype; | ||
229 | } else switch (ctx->vif->type) { | ||
230 | case NL80211_IFTYPE_AP: | ||
231 | ctx->staging.dev_type = ctx->ap_devtype; | ||
232 | break; | ||
233 | |||
234 | case NL80211_IFTYPE_STATION: | ||
235 | ctx->staging.dev_type = ctx->station_devtype; | ||
236 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | ||
237 | break; | ||
238 | |||
239 | case NL80211_IFTYPE_ADHOC: | ||
240 | ctx->staging.dev_type = ctx->ibss_devtype; | ||
241 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | ||
242 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | | ||
243 | RXON_FILTER_ACCEPT_GRP_MSK; | ||
244 | break; | ||
245 | |||
246 | default: | ||
247 | IWL_ERR(priv, "Unsupported interface type %d\n", | ||
248 | ctx->vif->type); | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | #if 0 | ||
253 | /* TODO: Figure out when short_preamble would be set and cache from | ||
254 | * that */ | ||
255 | if (!hw_to_local(priv->hw)->short_preamble) | ||
256 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
257 | else | ||
258 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
259 | #endif | ||
260 | |||
261 | ch_info = iwl_get_channel_info(priv, priv->band, | ||
262 | le16_to_cpu(ctx->active.channel)); | ||
263 | |||
264 | if (!ch_info) | ||
265 | ch_info = &priv->channel_info[0]; | ||
266 | |||
267 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | ||
268 | priv->band = ch_info->band; | ||
269 | |||
270 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | ||
271 | |||
272 | ctx->staging.ofdm_basic_rates = | ||
273 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
274 | ctx->staging.cck_basic_rates = | ||
275 | (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
276 | |||
277 | /* clear both MIX and PURE40 mode flag */ | ||
278 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | ||
279 | RXON_FLG_CHANNEL_MODE_PURE_40); | ||
280 | if (ctx->vif) | ||
281 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); | ||
282 | |||
283 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; | ||
284 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | ||
285 | ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; | ||
286 | } | ||
287 | |||
288 | void iwl_set_rate(struct iwl_priv *priv) | ||
289 | { | ||
290 | const struct ieee80211_supported_band *hw = NULL; | ||
291 | struct ieee80211_rate *rate; | ||
292 | struct iwl_rxon_context *ctx; | ||
293 | int i; | ||
294 | |||
295 | hw = iwl_get_hw_mode(priv, priv->band); | ||
296 | if (!hw) { | ||
297 | IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | priv->active_rate = 0; | ||
302 | |||
303 | for (i = 0; i < hw->n_bitrates; i++) { | ||
304 | rate = &(hw->bitrates[i]); | ||
305 | if (rate->hw_value < IWL_RATE_COUNT_LEGACY) | ||
306 | priv->active_rate |= (1 << rate->hw_value); | ||
307 | } | ||
308 | |||
309 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); | ||
310 | |||
311 | for_each_context(priv, ctx) { | ||
312 | ctx->staging.cck_basic_rates = | ||
313 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
314 | |||
315 | ctx->staging.ofdm_basic_rates = | ||
316 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | ||
321 | { | ||
322 | /* | ||
323 | * MULTI-FIXME | ||
324 | * See iwlagn_mac_channel_switch. | ||
325 | */ | ||
326 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
327 | |||
328 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
329 | return; | ||
330 | |||
331 | if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) | ||
332 | ieee80211_chswitch_done(ctx->vif, is_success); | ||
333 | } | ||
334 | |||
335 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
336 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | ||
337 | enum iwl_rxon_context_id ctxid) | ||
338 | { | ||
339 | struct iwl_rxon_context *ctx = &priv->contexts[ctxid]; | ||
340 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
341 | |||
342 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); | ||
343 | iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | ||
344 | IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); | ||
345 | IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); | ||
346 | IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", | ||
347 | le32_to_cpu(rxon->filter_flags)); | ||
348 | IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type); | ||
349 | IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n", | ||
350 | rxon->ofdm_basic_rates); | ||
351 | IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); | ||
352 | IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr); | ||
353 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | ||
354 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); | ||
355 | } | ||
356 | #endif | ||
357 | |||
358 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | ||
359 | { | ||
360 | unsigned int reload_msec; | ||
361 | unsigned long reload_jiffies; | ||
362 | |||
363 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
364 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) | ||
365 | iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); | ||
366 | #endif | ||
367 | |||
368 | /* uCode is no longer loaded. */ | ||
369 | priv->ucode_loaded = false; | ||
370 | |||
371 | /* Set the FW error flag -- cleared on iwl_down */ | ||
372 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
373 | |||
374 | /* Cancel currently queued command. */ | ||
375 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); | ||
376 | |||
377 | iwl_abort_notification_waits(&priv->notif_wait); | ||
378 | |||
379 | /* Keep the restart process from trying to send host | ||
380 | * commands by clearing the ready bit */ | ||
381 | clear_bit(STATUS_READY, &priv->status); | ||
382 | |||
383 | wake_up(&trans(priv)->wait_command_queue); | ||
384 | |||
385 | if (!ondemand) { | ||
386 | /* | ||
387 | * If firmware keep reloading, then it indicate something | ||
388 | * serious wrong and firmware having problem to recover | ||
389 | * from it. Instead of keep trying which will fill the syslog | ||
390 | * and hang the system, let's just stop it | ||
391 | */ | ||
392 | reload_jiffies = jiffies; | ||
393 | reload_msec = jiffies_to_msecs((long) reload_jiffies - | ||
394 | (long) priv->reload_jiffies); | ||
395 | priv->reload_jiffies = reload_jiffies; | ||
396 | if (reload_msec <= IWL_MIN_RELOAD_DURATION) { | ||
397 | priv->reload_count++; | ||
398 | if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { | ||
399 | IWL_ERR(priv, "BUG_ON, Stop restarting\n"); | ||
400 | return; | ||
401 | } | ||
402 | } else | ||
403 | priv->reload_count = 0; | ||
404 | } | ||
405 | |||
406 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
407 | if (iwlagn_mod_params.restart_fw) { | ||
408 | IWL_DEBUG_FW_ERRORS(priv, | ||
409 | "Restarting adapter due to uCode error.\n"); | ||
410 | queue_work(priv->workqueue, &priv->restart); | ||
411 | } else | ||
412 | IWL_DEBUG_FW_ERRORS(priv, | ||
413 | "Detected FW error, but not restarting\n"); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | ||
418 | { | ||
419 | int ret; | ||
420 | s8 prev_tx_power; | ||
421 | bool defer; | ||
422 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
423 | |||
424 | lockdep_assert_held(&priv->mutex); | ||
425 | |||
426 | if (priv->tx_power_user_lmt == tx_power && !force) | ||
427 | return 0; | ||
428 | |||
429 | if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { | ||
430 | IWL_WARN(priv, | ||
431 | "Requested user TXPOWER %d below lower limit %d.\n", | ||
432 | tx_power, | ||
433 | IWLAGN_TX_POWER_TARGET_POWER_MIN); | ||
434 | return -EINVAL; | ||
435 | } | ||
436 | |||
437 | if (tx_power > priv->tx_power_device_lmt) { | ||
438 | IWL_WARN(priv, | ||
439 | "Requested user TXPOWER %d above upper limit %d.\n", | ||
440 | tx_power, priv->tx_power_device_lmt); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | if (!iwl_is_ready_rf(priv)) | ||
445 | return -EIO; | ||
446 | |||
447 | /* scan complete and commit_rxon use tx_power_next value, | ||
448 | * it always need to be updated for newest request */ | ||
449 | priv->tx_power_next = tx_power; | ||
450 | |||
451 | /* do not set tx power when scanning or channel changing */ | ||
452 | defer = test_bit(STATUS_SCANNING, &priv->status) || | ||
453 | memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); | ||
454 | if (defer && !force) { | ||
455 | IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | prev_tx_power = priv->tx_power_user_lmt; | ||
460 | priv->tx_power_user_lmt = tx_power; | ||
461 | |||
462 | ret = iwlagn_send_tx_power(priv); | ||
463 | |||
464 | /* if fail to set tx_power, restore the orig. tx power */ | ||
465 | if (ret) { | ||
466 | priv->tx_power_user_lmt = prev_tx_power; | ||
467 | priv->tx_power_next = prev_tx_power; | ||
468 | } | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | void iwl_send_bt_config(struct iwl_priv *priv) | ||
473 | { | ||
474 | struct iwl_bt_cmd bt_cmd = { | ||
475 | .lead_time = BT_LEAD_TIME_DEF, | ||
476 | .max_kill = BT_MAX_KILL_DEF, | ||
477 | .kill_ack_mask = 0, | ||
478 | .kill_cts_mask = 0, | ||
479 | }; | ||
480 | |||
481 | if (!iwlagn_mod_params.bt_coex_active) | ||
482 | bt_cmd.flags = BT_COEX_DISABLE; | ||
483 | else | ||
484 | bt_cmd.flags = BT_COEX_ENABLE; | ||
485 | |||
486 | priv->bt_enable_flag = bt_cmd.flags; | ||
487 | IWL_DEBUG_INFO(priv, "BT coex %s\n", | ||
488 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | ||
489 | |||
490 | if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | ||
491 | CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) | ||
492 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | ||
493 | } | ||
494 | |||
495 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | ||
496 | { | ||
497 | struct iwl_statistics_cmd statistics_cmd = { | ||
498 | .configuration_flags = | ||
499 | clear ? IWL_STATS_CONF_CLEAR_STATS : 0, | ||
500 | }; | ||
501 | |||
502 | if (flags & CMD_ASYNC) | ||
503 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
504 | CMD_ASYNC, | ||
505 | sizeof(struct iwl_statistics_cmd), | ||
506 | &statistics_cmd); | ||
507 | else | ||
508 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
509 | CMD_SYNC, | ||
510 | sizeof(struct iwl_statistics_cmd), | ||
511 | &statistics_cmd); | ||
512 | } | ||
513 | |||
514 | |||
515 | 44 | ||
516 | 45 | ||
517 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 46 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -611,6 +140,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | |||
611 | 140 | ||
612 | const char *get_mgmt_string(int cmd) | 141 | const char *get_mgmt_string(int cmd) |
613 | { | 142 | { |
143 | #define IWL_CMD(x) case x: return #x | ||
614 | switch (cmd) { | 144 | switch (cmd) { |
615 | IWL_CMD(MANAGEMENT_ASSOC_REQ); | 145 | IWL_CMD(MANAGEMENT_ASSOC_REQ); |
616 | IWL_CMD(MANAGEMENT_ASSOC_RESP); | 146 | IWL_CMD(MANAGEMENT_ASSOC_RESP); |
@@ -628,10 +158,12 @@ const char *get_mgmt_string(int cmd) | |||
628 | return "UNKNOWN"; | 158 | return "UNKNOWN"; |
629 | 159 | ||
630 | } | 160 | } |
161 | #undef IWL_CMD | ||
631 | } | 162 | } |
632 | 163 | ||
633 | const char *get_ctrl_string(int cmd) | 164 | const char *get_ctrl_string(int cmd) |
634 | { | 165 | { |
166 | #define IWL_CMD(x) case x: return #x | ||
635 | switch (cmd) { | 167 | switch (cmd) { |
636 | IWL_CMD(CONTROL_BACK_REQ); | 168 | IWL_CMD(CONTROL_BACK_REQ); |
637 | IWL_CMD(CONTROL_BACK); | 169 | IWL_CMD(CONTROL_BACK); |
@@ -645,6 +177,7 @@ const char *get_ctrl_string(int cmd) | |||
645 | return "UNKNOWN"; | 177 | return "UNKNOWN"; |
646 | 178 | ||
647 | } | 179 | } |
180 | #undef IWL_CMD | ||
648 | } | 181 | } |
649 | 182 | ||
650 | void iwl_clear_traffic_stats(struct iwl_priv *priv) | 183 | void iwl_clear_traffic_stats(struct iwl_priv *priv) |
@@ -746,80 +279,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
746 | } | 279 | } |
747 | #endif | 280 | #endif |
748 | 281 | ||
749 | static void iwl_force_rf_reset(struct iwl_priv *priv) | ||
750 | { | ||
751 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
752 | return; | ||
753 | |||
754 | if (!iwl_is_any_associated(priv)) { | ||
755 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); | ||
756 | return; | ||
757 | } | ||
758 | /* | ||
759 | * There is no easy and better way to force reset the radio, | ||
760 | * the only known method is switching channel which will force to | ||
761 | * reset and tune the radio. | ||
762 | * Use internal short scan (single channel) operation to should | ||
763 | * achieve this objective. | ||
764 | * Driver should reset the radio when number of consecutive missed | ||
765 | * beacon, or any other uCode error condition detected. | ||
766 | */ | ||
767 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); | ||
768 | iwl_internal_short_hw_scan(priv); | ||
769 | } | ||
770 | |||
771 | |||
772 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) | ||
773 | { | ||
774 | struct iwl_force_reset *force_reset; | ||
775 | |||
776 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
777 | return -EINVAL; | ||
778 | |||
779 | if (mode >= IWL_MAX_FORCE_RESET) { | ||
780 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); | ||
781 | return -EINVAL; | ||
782 | } | ||
783 | force_reset = &priv->force_reset[mode]; | ||
784 | force_reset->reset_request_count++; | ||
785 | if (!external) { | ||
786 | if (force_reset->last_force_reset_jiffies && | ||
787 | time_after(force_reset->last_force_reset_jiffies + | ||
788 | force_reset->reset_duration, jiffies)) { | ||
789 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); | ||
790 | force_reset->reset_reject_count++; | ||
791 | return -EAGAIN; | ||
792 | } | ||
793 | } | ||
794 | force_reset->reset_success_count++; | ||
795 | force_reset->last_force_reset_jiffies = jiffies; | ||
796 | IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); | ||
797 | switch (mode) { | ||
798 | case IWL_RF_RESET: | ||
799 | iwl_force_rf_reset(priv); | ||
800 | break; | ||
801 | case IWL_FW_RESET: | ||
802 | /* | ||
803 | * if the request is from external(ex: debugfs), | ||
804 | * then always perform the request in regardless the module | ||
805 | * parameter setting | ||
806 | * if the request is from internal (uCode error or driver | ||
807 | * detect failure), then fw_restart module parameter | ||
808 | * need to be check before performing firmware reload | ||
809 | */ | ||
810 | if (!external && !iwlagn_mod_params.restart_fw) { | ||
811 | IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " | ||
812 | "module parameter setting\n"); | ||
813 | break; | ||
814 | } | ||
815 | IWL_ERR(priv, "On demand firmware reload\n"); | ||
816 | iwlagn_fw_error(priv, true); | ||
817 | break; | ||
818 | } | ||
819 | return 0; | ||
820 | } | ||
821 | |||
822 | |||
823 | int iwl_cmd_echo_test(struct iwl_priv *priv) | 282 | int iwl_cmd_echo_test(struct iwl_priv *priv) |
824 | { | 283 | { |
825 | int ret; | 284 | int ret; |
@@ -836,165 +295,3 @@ int iwl_cmd_echo_test(struct iwl_priv *priv) | |||
836 | IWL_DEBUG_INFO(priv, "echo testing pass\n"); | 295 | IWL_DEBUG_INFO(priv, "echo testing pass\n"); |
837 | return ret; | 296 | return ret; |
838 | } | 297 | } |
839 | |||
840 | static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq) | ||
841 | { | ||
842 | if (iwl_trans_check_stuck_queue(trans(priv), txq)) { | ||
843 | int ret; | ||
844 | ret = iwl_force_reset(priv, IWL_FW_RESET, false); | ||
845 | return (ret == -EAGAIN) ? 0 : 1; | ||
846 | } | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | /* | ||
851 | * Making watchdog tick be a quarter of timeout assure we will | ||
852 | * discover the queue hung between timeout and 1.25*timeout | ||
853 | */ | ||
854 | #define IWL_WD_TICK(timeout) ((timeout) / 4) | ||
855 | |||
856 | /* | ||
857 | * Watchdog timer callback, we check each tx queue for stuck, if if hung | ||
858 | * we reset the firmware. If everything is fine just rearm the timer. | ||
859 | */ | ||
860 | void iwl_bg_watchdog(unsigned long data) | ||
861 | { | ||
862 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
863 | int cnt; | ||
864 | unsigned long timeout; | ||
865 | |||
866 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
867 | return; | ||
868 | |||
869 | if (iwl_is_rfkill(priv)) | ||
870 | return; | ||
871 | |||
872 | timeout = hw_params(priv).wd_timeout; | ||
873 | if (timeout == 0) | ||
874 | return; | ||
875 | |||
876 | /* monitor and check for stuck queues */ | ||
877 | for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++) | ||
878 | if (iwl_check_stuck_queue(priv, cnt)) | ||
879 | return; | ||
880 | |||
881 | mod_timer(&priv->watchdog, jiffies + | ||
882 | msecs_to_jiffies(IWL_WD_TICK(timeout))); | ||
883 | } | ||
884 | |||
885 | void iwl_setup_watchdog(struct iwl_priv *priv) | ||
886 | { | ||
887 | unsigned int timeout = hw_params(priv).wd_timeout; | ||
888 | |||
889 | if (!iwlagn_mod_params.wd_disable) { | ||
890 | /* use system default */ | ||
891 | if (timeout && !cfg(priv)->base_params->wd_disable) | ||
892 | mod_timer(&priv->watchdog, | ||
893 | jiffies + | ||
894 | msecs_to_jiffies(IWL_WD_TICK(timeout))); | ||
895 | else | ||
896 | del_timer(&priv->watchdog); | ||
897 | } else { | ||
898 | /* module parameter overwrite default configuration */ | ||
899 | if (timeout && iwlagn_mod_params.wd_disable == 2) | ||
900 | mod_timer(&priv->watchdog, | ||
901 | jiffies + | ||
902 | msecs_to_jiffies(IWL_WD_TICK(timeout))); | ||
903 | else | ||
904 | del_timer(&priv->watchdog); | ||
905 | } | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | ||
910 | * @priv -- pointer to iwl_priv data structure | ||
911 | * @tsf_bits -- number of bits need to shift for masking) | ||
912 | */ | ||
913 | static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, | ||
914 | u16 tsf_bits) | ||
915 | { | ||
916 | return (1 << tsf_bits) - 1; | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time | ||
921 | * @priv -- pointer to iwl_priv data structure | ||
922 | * @tsf_bits -- number of bits need to shift for masking) | ||
923 | */ | ||
924 | static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, | ||
925 | u16 tsf_bits) | ||
926 | { | ||
927 | return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * extended beacon time format | ||
932 | * time in usec will be changed into a 32-bit value in extended:internal format | ||
933 | * the extended part is the beacon counts | ||
934 | * the internal part is the time in usec within one beacon interval | ||
935 | */ | ||
936 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) | ||
937 | { | ||
938 | u32 quot; | ||
939 | u32 rem; | ||
940 | u32 interval = beacon_interval * TIME_UNIT; | ||
941 | |||
942 | if (!interval || !usec) | ||
943 | return 0; | ||
944 | |||
945 | quot = (usec / interval) & | ||
946 | (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >> | ||
947 | IWLAGN_EXT_BEACON_TIME_POS); | ||
948 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | ||
949 | IWLAGN_EXT_BEACON_TIME_POS); | ||
950 | |||
951 | return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem; | ||
952 | } | ||
953 | |||
954 | /* base is usually what we get from ucode with each received frame, | ||
955 | * the same as HW timer counter counting down | ||
956 | */ | ||
957 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
958 | u32 addon, u32 beacon_interval) | ||
959 | { | ||
960 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | ||
961 | IWLAGN_EXT_BEACON_TIME_POS); | ||
962 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | ||
963 | IWLAGN_EXT_BEACON_TIME_POS); | ||
964 | u32 interval = beacon_interval * TIME_UNIT; | ||
965 | u32 res = (base & iwl_beacon_time_mask_high(priv, | ||
966 | IWLAGN_EXT_BEACON_TIME_POS)) + | ||
967 | (addon & iwl_beacon_time_mask_high(priv, | ||
968 | IWLAGN_EXT_BEACON_TIME_POS)); | ||
969 | |||
970 | if (base_low > addon_low) | ||
971 | res += base_low - addon_low; | ||
972 | else if (base_low < addon_low) { | ||
973 | res += interval + base_low - addon_low; | ||
974 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | ||
975 | } else | ||
976 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | ||
977 | |||
978 | return cpu_to_le32(res); | ||
979 | } | ||
980 | |||
981 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | ||
982 | { | ||
983 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
984 | |||
985 | if (state) | ||
986 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
987 | else | ||
988 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
989 | |||
990 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | ||
991 | } | ||
992 | |||
993 | void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||
994 | { | ||
995 | struct ieee80211_tx_info *info; | ||
996 | |||
997 | info = IEEE80211_SKB_CB(skb); | ||
998 | kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | ||
999 | dev_kfree_skb_any(skb); | ||
1000 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7aa3060fc6b5..199a0c03774c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -74,38 +74,10 @@ struct iwl_cmd; | |||
74 | 74 | ||
75 | #define TIME_UNIT 1024 | 75 | #define TIME_UNIT 1024 |
76 | 76 | ||
77 | struct iwl_lib_ops { | ||
78 | /* set hw dependent parameters */ | ||
79 | void (*set_hw_params)(struct iwl_priv *priv); | ||
80 | int (*set_channel_switch)(struct iwl_priv *priv, | ||
81 | struct ieee80211_channel_switch *ch_switch); | ||
82 | /* device specific configuration */ | ||
83 | void (*nic_config)(struct iwl_priv *priv); | ||
84 | |||
85 | /* eeprom operations (as defined in iwl-eeprom.h) */ | ||
86 | struct iwl_eeprom_ops eeprom_ops; | ||
87 | |||
88 | /* temperature */ | ||
89 | void (*temperature)(struct iwl_priv *priv); | ||
90 | }; | ||
91 | |||
92 | /*************************** | 77 | /*************************** |
93 | * L i b * | 78 | * L i b * |
94 | ***************************/ | 79 | ***************************/ |
95 | 80 | ||
96 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | ||
97 | struct iwl_rxon_context *ctx); | ||
98 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
99 | struct iwl_rxon_context *ctx, | ||
100 | enum ieee80211_band band, | ||
101 | struct ieee80211_vif *vif); | ||
102 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | ||
103 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||
104 | struct iwl_rxon_context *ctx, | ||
105 | struct ieee80211_sta_ht_cap *ht_cap); | ||
106 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||
107 | struct iwl_rxon_context *ctx); | ||
108 | void iwl_set_rate(struct iwl_priv *priv); | ||
109 | int iwl_cmd_echo_test(struct iwl_priv *priv); | 81 | int iwl_cmd_echo_test(struct iwl_priv *priv); |
110 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 82 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
111 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | 83 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); |
@@ -146,45 +118,9 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | |||
146 | } | 118 | } |
147 | #endif | 119 | #endif |
148 | 120 | ||
149 | /***************************************************** | ||
150 | * RX | ||
151 | ******************************************************/ | ||
152 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | ||
153 | |||
154 | void iwl_setup_watchdog(struct iwl_priv *priv); | ||
155 | /***************************************************** | ||
156 | * TX power | ||
157 | ****************************************************/ | ||
158 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); | ||
159 | |||
160 | /******************************************************************************* | 121 | /******************************************************************************* |
161 | * Scanning | 122 | * Scanning |
162 | ******************************************************************************/ | 123 | ******************************************************************************/ |
163 | void iwl_init_scan_params(struct iwl_priv *priv); | ||
164 | int iwl_scan_cancel(struct iwl_priv *priv); | ||
165 | void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | ||
166 | void iwl_force_scan_end(struct iwl_priv *priv); | ||
167 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
168 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); | ||
169 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | ||
170 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | ||
171 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); | ||
172 | int __must_check iwl_scan_initiate(struct iwl_priv *priv, | ||
173 | struct ieee80211_vif *vif, | ||
174 | enum iwl_scan_type scan_type, | ||
175 | enum ieee80211_band band); | ||
176 | |||
177 | /* For faster active scanning, scan will move to the next channel if fewer than | ||
178 | * PLCP_QUIET_THRESH packets are heard on this channel within | ||
179 | * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell | ||
180 | * time if it's a quiet channel (nothing responded to our probe, and there's | ||
181 | * no other traffic). | ||
182 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ | ||
183 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ | ||
184 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ | ||
185 | |||
186 | #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) | ||
187 | |||
188 | /* traffic log definitions */ | 124 | /* traffic log definitions */ |
189 | #define IWL_TRAFFIC_ENTRIES (256) | 125 | #define IWL_TRAFFIC_ENTRIES (256) |
190 | #define IWL_TRAFFIC_ENTRY_SIZE (64) | 126 | #define IWL_TRAFFIC_ENTRY_SIZE (64) |
@@ -192,28 +128,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | |||
192 | /***************************************************** | 128 | /***************************************************** |
193 | * S e n d i n g H o s t C o m m a n d s * | 129 | * S e n d i n g H o s t C o m m a n d s * |
194 | *****************************************************/ | 130 | *****************************************************/ |
195 | |||
196 | void iwl_bg_watchdog(unsigned long data); | ||
197 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); | ||
198 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
199 | u32 addon, u32 beacon_interval); | ||
200 | |||
201 | extern void iwl_send_bt_config(struct iwl_priv *priv); | ||
202 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | ||
203 | u8 flags, bool clear); | ||
204 | |||
205 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | ||
206 | struct iwl_priv *priv, enum ieee80211_band band) | ||
207 | { | ||
208 | return priv->hw->wiphy->bands[band]; | ||
209 | } | ||
210 | |||
211 | static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) | ||
212 | { | ||
213 | return cfg(priv)->bt_params && | ||
214 | cfg(priv)->bt_params->advanced_bt_coexist; | ||
215 | } | ||
216 | |||
217 | extern bool bt_siso_mode; | 131 | extern bool bt_siso_mode; |
218 | 132 | ||
219 | #endif /* __iwl_core_h__ */ | 133 | #endif /* __iwl_core_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 5f96ce105f08..59750543fce7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -430,6 +430,9 @@ | |||
430 | #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) | 430 | #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) |
431 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | 431 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) |
432 | 432 | ||
433 | /* Used to enable DBGM */ | ||
434 | #define HBUS_TARG_TEST_REG (HBUS_BASE+0x05c) | ||
435 | |||
433 | /* | 436 | /* |
434 | * Per-Tx-queue write pointer (index, really!) | 437 | * Per-Tx-queue write pointer (index, really!) |
435 | * Indicates index to next TFD that driver will fill (1 past latest filled). | 438 | * Indicates index to next TFD that driver will fill (1 past latest filled). |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d109d1bbb3a2..32834a797d11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -416,7 +416,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
416 | return -ENODATA; | 416 | return -ENODATA; |
417 | } | 417 | } |
418 | 418 | ||
419 | ptr = priv->shrd->eeprom; | 419 | ptr = priv->eeprom; |
420 | if (!ptr) { | 420 | if (!ptr) { |
421 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); | 421 | IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); |
422 | return -ENOMEM; | 422 | return -ENOMEM; |
@@ -428,10 +428,10 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
428 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 428 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
429 | return -ENOMEM; | 429 | return -ENOMEM; |
430 | } | 430 | } |
431 | eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION); | 431 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); |
432 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 432 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " |
433 | "version: 0x%x\n", | 433 | "version: 0x%x\n", |
434 | (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 434 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
435 | ? "OTP" : "EEPROM", eeprom_ver); | 435 | ? "OTP" : "EEPROM", eeprom_ver); |
436 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 436 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
437 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 437 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
@@ -526,8 +526,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
526 | int pos = 0; | 526 | int pos = 0; |
527 | const size_t bufsz = sizeof(buf); | 527 | const size_t bufsz = sizeof(buf); |
528 | 528 | ||
529 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", | ||
530 | test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); | ||
531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 529 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
532 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 530 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", | 531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", |
@@ -577,7 +575,7 @@ static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, | |||
577 | if (priv->rx_handlers_stats[cnt] > 0) | 575 | if (priv->rx_handlers_stats[cnt] > 0) |
578 | pos += scnprintf(buf + pos, bufsz - pos, | 576 | pos += scnprintf(buf + pos, bufsz - pos, |
579 | "\tRx handler[%36s]:\t\t %u\n", | 577 | "\tRx handler[%36s]:\t\t %u\n", |
580 | get_cmd_string(cnt), | 578 | iwl_dvm_get_cmd_string(cnt), |
581 | priv->rx_handlers_stats[cnt]); | 579 | priv->rx_handlers_stats[cnt]); |
582 | } | 580 | } |
583 | 581 | ||
@@ -1541,17 +1539,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1541 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | 1539 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { |
1542 | pos += scnprintf(buf + pos, bufsz - pos, | 1540 | pos += scnprintf(buf + pos, bufsz - pos, |
1543 | "tx power: (1/2 dB step)\n"); | 1541 | "tx power: (1/2 dB step)\n"); |
1544 | if ((hw_params(priv).valid_tx_ant & ANT_A) && | 1542 | if ((priv->hw_params.valid_tx_ant & ANT_A) && |
1545 | tx->tx_power.ant_a) | 1543 | tx->tx_power.ant_a) |
1546 | pos += scnprintf(buf + pos, bufsz - pos, | 1544 | pos += scnprintf(buf + pos, bufsz - pos, |
1547 | fmt_hex, "antenna A:", | 1545 | fmt_hex, "antenna A:", |
1548 | tx->tx_power.ant_a); | 1546 | tx->tx_power.ant_a); |
1549 | if ((hw_params(priv).valid_tx_ant & ANT_B) && | 1547 | if ((priv->hw_params.valid_tx_ant & ANT_B) && |
1550 | tx->tx_power.ant_b) | 1548 | tx->tx_power.ant_b) |
1551 | pos += scnprintf(buf + pos, bufsz - pos, | 1549 | pos += scnprintf(buf + pos, bufsz - pos, |
1552 | fmt_hex, "antenna B:", | 1550 | fmt_hex, "antenna B:", |
1553 | tx->tx_power.ant_b); | 1551 | tx->tx_power.ant_b); |
1554 | if ((hw_params(priv).valid_tx_ant & ANT_C) && | 1552 | if ((priv->hw_params.valid_tx_ant & ANT_C) && |
1555 | tx->tx_power.ant_c) | 1553 | tx->tx_power.ant_c) |
1556 | pos += scnprintf(buf + pos, bufsz - pos, | 1554 | pos += scnprintf(buf + pos, bufsz - pos, |
1557 | fmt_hex, "antenna C:", | 1555 | fmt_hex, "antenna C:", |
@@ -2267,59 +2265,39 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | |||
2267 | return count; | 2265 | return count; |
2268 | } | 2266 | } |
2269 | 2267 | ||
2270 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | 2268 | static ssize_t iwl_dbgfs_rf_reset_read(struct file *file, |
2271 | char __user *user_buf, | 2269 | char __user *user_buf, |
2272 | size_t count, loff_t *ppos) | 2270 | size_t count, loff_t *ppos) |
2273 | { | 2271 | { |
2274 | struct iwl_priv *priv = file->private_data; | 2272 | struct iwl_priv *priv = file->private_data; |
2275 | int i, pos = 0; | 2273 | int pos = 0; |
2276 | char buf[300]; | 2274 | char buf[300]; |
2277 | const size_t bufsz = sizeof(buf); | 2275 | const size_t bufsz = sizeof(buf); |
2278 | struct iwl_force_reset *force_reset; | 2276 | struct iwl_rf_reset *rf_reset = &priv->rf_reset; |
2277 | |||
2278 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2279 | "RF reset statistics\n"); | ||
2280 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2281 | "\tnumber of reset request: %d\n", | ||
2282 | rf_reset->reset_request_count); | ||
2283 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2284 | "\tnumber of reset request success: %d\n", | ||
2285 | rf_reset->reset_success_count); | ||
2286 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2287 | "\tnumber of reset request reject: %d\n", | ||
2288 | rf_reset->reset_reject_count); | ||
2279 | 2289 | ||
2280 | for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | ||
2281 | force_reset = &priv->force_reset[i]; | ||
2282 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2283 | "Force reset method %d\n", i); | ||
2284 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2285 | "\tnumber of reset request: %d\n", | ||
2286 | force_reset->reset_request_count); | ||
2287 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2288 | "\tnumber of reset request success: %d\n", | ||
2289 | force_reset->reset_success_count); | ||
2290 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2291 | "\tnumber of reset request reject: %d\n", | ||
2292 | force_reset->reset_reject_count); | ||
2293 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2294 | "\treset duration: %lu\n", | ||
2295 | force_reset->reset_duration); | ||
2296 | } | ||
2297 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 2290 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2298 | } | 2291 | } |
2299 | 2292 | ||
2300 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | 2293 | static ssize_t iwl_dbgfs_rf_reset_write(struct file *file, |
2301 | const char __user *user_buf, | 2294 | const char __user *user_buf, |
2302 | size_t count, loff_t *ppos) { | 2295 | size_t count, loff_t *ppos) { |
2303 | 2296 | ||
2304 | struct iwl_priv *priv = file->private_data; | 2297 | struct iwl_priv *priv = file->private_data; |
2305 | char buf[8]; | 2298 | int ret; |
2306 | int buf_size; | ||
2307 | int reset, ret; | ||
2308 | 2299 | ||
2309 | memset(buf, 0, sizeof(buf)); | 2300 | ret = iwl_force_rf_reset(priv, true); |
2310 | buf_size = min(count, sizeof(buf) - 1); | ||
2311 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2312 | return -EFAULT; | ||
2313 | if (sscanf(buf, "%d", &reset) != 1) | ||
2314 | return -EINVAL; | ||
2315 | switch (reset) { | ||
2316 | case IWL_RF_RESET: | ||
2317 | case IWL_FW_RESET: | ||
2318 | ret = iwl_force_reset(priv, reset, true); | ||
2319 | break; | ||
2320 | default: | ||
2321 | return -EINVAL; | ||
2322 | } | ||
2323 | return ret ? ret : count; | 2301 | return ret ? ret : count; |
2324 | } | 2302 | } |
2325 | 2303 | ||
@@ -2347,29 +2325,6 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, | |||
2347 | return count; | 2325 | return count; |
2348 | } | 2326 | } |
2349 | 2327 | ||
2350 | static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, | ||
2351 | const char __user *user_buf, | ||
2352 | size_t count, loff_t *ppos) | ||
2353 | { | ||
2354 | struct iwl_priv *priv = file->private_data; | ||
2355 | char buf[8]; | ||
2356 | int buf_size; | ||
2357 | int timeout; | ||
2358 | |||
2359 | memset(buf, 0, sizeof(buf)); | ||
2360 | buf_size = min(count, sizeof(buf) - 1); | ||
2361 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2362 | return -EFAULT; | ||
2363 | if (sscanf(buf, "%d", &timeout) != 1) | ||
2364 | return -EINVAL; | ||
2365 | if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) | ||
2366 | timeout = IWL_DEF_WD_TIMEOUT; | ||
2367 | |||
2368 | hw_params(priv).wd_timeout = timeout; | ||
2369 | iwl_setup_watchdog(priv); | ||
2370 | return count; | ||
2371 | } | ||
2372 | |||
2373 | static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, | 2328 | static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, |
2374 | char __user *user_buf, | 2329 | char __user *user_buf, |
2375 | size_t count, loff_t *ppos) { | 2330 | size_t count, loff_t *ppos) { |
@@ -2428,7 +2383,7 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, | |||
2428 | if (cfg(priv)->ht_params) | 2383 | if (cfg(priv)->ht_params) |
2429 | pos += scnprintf(buf + pos, bufsz - pos, | 2384 | pos += scnprintf(buf + pos, bufsz - pos, |
2430 | "use %s for aggregation\n", | 2385 | "use %s for aggregation\n", |
2431 | (hw_params(priv).use_rts_for_aggregation) ? | 2386 | (priv->hw_params.use_rts_for_aggregation) ? |
2432 | "rts/cts" : "cts-to-self"); | 2387 | "rts/cts" : "cts-to-self"); |
2433 | else | 2388 | else |
2434 | pos += scnprintf(buf + pos, bufsz - pos, "N/A"); | 2389 | pos += scnprintf(buf + pos, bufsz - pos, "N/A"); |
@@ -2455,9 +2410,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | |||
2455 | if (sscanf(buf, "%d", &rts) != 1) | 2410 | if (sscanf(buf, "%d", &rts) != 1) |
2456 | return -EINVAL; | 2411 | return -EINVAL; |
2457 | if (rts) | 2412 | if (rts) |
2458 | hw_params(priv).use_rts_for_aggregation = true; | 2413 | priv->hw_params.use_rts_for_aggregation = true; |
2459 | else | 2414 | else |
2460 | hw_params(priv).use_rts_for_aggregation = false; | 2415 | priv->hw_params.use_rts_for_aggregation = false; |
2461 | return count; | 2416 | return count; |
2462 | } | 2417 | } |
2463 | 2418 | ||
@@ -2516,6 +2471,34 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
2516 | return count; | 2471 | return count; |
2517 | } | 2472 | } |
2518 | 2473 | ||
2474 | static ssize_t iwl_dbgfs_calib_disabled_read(struct file *file, | ||
2475 | char __user *user_buf, | ||
2476 | size_t count, loff_t *ppos) | ||
2477 | { | ||
2478 | struct iwl_priv *priv = file->private_data; | ||
2479 | char buf[120]; | ||
2480 | int pos = 0; | ||
2481 | const size_t bufsz = sizeof(buf); | ||
2482 | |||
2483 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2484 | "Sensitivity calibrations %s\n", | ||
2485 | (priv->calib_disabled & | ||
2486 | IWL_SENSITIVITY_CALIB_DISABLED) ? | ||
2487 | "DISABLED" : "ENABLED"); | ||
2488 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2489 | "Chain noise calibrations %s\n", | ||
2490 | (priv->calib_disabled & | ||
2491 | IWL_CHAIN_NOISE_CALIB_DISABLED) ? | ||
2492 | "DISABLED" : "ENABLED"); | ||
2493 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2494 | "Tx power calibrations %s\n", | ||
2495 | (priv->calib_disabled & | ||
2496 | IWL_TX_POWER_CALIB_DISABLED) ? | ||
2497 | "DISABLED" : "ENABLED"); | ||
2498 | |||
2499 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2500 | } | ||
2501 | |||
2519 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2502 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
2520 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2503 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
2521 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2504 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -2530,17 +2513,17 @@ DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | |||
2530 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 2513 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); |
2531 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 2514 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); |
2532 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 2515 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); |
2533 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 2516 | DEBUGFS_READ_WRITE_FILE_OPS(rf_reset); |
2534 | DEBUGFS_READ_FILE_OPS(rxon_flags); | 2517 | DEBUGFS_READ_FILE_OPS(rxon_flags); |
2535 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | 2518 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); |
2536 | DEBUGFS_WRITE_FILE_OPS(txfifo_flush); | 2519 | DEBUGFS_WRITE_FILE_OPS(txfifo_flush); |
2537 | DEBUGFS_READ_FILE_OPS(ucode_bt_stats); | 2520 | DEBUGFS_READ_FILE_OPS(ucode_bt_stats); |
2538 | DEBUGFS_WRITE_FILE_OPS(wd_timeout); | ||
2539 | DEBUGFS_READ_FILE_OPS(bt_traffic); | 2521 | DEBUGFS_READ_FILE_OPS(bt_traffic); |
2540 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 2522 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); |
2541 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 2523 | DEBUGFS_READ_FILE_OPS(reply_tx_error); |
2542 | DEBUGFS_WRITE_FILE_OPS(echo_test); | 2524 | DEBUGFS_WRITE_FILE_OPS(echo_test); |
2543 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | 2525 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
2526 | DEBUGFS_READ_FILE_OPS(calib_disabled); | ||
2544 | 2527 | ||
2545 | /* | 2528 | /* |
2546 | * Create the debugfs files and directories | 2529 | * Create the debugfs files and directories |
@@ -2589,7 +2572,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2589 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); | 2572 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); |
2590 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 2573 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); |
2591 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 2574 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); |
2592 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | 2575 | DEBUGFS_ADD_FILE(rf_reset, dir_debug, S_IWUSR | S_IRUSR); |
2593 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 2576 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
2594 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 2577 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
2595 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 2578 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
@@ -2602,17 +2585,14 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2602 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); | 2585 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); |
2603 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 2586 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
2604 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 2587 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
2605 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | ||
2606 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); | 2588 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); |
2607 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); | 2589 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); |
2608 | 2590 | ||
2609 | if (iwl_advanced_bt_coexist(priv)) | 2591 | if (iwl_advanced_bt_coexist(priv)) |
2610 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 2592 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); |
2611 | 2593 | ||
2612 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 2594 | /* Calibrations disabled/enabled status*/ |
2613 | &priv->disable_sens_cal); | 2595 | DEBUGFS_ADD_FILE(calib_disabled, dir_rf, S_IRUSR); |
2614 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | ||
2615 | &priv->disable_chain_noise_cal); | ||
2616 | 2596 | ||
2617 | if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) | 2597 | if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) |
2618 | goto err; | 2598 | goto err; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 99be58940e27..c235a1ea71b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -51,8 +51,6 @@ | |||
51 | #include "iwl-op-mode.h" | 51 | #include "iwl-op-mode.h" |
52 | #include "iwl-notif-wait.h" | 52 | #include "iwl-notif-wait.h" |
53 | 53 | ||
54 | struct iwl_tx_queue; | ||
55 | |||
56 | /* CT-KILL constants */ | 54 | /* CT-KILL constants */ |
57 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 55 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
58 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ | 56 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ |
@@ -582,9 +580,9 @@ struct iwl_event_log { | |||
582 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0) | 580 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0) |
583 | 581 | ||
584 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | 582 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) |
585 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | ||
586 | 583 | ||
587 | /* TX queue watchdog timeouts in mSecs */ | 584 | /* TX queue watchdog timeouts in mSecs */ |
585 | #define IWL_WATCHHDOG_DISABLED (0) | ||
588 | #define IWL_DEF_WD_TIMEOUT (2000) | 586 | #define IWL_DEF_WD_TIMEOUT (2000) |
589 | #define IWL_LONG_WD_TIMEOUT (10000) | 587 | #define IWL_LONG_WD_TIMEOUT (10000) |
590 | #define IWL_MAX_WD_TIMEOUT (120000) | 588 | #define IWL_MAX_WD_TIMEOUT (120000) |
@@ -597,18 +595,11 @@ struct iwl_event_log { | |||
597 | #define IWL_MAX_CONTINUE_RELOAD_CNT 4 | 595 | #define IWL_MAX_CONTINUE_RELOAD_CNT 4 |
598 | 596 | ||
599 | 597 | ||
600 | enum iwl_reset { | 598 | struct iwl_rf_reset { |
601 | IWL_RF_RESET = 0, | ||
602 | IWL_FW_RESET, | ||
603 | IWL_MAX_FORCE_RESET, | ||
604 | }; | ||
605 | |||
606 | struct iwl_force_reset { | ||
607 | int reset_request_count; | 599 | int reset_request_count; |
608 | int reset_success_count; | 600 | int reset_success_count; |
609 | int reset_reject_count; | 601 | int reset_reject_count; |
610 | unsigned long reset_duration; | 602 | unsigned long last_reset_jiffies; |
611 | unsigned long last_force_reset_jiffies; | ||
612 | }; | 603 | }; |
613 | 604 | ||
614 | /* extend beacon time format bit shifting */ | 605 | /* extend beacon time format bit shifting */ |
@@ -680,6 +671,52 @@ enum iwl_scan_type { | |||
680 | IWL_SCAN_ROC, | 671 | IWL_SCAN_ROC, |
681 | }; | 672 | }; |
682 | 673 | ||
674 | /** | ||
675 | * struct iwl_hw_params | ||
676 | * | ||
677 | * Holds the module parameters | ||
678 | * | ||
679 | * @tx_chains_num: Number of TX chains | ||
680 | * @rx_chains_num: Number of RX chains | ||
681 | * @valid_tx_ant: usable antennas for TX | ||
682 | * @valid_rx_ant: usable antennas for RX | ||
683 | * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) | ||
684 | * @sku: sku read from EEPROM | ||
685 | * @ct_kill_threshold: temperature threshold - in hw dependent unit | ||
686 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | ||
687 | * relevant for 1000, 6000 and up | ||
688 | * @struct iwl_sensitivity_ranges: range of sensitivity values | ||
689 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
690 | */ | ||
691 | struct iwl_hw_params { | ||
692 | u8 tx_chains_num; | ||
693 | u8 rx_chains_num; | ||
694 | u8 valid_tx_ant; | ||
695 | u8 valid_rx_ant; | ||
696 | u8 ht40_channel; | ||
697 | bool use_rts_for_aggregation; | ||
698 | u16 sku; | ||
699 | u32 ct_kill_threshold; | ||
700 | u32 ct_kill_exit_threshold; | ||
701 | |||
702 | const struct iwl_sensitivity_ranges *sens; | ||
703 | }; | ||
704 | |||
705 | struct iwl_lib_ops { | ||
706 | /* set hw dependent parameters */ | ||
707 | void (*set_hw_params)(struct iwl_priv *priv); | ||
708 | int (*set_channel_switch)(struct iwl_priv *priv, | ||
709 | struct ieee80211_channel_switch *ch_switch); | ||
710 | /* device specific configuration */ | ||
711 | void (*nic_config)(struct iwl_priv *priv); | ||
712 | |||
713 | /* eeprom operations (as defined in iwl-eeprom.h) */ | ||
714 | struct iwl_eeprom_ops eeprom_ops; | ||
715 | |||
716 | /* temperature */ | ||
717 | void (*temperature)(struct iwl_priv *priv); | ||
718 | }; | ||
719 | |||
683 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | 720 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
684 | struct iwl_testmode_trace { | 721 | struct iwl_testmode_trace { |
685 | u32 buff_size; | 722 | u32 buff_size; |
@@ -704,6 +741,14 @@ struct iwl_wipan_noa_data { | |||
704 | u8 data[]; | 741 | u8 data[]; |
705 | }; | 742 | }; |
706 | 743 | ||
744 | /* Calibration disabling bit mask */ | ||
745 | #define IWL_SENSITIVITY_CALIB_DISABLED BIT(1) | ||
746 | #define IWL_CHAIN_NOISE_CALIB_DISABLED BIT(2) | ||
747 | #define IWL_TX_POWER_CALIB_DISABLED BIT(3) | ||
748 | |||
749 | #define IWL_CALIB_ENABLE_ALL 0 | ||
750 | #define IWL_CALIB_DISABLE_ALL 0xFFFFFFFF | ||
751 | |||
707 | #define IWL_OP_MODE_GET_DVM(_iwl_op_mode) \ | 752 | #define IWL_OP_MODE_GET_DVM(_iwl_op_mode) \ |
708 | ((struct iwl_priv *) ((_iwl_op_mode)->op_mode_specific)) | 753 | ((struct iwl_priv *) ((_iwl_op_mode)->op_mode_specific)) |
709 | 754 | ||
@@ -716,6 +761,7 @@ struct iwl_priv { | |||
716 | /*data shared among all the driver's layers */ | 761 | /*data shared among all the driver's layers */ |
717 | struct iwl_shared *shrd; | 762 | struct iwl_shared *shrd; |
718 | const struct iwl_fw *fw; | 763 | const struct iwl_fw *fw; |
764 | const struct iwl_lib_ops *lib; | ||
719 | unsigned long status; | 765 | unsigned long status; |
720 | 766 | ||
721 | spinlock_t sta_lock; | 767 | spinlock_t sta_lock; |
@@ -738,6 +784,8 @@ struct iwl_priv { | |||
738 | 784 | ||
739 | struct workqueue_struct *workqueue; | 785 | struct workqueue_struct *workqueue; |
740 | 786 | ||
787 | struct iwl_hw_params hw_params; | ||
788 | |||
741 | enum ieee80211_band band; | 789 | enum ieee80211_band band; |
742 | u8 valid_contexts; | 790 | u8 valid_contexts; |
743 | 791 | ||
@@ -772,8 +820,8 @@ struct iwl_priv { | |||
772 | /*counters */ | 820 | /*counters */ |
773 | u32 rx_handlers_stats[REPLY_MAX]; | 821 | u32 rx_handlers_stats[REPLY_MAX]; |
774 | 822 | ||
775 | /* force reset */ | 823 | /* rf reset */ |
776 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | 824 | struct iwl_rf_reset rf_reset; |
777 | 825 | ||
778 | /* firmware reload counter and timestamp */ | 826 | /* firmware reload counter and timestamp */ |
779 | unsigned long reload_jiffies; | 827 | unsigned long reload_jiffies; |
@@ -819,8 +867,6 @@ struct iwl_priv { | |||
819 | 867 | ||
820 | __le16 switch_channel; | 868 | __le16 switch_channel; |
821 | 869 | ||
822 | u16 active_rate; | ||
823 | |||
824 | u8 start_calib; | 870 | u8 start_calib; |
825 | struct iwl_sensitivity_data sensitivity_data; | 871 | struct iwl_sensitivity_data sensitivity_data; |
826 | struct iwl_chain_noise_data chain_noise_data; | 872 | struct iwl_chain_noise_data chain_noise_data; |
@@ -967,13 +1013,15 @@ struct iwl_priv { | |||
967 | void *wowlan_sram; | 1013 | void *wowlan_sram; |
968 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 1014 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
969 | 1015 | ||
1016 | /* eeprom -- this is in the card's little endian byte order */ | ||
1017 | u8 *eeprom; | ||
1018 | enum iwl_nvm_type nvm_device_type; | ||
1019 | |||
970 | struct work_struct txpower_work; | 1020 | struct work_struct txpower_work; |
971 | u32 disable_sens_cal; | 1021 | u32 calib_disabled; |
972 | u32 disable_chain_noise_cal; | ||
973 | struct work_struct run_time_calib_work; | 1022 | struct work_struct run_time_calib_work; |
974 | struct timer_list statistics_periodic; | 1023 | struct timer_list statistics_periodic; |
975 | struct timer_list ucode_trace; | 1024 | struct timer_list ucode_trace; |
976 | struct timer_list watchdog; | ||
977 | 1025 | ||
978 | struct iwl_event_log event_log; | 1026 | struct iwl_event_log event_log; |
979 | 1027 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 6f312c77af5e..17485e715424 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -284,6 +284,7 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces, | |||
284 | 284 | ||
285 | sec->offset = le32_to_cpu(sec_parse->offset); | 285 | sec->offset = le32_to_cpu(sec_parse->offset); |
286 | sec->data = sec_parse->data; | 286 | sec->data = sec_parse->data; |
287 | sec->size = size - sizeof(sec_parse->offset); | ||
287 | 288 | ||
288 | ++img->sec_counter; | 289 | ++img->sec_counter; |
289 | 290 | ||
@@ -414,9 +415,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
414 | struct iwl_ucode_tlv *tlv; | 415 | struct iwl_ucode_tlv *tlv; |
415 | size_t len = ucode_raw->size; | 416 | size_t len = ucode_raw->size; |
416 | const u8 *data; | 417 | const u8 *data; |
417 | int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; | ||
418 | int tmp; | ||
419 | u64 alternatives; | ||
420 | u32 tlv_len; | 418 | u32 tlv_len; |
421 | enum iwl_ucode_tlv_type tlv_type; | 419 | enum iwl_ucode_tlv_type tlv_type; |
422 | const u8 *tlv_data; | 420 | const u8 *tlv_data; |
@@ -434,23 +432,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
434 | return -EINVAL; | 432 | return -EINVAL; |
435 | } | 433 | } |
436 | 434 | ||
437 | /* | ||
438 | * Check which alternatives are present, and "downgrade" | ||
439 | * when the chosen alternative is not present, warning | ||
440 | * the user when that happens. Some files may not have | ||
441 | * any alternatives, so don't warn in that case. | ||
442 | */ | ||
443 | alternatives = le64_to_cpu(ucode->alternatives); | ||
444 | tmp = wanted_alternative; | ||
445 | if (wanted_alternative > 63) | ||
446 | wanted_alternative = 63; | ||
447 | while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) | ||
448 | wanted_alternative--; | ||
449 | if (wanted_alternative && wanted_alternative != tmp) | ||
450 | IWL_WARN(drv, | ||
451 | "uCode alternative %d not available, choosing %d\n", | ||
452 | tmp, wanted_alternative); | ||
453 | |||
454 | drv->fw.ucode_ver = le32_to_cpu(ucode->ver); | 435 | drv->fw.ucode_ver = le32_to_cpu(ucode->ver); |
455 | build = le32_to_cpu(ucode->build); | 436 | build = le32_to_cpu(ucode->build); |
456 | 437 | ||
@@ -475,14 +456,11 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
475 | len -= sizeof(*ucode); | 456 | len -= sizeof(*ucode); |
476 | 457 | ||
477 | while (len >= sizeof(*tlv)) { | 458 | while (len >= sizeof(*tlv)) { |
478 | u16 tlv_alt; | ||
479 | |||
480 | len -= sizeof(*tlv); | 459 | len -= sizeof(*tlv); |
481 | tlv = (void *)data; | 460 | tlv = (void *)data; |
482 | 461 | ||
483 | tlv_len = le32_to_cpu(tlv->length); | 462 | tlv_len = le32_to_cpu(tlv->length); |
484 | tlv_type = le16_to_cpu(tlv->type); | 463 | tlv_type = le32_to_cpu(tlv->type); |
485 | tlv_alt = le16_to_cpu(tlv->alternative); | ||
486 | tlv_data = tlv->data; | 464 | tlv_data = tlv->data; |
487 | 465 | ||
488 | if (len < tlv_len) { | 466 | if (len < tlv_len) { |
@@ -493,14 +471,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
493 | len -= ALIGN(tlv_len, 4); | 471 | len -= ALIGN(tlv_len, 4); |
494 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | 472 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); |
495 | 473 | ||
496 | /* | ||
497 | * Alternative 0 is always valid. | ||
498 | * | ||
499 | * Skip alternative TLVs that are not selected. | ||
500 | */ | ||
501 | if (tlv_alt != 0 && tlv_alt != wanted_alternative) | ||
502 | continue; | ||
503 | |||
504 | switch (tlv_type) { | 474 | switch (tlv_type) { |
505 | case IWL_UCODE_TLV_INST: | 475 | case IWL_UCODE_TLV_INST: |
506 | set_sec_data(pieces, IWL_UCODE_REGULAR, | 476 | set_sec_data(pieces, IWL_UCODE_REGULAR, |
@@ -838,42 +808,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
838 | IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version); | 808 | IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version); |
839 | 809 | ||
840 | /* | 810 | /* |
841 | * For any of the failures below (before allocating pci memory) | ||
842 | * we will try to load a version with a smaller API -- maybe the | ||
843 | * user just got a corrupted version of the latest API. | ||
844 | */ | ||
845 | |||
846 | IWL_DEBUG_INFO(drv, "f/w package hdr ucode version raw = 0x%x\n", | ||
847 | drv->fw.ucode_ver); | ||
848 | IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n", | ||
849 | get_sec_size(&pieces, IWL_UCODE_REGULAR, | ||
850 | IWL_UCODE_SECTION_INST)); | ||
851 | IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n", | ||
852 | get_sec_size(&pieces, IWL_UCODE_REGULAR, | ||
853 | IWL_UCODE_SECTION_DATA)); | ||
854 | IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n", | ||
855 | get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST)); | ||
856 | IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n", | ||
857 | get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA)); | ||
858 | |||
859 | /* Verify that uCode images will fit in card's SRAM */ | ||
860 | if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) > | ||
861 | cfg->max_inst_size) { | ||
862 | IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n", | ||
863 | get_sec_size(&pieces, IWL_UCODE_REGULAR, | ||
864 | IWL_UCODE_SECTION_INST)); | ||
865 | goto try_again; | ||
866 | } | ||
867 | |||
868 | if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) > | ||
869 | cfg->max_data_size) { | ||
870 | IWL_ERR(drv, "uCode data len %Zd too large to fit in\n", | ||
871 | get_sec_size(&pieces, IWL_UCODE_REGULAR, | ||
872 | IWL_UCODE_SECTION_DATA)); | ||
873 | goto try_again; | ||
874 | } | ||
875 | |||
876 | /* | ||
877 | * In mvm uCode there is no difference between data and instructions | 811 | * In mvm uCode there is no difference between data and instructions |
878 | * sections. | 812 | * sections. |
879 | */ | 813 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 23cea42b9495..a004431d1a60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -187,33 +187,33 @@ static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | |||
187 | 187 | ||
188 | } | 188 | } |
189 | 189 | ||
190 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans) | 190 | static int iwl_eeprom_verify_signature(struct iwl_priv *priv) |
191 | { | 191 | { |
192 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & | 192 | u32 gp = iwl_read32(trans(priv), CSR_EEPROM_GP) & |
193 | CSR_EEPROM_GP_VALID_MSK; | 193 | CSR_EEPROM_GP_VALID_MSK; |
194 | int ret = 0; | 194 | int ret = 0; |
195 | 195 | ||
196 | IWL_DEBUG_EEPROM(trans, "EEPROM signature=0x%08x\n", gp); | 196 | IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); |
197 | switch (gp) { | 197 | switch (gp) { |
198 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | 198 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: |
199 | if (trans->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | 199 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { |
200 | IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n", | 200 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", |
201 | gp); | 201 | gp); |
202 | ret = -ENOENT; | 202 | ret = -ENOENT; |
203 | } | 203 | } |
204 | break; | 204 | break; |
205 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | 205 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: |
206 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | 206 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: |
207 | if (trans->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | 207 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { |
208 | IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp); | 208 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); |
209 | ret = -ENOENT; | 209 | ret = -ENOENT; |
210 | } | 210 | } |
211 | break; | 211 | break; |
212 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | 212 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: |
213 | default: | 213 | default: |
214 | IWL_ERR(trans, "bad EEPROM/OTP signature, type=%s, " | 214 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " |
215 | "EEPROM_GP=0x%08x\n", | 215 | "EEPROM_GP=0x%08x\n", |
216 | (trans->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 216 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
217 | ? "OTP" : "EEPROM", gp); | 217 | ? "OTP" : "EEPROM", gp); |
218 | ret = -ENOENT; | 218 | ret = -ENOENT; |
219 | break; | 219 | break; |
@@ -221,11 +221,11 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans) | |||
221 | return ret; | 221 | return ret; |
222 | } | 222 | } |
223 | 223 | ||
224 | u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset) | 224 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset) |
225 | { | 225 | { |
226 | if (!shrd->eeprom) | 226 | if (!priv->eeprom) |
227 | return 0; | 227 | return 0; |
228 | return (u16)shrd->eeprom[offset] | ((u16)shrd->eeprom[offset + 1] << 8); | 228 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); |
229 | } | 229 | } |
230 | 230 | ||
231 | int iwl_eeprom_check_version(struct iwl_priv *priv) | 231 | int iwl_eeprom_check_version(struct iwl_priv *priv) |
@@ -233,8 +233,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv) | |||
233 | u16 eeprom_ver; | 233 | u16 eeprom_ver; |
234 | u16 calib_ver; | 234 | u16 calib_ver; |
235 | 235 | ||
236 | eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION); | 236 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); |
237 | calib_ver = iwl_eeprom_calib_version(priv->shrd); | 237 | calib_ver = iwl_eeprom_calib_version(priv); |
238 | 238 | ||
239 | if (eeprom_ver < cfg(priv)->eeprom_ver || | 239 | if (eeprom_ver < cfg(priv)->eeprom_ver || |
240 | calib_ver < cfg(priv)->eeprom_calib_ver) | 240 | calib_ver < cfg(priv)->eeprom_calib_ver) |
@@ -255,50 +255,107 @@ err: | |||
255 | 255 | ||
256 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | 256 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv) |
257 | { | 257 | { |
258 | struct iwl_shared *shrd = priv->shrd; | ||
259 | u16 radio_cfg; | 258 | u16 radio_cfg; |
260 | 259 | ||
261 | hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP); | 260 | priv->hw_params.sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); |
262 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE && | 261 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && |
263 | !cfg(priv)->ht_params) { | 262 | !cfg(priv)->ht_params) { |
264 | IWL_ERR(priv, "Invalid 11n configuration\n"); | 263 | IWL_ERR(priv, "Invalid 11n configuration\n"); |
265 | return -EINVAL; | 264 | return -EINVAL; |
266 | } | 265 | } |
267 | 266 | ||
268 | if (!hw_params(priv).sku) { | 267 | if (!priv->hw_params.sku) { |
269 | IWL_ERR(priv, "Invalid device sku\n"); | 268 | IWL_ERR(priv, "Invalid device sku\n"); |
270 | return -EINVAL; | 269 | return -EINVAL; |
271 | } | 270 | } |
272 | 271 | ||
273 | IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku); | 272 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); |
274 | 273 | ||
275 | radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG); | 274 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
276 | 275 | ||
277 | hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | 276 | priv->hw_params.valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); |
278 | hw_params(priv).valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | 277 | priv->hw_params.valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); |
279 | 278 | ||
280 | /* check overrides (some devices have wrong EEPROM) */ | 279 | /* check overrides (some devices have wrong EEPROM) */ |
281 | if (cfg(priv)->valid_tx_ant) | 280 | if (cfg(priv)->valid_tx_ant) |
282 | hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; | 281 | priv->hw_params.valid_tx_ant = cfg(priv)->valid_tx_ant; |
283 | if (cfg(priv)->valid_rx_ant) | 282 | if (cfg(priv)->valid_rx_ant) |
284 | hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; | 283 | priv->hw_params.valid_rx_ant = cfg(priv)->valid_rx_ant; |
285 | 284 | ||
286 | if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) { | 285 | if (!priv->hw_params.valid_tx_ant || !priv->hw_params.valid_rx_ant) { |
287 | IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", | 286 | IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", |
288 | hw_params(priv).valid_tx_ant, | 287 | priv->hw_params.valid_tx_ant, |
289 | hw_params(priv).valid_rx_ant); | 288 | priv->hw_params.valid_rx_ant); |
290 | return -EINVAL; | 289 | return -EINVAL; |
291 | } | 290 | } |
292 | 291 | ||
293 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | 292 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", |
294 | hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant); | 293 | priv->hw_params.valid_tx_ant, priv->hw_params.valid_rx_ant); |
295 | 294 | ||
296 | return 0; | 295 | return 0; |
297 | } | 296 | } |
298 | 297 | ||
299 | void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac) | 298 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv) |
300 | { | 299 | { |
301 | const u8 *addr = iwl_eeprom_query_addr(shrd, | 300 | struct iwl_eeprom_calib_hdr *hdr; |
301 | |||
302 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
303 | EEPROM_CALIB_ALL); | ||
304 | return hdr->version; | ||
305 | } | ||
306 | |||
307 | static u32 eeprom_indirect_address(struct iwl_priv *priv, u32 address) | ||
308 | { | ||
309 | u16 offset = 0; | ||
310 | |||
311 | if ((address & INDIRECT_ADDRESS) == 0) | ||
312 | return address; | ||
313 | |||
314 | switch (address & INDIRECT_TYPE_MSK) { | ||
315 | case INDIRECT_HOST: | ||
316 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | ||
317 | break; | ||
318 | case INDIRECT_GENERAL: | ||
319 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | ||
320 | break; | ||
321 | case INDIRECT_REGULATORY: | ||
322 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | ||
323 | break; | ||
324 | case INDIRECT_TXP_LIMIT: | ||
325 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); | ||
326 | break; | ||
327 | case INDIRECT_TXP_LIMIT_SIZE: | ||
328 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); | ||
329 | break; | ||
330 | case INDIRECT_CALIBRATION: | ||
331 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | ||
332 | break; | ||
333 | case INDIRECT_PROCESS_ADJST: | ||
334 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | ||
335 | break; | ||
336 | case INDIRECT_OTHERS: | ||
337 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | ||
338 | break; | ||
339 | default: | ||
340 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
341 | address & INDIRECT_TYPE_MSK); | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | /* translate the offset from words to byte */ | ||
346 | return (address & ADDRESS_MSK) + (offset << 1); | ||
347 | } | ||
348 | |||
349 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset) | ||
350 | { | ||
351 | u32 address = eeprom_indirect_address(priv, offset); | ||
352 | BUG_ON(address >= cfg(priv)->base_params->eeprom_size); | ||
353 | return &priv->eeprom[address]; | ||
354 | } | ||
355 | |||
356 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac) | ||
357 | { | ||
358 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
302 | EEPROM_MAC_ADDRESS); | 359 | EEPROM_MAC_ADDRESS); |
303 | memcpy(mac, addr, ETH_ALEN); | 360 | memcpy(mac, addr, ETH_ALEN); |
304 | } | 361 | } |
@@ -591,7 +648,6 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | |||
591 | 648 | ||
592 | static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | 649 | static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) |
593 | { | 650 | { |
594 | struct iwl_shared *shrd = priv->shrd; | ||
595 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | 651 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; |
596 | int idx, entries; | 652 | int idx, entries; |
597 | __le16 *txp_len; | 653 | __le16 *txp_len; |
@@ -600,10 +656,10 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
600 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | 656 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); |
601 | 657 | ||
602 | /* the length is in 16-bit words, but we want entries */ | 658 | /* the length is in 16-bit words, but we want entries */ |
603 | txp_len = (__le16 *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_SZ_OFFS); | 659 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); |
604 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | 660 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; |
605 | 661 | ||
606 | txp_array = (void *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_OFFS); | 662 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); |
607 | 663 | ||
608 | for (idx = 0; idx < entries; idx++) { | 664 | for (idx = 0; idx < entries; idx++) { |
609 | txp = &txp_array[idx]; | 665 | txp = &txp_array[idx]; |
@@ -656,66 +712,66 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
656 | /** | 712 | /** |
657 | * iwl_eeprom_init - read EEPROM contents | 713 | * iwl_eeprom_init - read EEPROM contents |
658 | * | 714 | * |
659 | * Load the EEPROM contents from adapter into shrd->eeprom | 715 | * Load the EEPROM contents from adapter into priv->eeprom |
660 | * | 716 | * |
661 | * NOTE: This routine uses the non-debug IO access functions. | 717 | * NOTE: This routine uses the non-debug IO access functions. |
662 | */ | 718 | */ |
663 | int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev) | 719 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) |
664 | { | 720 | { |
665 | __le16 *e; | 721 | __le16 *e; |
666 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP); | 722 | u32 gp = iwl_read32(trans(priv), CSR_EEPROM_GP); |
667 | int sz; | 723 | int sz; |
668 | int ret; | 724 | int ret; |
669 | u16 addr; | 725 | u16 addr; |
670 | u16 validblockaddr = 0; | 726 | u16 validblockaddr = 0; |
671 | u16 cache_addr = 0; | 727 | u16 cache_addr = 0; |
672 | 728 | ||
673 | trans->nvm_device_type = iwl_get_nvm_type(trans, hw_rev); | 729 | priv->nvm_device_type = iwl_get_nvm_type(trans(priv), hw_rev); |
674 | if (trans->nvm_device_type == -ENOENT) | 730 | if (priv->nvm_device_type == -ENOENT) |
675 | return -ENOENT; | 731 | return -ENOENT; |
676 | /* allocate eeprom */ | 732 | /* allocate eeprom */ |
677 | sz = cfg(trans)->base_params->eeprom_size; | 733 | sz = cfg(priv)->base_params->eeprom_size; |
678 | IWL_DEBUG_EEPROM(trans, "NVM size = %d\n", sz); | 734 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); |
679 | trans->shrd->eeprom = kzalloc(sz, GFP_KERNEL); | 735 | priv->eeprom = kzalloc(sz, GFP_KERNEL); |
680 | if (!trans->shrd->eeprom) { | 736 | if (!priv->eeprom) { |
681 | ret = -ENOMEM; | 737 | ret = -ENOMEM; |
682 | goto alloc_err; | 738 | goto alloc_err; |
683 | } | 739 | } |
684 | e = (__le16 *)trans->shrd->eeprom; | 740 | e = (__le16 *)priv->eeprom; |
685 | 741 | ||
686 | ret = iwl_eeprom_verify_signature(trans); | 742 | ret = iwl_eeprom_verify_signature(priv); |
687 | if (ret < 0) { | 743 | if (ret < 0) { |
688 | IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | 744 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); |
689 | ret = -ENOENT; | 745 | ret = -ENOENT; |
690 | goto err; | 746 | goto err; |
691 | } | 747 | } |
692 | 748 | ||
693 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | 749 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ |
694 | ret = iwl_eeprom_acquire_semaphore(trans); | 750 | ret = iwl_eeprom_acquire_semaphore(trans(priv)); |
695 | if (ret < 0) { | 751 | if (ret < 0) { |
696 | IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); | 752 | IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); |
697 | ret = -ENOENT; | 753 | ret = -ENOENT; |
698 | goto err; | 754 | goto err; |
699 | } | 755 | } |
700 | 756 | ||
701 | if (trans->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | 757 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { |
702 | 758 | ||
703 | ret = iwl_init_otp_access(trans); | 759 | ret = iwl_init_otp_access(trans(priv)); |
704 | if (ret) { | 760 | if (ret) { |
705 | IWL_ERR(trans, "Failed to initialize OTP access.\n"); | 761 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); |
706 | ret = -ENOENT; | 762 | ret = -ENOENT; |
707 | goto done; | 763 | goto done; |
708 | } | 764 | } |
709 | iwl_write32(trans, CSR_EEPROM_GP, | 765 | iwl_write32(trans(priv), CSR_EEPROM_GP, |
710 | iwl_read32(trans, CSR_EEPROM_GP) & | 766 | iwl_read32(trans(priv), CSR_EEPROM_GP) & |
711 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | 767 | ~CSR_EEPROM_GP_IF_OWNER_MSK); |
712 | 768 | ||
713 | iwl_set_bit(trans, CSR_OTP_GP_REG, | 769 | iwl_set_bit(trans(priv), CSR_OTP_GP_REG, |
714 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | 770 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | |
715 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | 771 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); |
716 | /* traversing the linked list if no shadow ram supported */ | 772 | /* traversing the linked list if no shadow ram supported */ |
717 | if (!cfg(trans)->base_params->shadow_ram_support) { | 773 | if (!cfg(priv)->base_params->shadow_ram_support) { |
718 | if (iwl_find_otp_image(trans, &validblockaddr)) { | 774 | if (iwl_find_otp_image(trans(priv), &validblockaddr)) { |
719 | ret = -ENOENT; | 775 | ret = -ENOENT; |
720 | goto done; | 776 | goto done; |
721 | } | 777 | } |
@@ -724,7 +780,8 @@ int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev) | |||
724 | addr += sizeof(u16)) { | 780 | addr += sizeof(u16)) { |
725 | __le16 eeprom_data; | 781 | __le16 eeprom_data; |
726 | 782 | ||
727 | ret = iwl_read_otp_word(trans, addr, &eeprom_data); | 783 | ret = iwl_read_otp_word(trans(priv), addr, |
784 | &eeprom_data); | ||
728 | if (ret) | 785 | if (ret) |
729 | goto done; | 786 | goto done; |
730 | e[cache_addr / 2] = eeprom_data; | 787 | e[cache_addr / 2] = eeprom_data; |
@@ -735,94 +792,93 @@ int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev) | |||
735 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | 792 | for (addr = 0; addr < sz; addr += sizeof(u16)) { |
736 | u32 r; | 793 | u32 r; |
737 | 794 | ||
738 | iwl_write32(trans, CSR_EEPROM_REG, | 795 | iwl_write32(trans(priv), CSR_EEPROM_REG, |
739 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 796 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
740 | 797 | ||
741 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | 798 | ret = iwl_poll_bit(trans(priv), CSR_EEPROM_REG, |
742 | CSR_EEPROM_REG_READ_VALID_MSK, | 799 | CSR_EEPROM_REG_READ_VALID_MSK, |
743 | CSR_EEPROM_REG_READ_VALID_MSK, | 800 | CSR_EEPROM_REG_READ_VALID_MSK, |
744 | IWL_EEPROM_ACCESS_TIMEOUT); | 801 | IWL_EEPROM_ACCESS_TIMEOUT); |
745 | if (ret < 0) { | 802 | if (ret < 0) { |
746 | IWL_ERR(trans, | 803 | IWL_ERR(priv, |
747 | "Time out reading EEPROM[%d]\n", addr); | 804 | "Time out reading EEPROM[%d]\n", addr); |
748 | goto done; | 805 | goto done; |
749 | } | 806 | } |
750 | r = iwl_read32(trans, CSR_EEPROM_REG); | 807 | r = iwl_read32(trans(priv), CSR_EEPROM_REG); |
751 | e[addr / 2] = cpu_to_le16(r >> 16); | 808 | e[addr / 2] = cpu_to_le16(r >> 16); |
752 | } | 809 | } |
753 | } | 810 | } |
754 | 811 | ||
755 | IWL_DEBUG_EEPROM(trans, "NVM Type: %s, version: 0x%x\n", | 812 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", |
756 | (trans->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 813 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
757 | ? "OTP" : "EEPROM", | 814 | ? "OTP" : "EEPROM", |
758 | iwl_eeprom_query16(trans->shrd, EEPROM_VERSION)); | 815 | iwl_eeprom_query16(priv, EEPROM_VERSION)); |
759 | 816 | ||
760 | ret = 0; | 817 | ret = 0; |
761 | done: | 818 | done: |
762 | iwl_eeprom_release_semaphore(trans); | 819 | iwl_eeprom_release_semaphore(trans(priv)); |
763 | 820 | ||
764 | err: | 821 | err: |
765 | if (ret) | 822 | if (ret) |
766 | iwl_eeprom_free(trans->shrd); | 823 | iwl_eeprom_free(priv); |
767 | alloc_err: | 824 | alloc_err: |
768 | return ret; | 825 | return ret; |
769 | } | 826 | } |
770 | 827 | ||
771 | void iwl_eeprom_free(struct iwl_shared *shrd) | 828 | void iwl_eeprom_free(struct iwl_priv *priv) |
772 | { | 829 | { |
773 | kfree(shrd->eeprom); | 830 | kfree(priv->eeprom); |
774 | shrd->eeprom = NULL; | 831 | priv->eeprom = NULL; |
775 | } | 832 | } |
776 | 833 | ||
777 | static void iwl_init_band_reference(const struct iwl_priv *priv, | 834 | static void iwl_init_band_reference(struct iwl_priv *priv, |
778 | int eep_band, int *eeprom_ch_count, | 835 | int eep_band, int *eeprom_ch_count, |
779 | const struct iwl_eeprom_channel **eeprom_ch_info, | 836 | const struct iwl_eeprom_channel **eeprom_ch_info, |
780 | const u8 **eeprom_ch_index) | 837 | const u8 **eeprom_ch_index) |
781 | { | 838 | { |
782 | struct iwl_shared *shrd = priv->shrd; | 839 | u32 offset = priv->lib-> |
783 | u32 offset = cfg(priv)->lib-> | ||
784 | eeprom_ops.regulatory_bands[eep_band - 1]; | 840 | eeprom_ops.regulatory_bands[eep_band - 1]; |
785 | switch (eep_band) { | 841 | switch (eep_band) { |
786 | case 1: /* 2.4GHz band */ | 842 | case 1: /* 2.4GHz band */ |
787 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | 843 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); |
788 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 844 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
789 | iwl_eeprom_query_addr(shrd, offset); | 845 | iwl_eeprom_query_addr(priv, offset); |
790 | *eeprom_ch_index = iwl_eeprom_band_1; | 846 | *eeprom_ch_index = iwl_eeprom_band_1; |
791 | break; | 847 | break; |
792 | case 2: /* 4.9GHz band */ | 848 | case 2: /* 4.9GHz band */ |
793 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | 849 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); |
794 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 850 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
795 | iwl_eeprom_query_addr(shrd, offset); | 851 | iwl_eeprom_query_addr(priv, offset); |
796 | *eeprom_ch_index = iwl_eeprom_band_2; | 852 | *eeprom_ch_index = iwl_eeprom_band_2; |
797 | break; | 853 | break; |
798 | case 3: /* 5.2GHz band */ | 854 | case 3: /* 5.2GHz band */ |
799 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | 855 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); |
800 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 856 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
801 | iwl_eeprom_query_addr(shrd, offset); | 857 | iwl_eeprom_query_addr(priv, offset); |
802 | *eeprom_ch_index = iwl_eeprom_band_3; | 858 | *eeprom_ch_index = iwl_eeprom_band_3; |
803 | break; | 859 | break; |
804 | case 4: /* 5.5GHz band */ | 860 | case 4: /* 5.5GHz band */ |
805 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | 861 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); |
806 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 862 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
807 | iwl_eeprom_query_addr(shrd, offset); | 863 | iwl_eeprom_query_addr(priv, offset); |
808 | *eeprom_ch_index = iwl_eeprom_band_4; | 864 | *eeprom_ch_index = iwl_eeprom_band_4; |
809 | break; | 865 | break; |
810 | case 5: /* 5.7GHz band */ | 866 | case 5: /* 5.7GHz band */ |
811 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | 867 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); |
812 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 868 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
813 | iwl_eeprom_query_addr(shrd, offset); | 869 | iwl_eeprom_query_addr(priv, offset); |
814 | *eeprom_ch_index = iwl_eeprom_band_5; | 870 | *eeprom_ch_index = iwl_eeprom_band_5; |
815 | break; | 871 | break; |
816 | case 6: /* 2.4GHz ht40 channels */ | 872 | case 6: /* 2.4GHz ht40 channels */ |
817 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | 873 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); |
818 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 874 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
819 | iwl_eeprom_query_addr(shrd, offset); | 875 | iwl_eeprom_query_addr(priv, offset); |
820 | *eeprom_ch_index = iwl_eeprom_band_6; | 876 | *eeprom_ch_index = iwl_eeprom_band_6; |
821 | break; | 877 | break; |
822 | case 7: /* 5 GHz ht40 channels */ | 878 | case 7: /* 5 GHz ht40 channels */ |
823 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | 879 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); |
824 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | 880 | *eeprom_ch_info = (struct iwl_eeprom_channel *) |
825 | iwl_eeprom_query_addr(shrd, offset); | 881 | iwl_eeprom_query_addr(priv, offset); |
826 | *eeprom_ch_index = iwl_eeprom_band_7; | 882 | *eeprom_ch_index = iwl_eeprom_band_7; |
827 | break; | 883 | break; |
828 | default: | 884 | default: |
@@ -987,9 +1043,9 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
987 | } | 1043 | } |
988 | 1044 | ||
989 | /* Check if we do have HT40 channels */ | 1045 | /* Check if we do have HT40 channels */ |
990 | if (cfg(priv)->lib->eeprom_ops.regulatory_bands[5] == | 1046 | if (priv->lib->eeprom_ops.regulatory_bands[5] == |
991 | EEPROM_REGULATORY_BAND_NO_HT40 && | 1047 | EEPROM_REGULATORY_BAND_NO_HT40 && |
992 | cfg(priv)->lib->eeprom_ops.regulatory_bands[6] == | 1048 | priv->lib->eeprom_ops.regulatory_bands[6] == |
993 | EEPROM_REGULATORY_BAND_NO_HT40) | 1049 | EEPROM_REGULATORY_BAND_NO_HT40) |
994 | return 0; | 1050 | return 0; |
995 | 1051 | ||
@@ -1025,7 +1081,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
1025 | * driver need to process addition information | 1081 | * driver need to process addition information |
1026 | * to determine the max channel tx power limits | 1082 | * to determine the max channel tx power limits |
1027 | */ | 1083 | */ |
1028 | if (cfg(priv)->lib->eeprom_ops.enhanced_txpower) | 1084 | if (priv->lib->eeprom_ops.enhanced_txpower) |
1029 | iwl_eeprom_enhanced_txpower(priv); | 1085 | iwl_eeprom_enhanced_txpower(priv); |
1030 | 1086 | ||
1031 | return 0; | 1087 | return 0; |
@@ -1072,7 +1128,7 @@ void iwl_rf_config(struct iwl_priv *priv) | |||
1072 | { | 1128 | { |
1073 | u16 radio_cfg; | 1129 | u16 radio_cfg; |
1074 | 1130 | ||
1075 | radio_cfg = iwl_eeprom_query16(priv->shrd, EEPROM_RADIO_CONFIG); | 1131 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
1076 | 1132 | ||
1077 | /* write radio config values to register */ | 1133 | /* write radio config values to register */ |
1078 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | 1134 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e4a758340996..b3a3b1f0fdc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -66,8 +66,6 @@ | |||
66 | #include <net/mac80211.h> | 66 | #include <net/mac80211.h> |
67 | 67 | ||
68 | struct iwl_priv; | 68 | struct iwl_priv; |
69 | struct iwl_shared; | ||
70 | struct iwl_trans; | ||
71 | 69 | ||
72 | /* | 70 | /* |
73 | * EEPROM access time values: | 71 | * EEPROM access time values: |
@@ -306,12 +304,14 @@ struct iwl_eeprom_ops { | |||
306 | }; | 304 | }; |
307 | 305 | ||
308 | 306 | ||
309 | int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev); | 307 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); |
310 | void iwl_eeprom_free(struct iwl_shared *shrd); | 308 | void iwl_eeprom_free(struct iwl_priv *priv); |
311 | int iwl_eeprom_check_version(struct iwl_priv *priv); | 309 | int iwl_eeprom_check_version(struct iwl_priv *priv); |
312 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv); | 310 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv); |
313 | const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset); | 311 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv); |
314 | u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset); | 312 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset); |
313 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset); | ||
314 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac); | ||
315 | int iwl_init_channel_map(struct iwl_priv *priv); | 315 | int iwl_init_channel_map(struct iwl_priv *priv); |
316 | void iwl_free_channel_map(struct iwl_priv *priv); | 316 | void iwl_free_channel_map(struct iwl_priv *priv); |
317 | const struct iwl_channel_info *iwl_get_channel_info( | 317 | const struct iwl_channel_info *iwl_get_channel_info( |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index c924ccb93c8c..e71564053e7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -93,15 +93,7 @@ struct iwl_ucode_header { | |||
93 | * new TLV uCode file layout | 93 | * new TLV uCode file layout |
94 | * | 94 | * |
95 | * The new TLV file format contains TLVs, that each specify | 95 | * The new TLV file format contains TLVs, that each specify |
96 | * some piece of data. To facilitate "groups", for example | 96 | * some piece of data. |
97 | * different instruction image with different capabilities, | ||
98 | * bundled with the same init image, an alternative mechanism | ||
99 | * is provided: | ||
100 | * When the alternative field is 0, that means that the item | ||
101 | * is always valid. When it is non-zero, then it is only | ||
102 | * valid in conjunction with items of the same alternative, | ||
103 | * in which case the driver (user) selects one alternative | ||
104 | * to use. | ||
105 | */ | 97 | */ |
106 | 98 | ||
107 | enum iwl_ucode_tlv_type { | 99 | enum iwl_ucode_tlv_type { |
@@ -132,8 +124,7 @@ enum iwl_ucode_tlv_type { | |||
132 | }; | 124 | }; |
133 | 125 | ||
134 | struct iwl_ucode_tlv { | 126 | struct iwl_ucode_tlv { |
135 | __le16 type; /* see above */ | 127 | __le32 type; /* see above */ |
136 | __le16 alternative; /* see comment */ | ||
137 | __le32 length; /* not including type/length fields */ | 128 | __le32 length; /* not including type/length fields */ |
138 | u8 data[0]; | 129 | u8 data[0]; |
139 | }; | 130 | }; |
@@ -152,7 +143,7 @@ struct iwl_tlv_ucode_header { | |||
152 | u8 human_readable[64]; | 143 | u8 human_readable[64]; |
153 | __le32 ver; /* major/minor/API/serial */ | 144 | __le32 ver; /* major/minor/API/serial */ |
154 | __le32 build; | 145 | __le32 build; |
155 | __le64 alternatives; /* bitmask of valid alternatives */ | 146 | __le64 ignore; |
156 | /* | 147 | /* |
157 | * The data contained herein has a TLV layout, | 148 | * The data contained herein has a TLV layout, |
158 | * see above for the TLV header and types. | 149 | * see above for the TLV header and types. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index f1c675a2a6f3..3f82ff4f3afe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -160,7 +160,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
160 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 160 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
161 | IEEE80211_HW_SCAN_WHILE_IDLE; | 161 | IEEE80211_HW_SCAN_WHILE_IDLE; |
162 | 162 | ||
163 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | 163 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |
164 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 164 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
165 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 165 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
166 | 166 | ||
@@ -333,7 +333,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) | |||
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static void iwlagn_mac_stop(struct ieee80211_hw *hw) | 336 | void iwlagn_mac_stop(struct ieee80211_hw *hw) |
337 | { | 337 | { |
338 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 338 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
339 | 339 | ||
@@ -361,9 +361,9 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
361 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 361 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
362 | } | 362 | } |
363 | 363 | ||
364 | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | 364 | void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, |
365 | struct ieee80211_vif *vif, | 365 | struct ieee80211_vif *vif, |
366 | struct cfg80211_gtk_rekey_data *data) | 366 | struct cfg80211_gtk_rekey_data *data) |
367 | { | 367 | { |
368 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 368 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
369 | 369 | ||
@@ -389,8 +389,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | |||
389 | 389 | ||
390 | #ifdef CONFIG_PM_SLEEP | 390 | #ifdef CONFIG_PM_SLEEP |
391 | 391 | ||
392 | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | 392 | int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
393 | struct cfg80211_wowlan *wowlan) | ||
394 | { | 393 | { |
395 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 394 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
396 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 395 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
@@ -499,7 +498,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
499 | 498 | ||
500 | #endif | 499 | #endif |
501 | 500 | ||
502 | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 501 | void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
503 | { | 502 | { |
504 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 503 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
505 | 504 | ||
@@ -510,21 +509,21 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
510 | dev_kfree_skb_any(skb); | 509 | dev_kfree_skb_any(skb); |
511 | } | 510 | } |
512 | 511 | ||
513 | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | 512 | void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, |
514 | struct ieee80211_vif *vif, | 513 | struct ieee80211_vif *vif, |
515 | struct ieee80211_key_conf *keyconf, | 514 | struct ieee80211_key_conf *keyconf, |
516 | struct ieee80211_sta *sta, | 515 | struct ieee80211_sta *sta, |
517 | u32 iv32, u16 *phase1key) | 516 | u32 iv32, u16 *phase1key) |
518 | { | 517 | { |
519 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 518 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
520 | 519 | ||
521 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | 520 | iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); |
522 | } | 521 | } |
523 | 522 | ||
524 | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 523 | int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
525 | struct ieee80211_vif *vif, | 524 | struct ieee80211_vif *vif, |
526 | struct ieee80211_sta *sta, | 525 | struct ieee80211_sta *sta, |
527 | struct ieee80211_key_conf *key) | 526 | struct ieee80211_key_conf *key) |
528 | { | 527 | { |
529 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 528 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
530 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 529 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -624,11 +623,11 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
624 | return ret; | 623 | return ret; |
625 | } | 624 | } |
626 | 625 | ||
627 | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | 626 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |
628 | struct ieee80211_vif *vif, | 627 | struct ieee80211_vif *vif, |
629 | enum ieee80211_ampdu_mlme_action action, | 628 | enum ieee80211_ampdu_mlme_action action, |
630 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 629 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
631 | u8 buf_size) | 630 | u8 buf_size) |
632 | { | 631 | { |
633 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 632 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
634 | int ret = -EINVAL; | 633 | int ret = -EINVAL; |
@@ -637,7 +636,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
637 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | 636 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", |
638 | sta->addr, tid); | 637 | sta->addr, tid); |
639 | 638 | ||
640 | if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)) | 639 | if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)) |
641 | return -EACCES; | 640 | return -EACCES; |
642 | 641 | ||
643 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 642 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
@@ -671,7 +670,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
671 | priv->agg_tids_count); | 670 | priv->agg_tids_count); |
672 | } | 671 | } |
673 | if (!priv->agg_tids_count && | 672 | if (!priv->agg_tids_count && |
674 | hw_params(priv).use_rts_for_aggregation) { | 673 | priv->hw_params.use_rts_for_aggregation) { |
675 | /* | 674 | /* |
676 | * switch off RTS/CTS if it was previously enabled | 675 | * switch off RTS/CTS if it was previously enabled |
677 | */ | 676 | */ |
@@ -750,11 +749,11 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, | |||
750 | return ret; | 749 | return ret; |
751 | } | 750 | } |
752 | 751 | ||
753 | static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | 752 | int iwlagn_mac_sta_state(struct ieee80211_hw *hw, |
754 | struct ieee80211_vif *vif, | 753 | struct ieee80211_vif *vif, |
755 | struct ieee80211_sta *sta, | 754 | struct ieee80211_sta *sta, |
756 | enum ieee80211_sta_state old_state, | 755 | enum ieee80211_sta_state old_state, |
757 | enum ieee80211_sta_state new_state) | 756 | enum ieee80211_sta_state new_state) |
758 | { | 757 | { |
759 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 758 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
760 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 759 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -833,8 +832,8 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | |||
833 | return ret; | 832 | return ret; |
834 | } | 833 | } |
835 | 834 | ||
836 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | 835 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, |
837 | struct ieee80211_channel_switch *ch_switch) | 836 | struct ieee80211_channel_switch *ch_switch) |
838 | { | 837 | { |
839 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 838 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
840 | const struct iwl_channel_info *ch_info; | 839 | const struct iwl_channel_info *ch_info; |
@@ -867,7 +866,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | |||
867 | if (!iwl_is_associated_ctx(ctx)) | 866 | if (!iwl_is_associated_ctx(ctx)) |
868 | goto out; | 867 | goto out; |
869 | 868 | ||
870 | if (!cfg(priv)->lib->set_channel_switch) | 869 | if (!priv->lib->set_channel_switch) |
871 | goto out; | 870 | goto out; |
872 | 871 | ||
873 | ch = channel->hw_value; | 872 | ch = channel->hw_value; |
@@ -903,7 +902,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | |||
903 | */ | 902 | */ |
904 | set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); | 903 | set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); |
905 | priv->switch_channel = cpu_to_le16(ch); | 904 | priv->switch_channel = cpu_to_le16(ch); |
906 | if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) { | 905 | if (priv->lib->set_channel_switch(priv, ch_switch)) { |
907 | clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); | 906 | clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); |
908 | priv->switch_channel = 0; | 907 | priv->switch_channel = 0; |
909 | ieee80211_chswitch_done(ctx->vif, false); | 908 | ieee80211_chswitch_done(ctx->vif, false); |
@@ -914,10 +913,25 @@ out: | |||
914 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 913 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
915 | } | 914 | } |
916 | 915 | ||
917 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, | 916 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) |
918 | unsigned int changed_flags, | 917 | { |
919 | unsigned int *total_flags, | 918 | /* |
920 | u64 multicast) | 919 | * MULTI-FIXME |
920 | * See iwlagn_mac_channel_switch. | ||
921 | */ | ||
922 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
923 | |||
924 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
925 | return; | ||
926 | |||
927 | if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) | ||
928 | ieee80211_chswitch_done(ctx->vif, is_success); | ||
929 | } | ||
930 | |||
931 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
932 | unsigned int changed_flags, | ||
933 | unsigned int *total_flags, | ||
934 | u64 multicast) | ||
921 | { | 935 | { |
922 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 936 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
923 | __le32 filter_or = 0, filter_nand = 0; | 937 | __le32 filter_or = 0, filter_nand = 0; |
@@ -964,7 +978,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
964 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 978 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
965 | } | 979 | } |
966 | 980 | ||
967 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | 981 | void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) |
968 | { | 982 | { |
969 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 983 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
970 | 984 | ||
@@ -1091,7 +1105,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
1091 | return err; | 1105 | return err; |
1092 | } | 1106 | } |
1093 | 1107 | ||
1094 | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | 1108 | int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) |
1095 | { | 1109 | { |
1096 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1110 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1097 | 1111 | ||
@@ -1108,8 +1122,8 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
1108 | return 0; | 1122 | return 0; |
1109 | } | 1123 | } |
1110 | 1124 | ||
1111 | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | 1125 | void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, |
1112 | enum ieee80211_rssi_event rssi_event) | 1126 | enum ieee80211_rssi_event rssi_event) |
1113 | { | 1127 | { |
1114 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1128 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1115 | 1129 | ||
@@ -1133,8 +1147,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | |||
1133 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1147 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1134 | } | 1148 | } |
1135 | 1149 | ||
1136 | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | 1150 | int iwlagn_mac_set_tim(struct ieee80211_hw *hw, |
1137 | struct ieee80211_sta *sta, bool set) | 1151 | struct ieee80211_sta *sta, bool set) |
1138 | { | 1152 | { |
1139 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1153 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1140 | 1154 | ||
@@ -1143,9 +1157,9 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | |||
1143 | return 0; | 1157 | return 0; |
1144 | } | 1158 | } |
1145 | 1159 | ||
1146 | static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | 1160 | int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, |
1147 | struct ieee80211_vif *vif, u16 queue, | 1161 | struct ieee80211_vif *vif, u16 queue, |
1148 | const struct ieee80211_tx_queue_params *params) | 1162 | const struct ieee80211_tx_queue_params *params) |
1149 | { | 1163 | { |
1150 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1164 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1151 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1165 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
@@ -1187,7 +1201,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | |||
1187 | return 0; | 1201 | return 0; |
1188 | } | 1202 | } |
1189 | 1203 | ||
1190 | static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) | 1204 | int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) |
1191 | { | 1205 | { |
1192 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1206 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1193 | 1207 | ||
@@ -1203,8 +1217,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
1203 | return iwlagn_commit_rxon(priv, ctx); | 1217 | return iwlagn_commit_rxon(priv, ctx); |
1204 | } | 1218 | } |
1205 | 1219 | ||
1206 | static int iwl_setup_interface(struct iwl_priv *priv, | 1220 | int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
1207 | struct iwl_rxon_context *ctx) | ||
1208 | { | 1221 | { |
1209 | struct ieee80211_vif *vif = ctx->vif; | 1222 | struct ieee80211_vif *vif = ctx->vif; |
1210 | int err; | 1223 | int err; |
@@ -1307,9 +1320,9 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, | |||
1307 | return err; | 1320 | return err; |
1308 | } | 1321 | } |
1309 | 1322 | ||
1310 | static void iwl_teardown_interface(struct iwl_priv *priv, | 1323 | void iwl_teardown_interface(struct iwl_priv *priv, |
1311 | struct ieee80211_vif *vif, | 1324 | struct ieee80211_vif *vif, |
1312 | bool mode_change) | 1325 | bool mode_change) |
1313 | { | 1326 | { |
1314 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1327 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
1315 | 1328 | ||
@@ -1450,9 +1463,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1450 | return err; | 1463 | return err; |
1451 | } | 1464 | } |
1452 | 1465 | ||
1453 | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | 1466 | int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, |
1454 | struct ieee80211_vif *vif, | 1467 | struct ieee80211_vif *vif, |
1455 | struct cfg80211_scan_request *req) | 1468 | struct cfg80211_scan_request *req) |
1456 | { | 1469 | { |
1457 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1470 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1458 | int ret; | 1471 | int ret; |
@@ -1507,7 +1520,7 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1507 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); | 1520 | iwl_send_add_sta(priv, &cmd, CMD_ASYNC); |
1508 | } | 1521 | } |
1509 | 1522 | ||
1510 | static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | 1523 | void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, |
1511 | struct ieee80211_vif *vif, | 1524 | struct ieee80211_vif *vif, |
1512 | enum sta_notify_cmd cmd, | 1525 | enum sta_notify_cmd cmd, |
1513 | struct ieee80211_sta *sta) | 1526 | struct ieee80211_sta *sta) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index b1fd251e88d5..ca947aebb727 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -125,6 +125,7 @@ struct iwl_fw; | |||
125 | * @cmd_queue_full: Called when the command queue gets full. Must be atomic. | 125 | * @cmd_queue_full: Called when the command queue gets full. Must be atomic. |
126 | * @nic_config: configure NIC, called before firmware is started. | 126 | * @nic_config: configure NIC, called before firmware is started. |
127 | * May sleep | 127 | * May sleep |
128 | * @wimax_active: invoked when WiMax becomes active. Must be atomic. | ||
128 | */ | 129 | */ |
129 | struct iwl_op_mode_ops { | 130 | struct iwl_op_mode_ops { |
130 | struct iwl_op_mode *(*start)(struct iwl_trans *trans, | 131 | struct iwl_op_mode *(*start)(struct iwl_trans *trans, |
@@ -139,6 +140,7 @@ struct iwl_op_mode_ops { | |||
139 | void (*nic_error)(struct iwl_op_mode *op_mode); | 140 | void (*nic_error)(struct iwl_op_mode *op_mode); |
140 | void (*cmd_queue_full)(struct iwl_op_mode *op_mode); | 141 | void (*cmd_queue_full)(struct iwl_op_mode *op_mode); |
141 | void (*nic_config)(struct iwl_op_mode *op_mode); | 142 | void (*nic_config)(struct iwl_op_mode *op_mode); |
143 | void (*wimax_active)(struct iwl_op_mode *op_mode); | ||
142 | }; | 144 | }; |
143 | 145 | ||
144 | /** | 146 | /** |
@@ -209,6 +211,11 @@ static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode) | |||
209 | op_mode->ops->nic_config(op_mode); | 211 | op_mode->ops->nic_config(op_mode); |
210 | } | 212 | } |
211 | 213 | ||
214 | static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode) | ||
215 | { | ||
216 | op_mode->ops->wimax_active(op_mode); | ||
217 | } | ||
218 | |||
212 | /***************************************************** | 219 | /***************************************************** |
213 | * Op mode layers implementations | 220 | * Op mode layers implementations |
214 | ******************************************************/ | 221 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index f3e56b04d775..754001581340 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -67,10 +67,8 @@ | |||
67 | #include <linux/pci.h> | 67 | #include <linux/pci.h> |
68 | #include <linux/pci-aspm.h> | 68 | #include <linux/pci-aspm.h> |
69 | 69 | ||
70 | #include "iwl-io.h" | ||
71 | #include "iwl-shared.h" | 70 | #include "iwl-shared.h" |
72 | #include "iwl-trans.h" | 71 | #include "iwl-trans.h" |
73 | #include "iwl-csr.h" | ||
74 | #include "iwl-cfg.h" | 72 | #include "iwl-cfg.h" |
75 | #include "iwl-drv.h" | 73 | #include "iwl-drv.h" |
76 | #include "iwl-trans.h" | 74 | #include "iwl-trans.h" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index d65305d08ebf..1a791af82d15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -228,8 +228,24 @@ static u16 channel_id_to_papd(u16 ch_id) | |||
228 | 228 | ||
229 | static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id) | 229 | static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id) |
230 | { | 230 | { |
231 | /* TODO David*/ | 231 | struct iwl_phy_db_chg_txp *txp_chg; |
232 | return 0; | 232 | int i; |
233 | u8 ch_index = ch_id_to_ch_index(ch_id); | ||
234 | if (ch_index == 0xff) | ||
235 | return 0xff; | ||
236 | |||
237 | for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++) { | ||
238 | txp_chg = (void *)phy_db->calib_ch_group_txp[i].data; | ||
239 | if (!txp_chg) | ||
240 | return 0xff; | ||
241 | /* | ||
242 | * Looking for the first channel group that its max channel is | ||
243 | * higher then wanted channel. | ||
244 | */ | ||
245 | if (le16_to_cpu(txp_chg->max_channel_idx) >= ch_index) | ||
246 | return i; | ||
247 | } | ||
248 | return 0xff; | ||
233 | } | 249 | } |
234 | 250 | ||
235 | int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | 251 | int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h index ba91a8b28398..5e86305de66a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.h +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h | |||
@@ -108,6 +108,12 @@ enum iwl_phy_db_section_type { | |||
108 | IWL_PHY_DB_MAX | 108 | IWL_PHY_DB_MAX |
109 | }; | 109 | }; |
110 | 110 | ||
111 | /* for parsing of tx power channel group data that comes from the firmware*/ | ||
112 | struct iwl_phy_db_chg_txp { | ||
113 | __le32 space; | ||
114 | __le16 max_channel_idx; | ||
115 | } __packed; | ||
116 | |||
111 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_shared *shrd); | 117 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_shared *shrd); |
112 | 118 | ||
113 | void iwl_phy_db_free(struct iwl_phy_db *phy_db); | 119 | void iwl_phy_db_free(struct iwl_phy_db *phy_db); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 7bc7a82aba47..174a0f737214 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -268,61 +268,6 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, | |||
268 | IWL_DEBUG_POWER(priv, "Sleep command for CAM\n"); | 268 | IWL_DEBUG_POWER(priv, "Sleep command for CAM\n"); |
269 | } | 269 | } |
270 | 270 | ||
271 | static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, | ||
272 | struct iwl_powertable_cmd *cmd, | ||
273 | int dynps_ms, int wakeup_period) | ||
274 | { | ||
275 | /* | ||
276 | * These are the original power level 3 sleep successions. The | ||
277 | * device may behave better with such succession and was also | ||
278 | * only tested with that. Just like the original sleep commands, | ||
279 | * also adjust the succession here to the wakeup_period below. | ||
280 | * The ranges are the same as for the sleep commands, 0-2, 3-9 | ||
281 | * and >10, which is selected based on the DTIM interval for | ||
282 | * the sleep index but here we use the wakeup period since that | ||
283 | * is what we need to do for the latency requirements. | ||
284 | */ | ||
285 | static const u8 slp_succ_r0[IWL_POWER_VEC_SIZE] = { 2, 2, 2, 2, 2 }; | ||
286 | static const u8 slp_succ_r1[IWL_POWER_VEC_SIZE] = { 2, 4, 6, 7, 9 }; | ||
287 | static const u8 slp_succ_r2[IWL_POWER_VEC_SIZE] = { 2, 7, 9, 9, 0xFF }; | ||
288 | const u8 *slp_succ = slp_succ_r0; | ||
289 | int i; | ||
290 | |||
291 | if (wakeup_period > IWL_DTIM_RANGE_0_MAX) | ||
292 | slp_succ = slp_succ_r1; | ||
293 | if (wakeup_period > IWL_DTIM_RANGE_1_MAX) | ||
294 | slp_succ = slp_succ_r2; | ||
295 | |||
296 | memset(cmd, 0, sizeof(*cmd)); | ||
297 | |||
298 | cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK | | ||
299 | IWL_POWER_FAST_PD; /* no use seeing frames for others */ | ||
300 | |||
301 | if (priv->power_data.bus_pm) | ||
302 | cmd->flags |= IWL_POWER_PCI_PM_MSK; | ||
303 | |||
304 | if (cfg(priv)->base_params->shadow_reg_enable) | ||
305 | cmd->flags |= IWL_POWER_SHADOW_REG_ENA; | ||
306 | else | ||
307 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; | ||
308 | |||
309 | if (iwl_advanced_bt_coexist(priv)) { | ||
310 | if (!cfg(priv)->bt_params->bt_sco_disable) | ||
311 | cmd->flags |= IWL_POWER_BT_SCO_ENA; | ||
312 | else | ||
313 | cmd->flags &= ~IWL_POWER_BT_SCO_ENA; | ||
314 | } | ||
315 | |||
316 | cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms); | ||
317 | cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms); | ||
318 | |||
319 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | ||
320 | cmd->sleep_interval[i] = | ||
321 | cpu_to_le32(min_t(int, slp_succ[i], wakeup_period)); | ||
322 | |||
323 | IWL_DEBUG_POWER(priv, "Automatic sleep command\n"); | ||
324 | } | ||
325 | |||
326 | static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) | 271 | static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) |
327 | { | 272 | { |
328 | IWL_DEBUG_POWER(priv, "Sending power/sleep command\n"); | 273 | IWL_DEBUG_POWER(priv, "Sending power/sleep command\n"); |
@@ -363,7 +308,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
363 | iwl_static_sleep_cmd(priv, cmd, | 308 | iwl_static_sleep_cmd(priv, cmd, |
364 | priv->power_data.debug_sleep_level_override, | 309 | priv->power_data.debug_sleep_level_override, |
365 | dtimper); | 310 | dtimper); |
366 | else if (iwlagn_mod_params.no_sleep_autoadjust) { | 311 | else { |
367 | if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 && | 312 | if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 && |
368 | iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5) | 313 | iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5) |
369 | iwl_static_sleep_cmd(priv, cmd, | 314 | iwl_static_sleep_cmd(priv, cmd, |
@@ -371,10 +316,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
371 | else | 316 | else |
372 | iwl_static_sleep_cmd(priv, cmd, | 317 | iwl_static_sleep_cmd(priv, cmd, |
373 | IWL_POWER_INDEX_1, dtimper); | 318 | IWL_POWER_INDEX_1, dtimper); |
374 | } else | 319 | } |
375 | iwl_power_fill_sleep_cmd(priv, cmd, | ||
376 | priv->hw->conf.dynamic_ps_timeout, | ||
377 | priv->hw->conf.max_sleep_period); | ||
378 | } | 320 | } |
379 | 321 | ||
380 | int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, | 322 | int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dcf5b12071b4..490a60d8ad7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -673,12 +673,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
673 | u16 rx_chain = 0; | 673 | u16 rx_chain = 0; |
674 | enum ieee80211_band band; | 674 | enum ieee80211_band band; |
675 | u8 n_probes = 0; | 675 | u8 n_probes = 0; |
676 | u8 rx_ant = hw_params(priv).valid_rx_ant; | 676 | u8 rx_ant = priv->hw_params.valid_rx_ant; |
677 | u8 rate; | 677 | u8 rate; |
678 | bool is_active = false; | 678 | bool is_active = false; |
679 | int chan_mod; | 679 | int chan_mod; |
680 | u8 active_chains; | 680 | u8 active_chains; |
681 | u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; | 681 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; |
682 | int ret; | 682 | int ret; |
683 | 683 | ||
684 | lockdep_assert_held(&priv->mutex); | 684 | lockdep_assert_held(&priv->mutex); |
@@ -872,7 +872,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
872 | 872 | ||
873 | /* MIMO is not used here, but value is required */ | 873 | /* MIMO is not used here, but value is required */ |
874 | rx_chain |= | 874 | rx_chain |= |
875 | hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | 875 | priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
876 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 876 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
877 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 877 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
878 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 878 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
@@ -985,7 +985,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
985 | 985 | ||
986 | void iwl_init_scan_params(struct iwl_priv *priv) | 986 | void iwl_init_scan_params(struct iwl_priv *priv) |
987 | { | 987 | { |
988 | u8 ant_idx = fls(hw_params(priv).valid_tx_ant) - 1; | 988 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; |
989 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | 989 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) |
990 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | 990 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; |
991 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 991 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 983b41e43d4b..35bd83ce3dae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -70,6 +70,7 @@ | |||
70 | 70 | ||
71 | #include "iwl-commands.h" | 71 | #include "iwl-commands.h" |
72 | #include "iwl-fw.h" | 72 | #include "iwl-fw.h" |
73 | #include "iwl-config.h" | ||
73 | 74 | ||
74 | /** | 75 | /** |
75 | * DOC: shared area - role and goal | 76 | * DOC: shared area - role and goal |
@@ -95,7 +96,6 @@ | |||
95 | 96 | ||
96 | struct iwl_priv; | 97 | struct iwl_priv; |
97 | struct iwl_trans; | 98 | struct iwl_trans; |
98 | struct iwl_sensitivity_ranges; | ||
99 | struct iwl_trans_ops; | 99 | struct iwl_trans_ops; |
100 | 100 | ||
101 | #define DRV_NAME "iwlwifi" | 101 | #define DRV_NAME "iwlwifi" |
@@ -118,252 +118,56 @@ extern struct iwl_mod_params iwlagn_mod_params; | |||
118 | * @disable_11n: disable 11n capabilities, default = 0, | 118 | * @disable_11n: disable 11n capabilities, default = 0, |
119 | * use IWL_DISABLE_HT_* constants | 119 | * use IWL_DISABLE_HT_* constants |
120 | * @amsdu_size_8K: enable 8K amsdu size, default = 1 | 120 | * @amsdu_size_8K: enable 8K amsdu size, default = 1 |
121 | * @antenna: both antennas (use diversity), default = 0 | ||
122 | * @restart_fw: restart firmware, default = 1 | 121 | * @restart_fw: restart firmware, default = 1 |
123 | * @plcp_check: enable plcp health check, default = true | 122 | * @plcp_check: enable plcp health check, default = true |
124 | * @ack_check: disable ack health check, default = false | ||
125 | * @wd_disable: enable stuck queue check, default = 0 | 123 | * @wd_disable: enable stuck queue check, default = 0 |
126 | * @bt_coex_active: enable bt coex, default = true | 124 | * @bt_coex_active: enable bt coex, default = true |
127 | * @led_mode: system default, default = 0 | 125 | * @led_mode: system default, default = 0 |
128 | * @no_sleep_autoadjust: disable autoadjust, default = true | ||
129 | * @power_save: disable power save, default = false | 126 | * @power_save: disable power save, default = false |
130 | * @power_level: power level, default = 1 | 127 | * @power_level: power level, default = 1 |
131 | * @debug_level: levels are IWL_DL_* | 128 | * @debug_level: levels are IWL_DL_* |
132 | * @ant_coupling: antenna coupling in dB, default = 0 | 129 | * @ant_coupling: antenna coupling in dB, default = 0 |
133 | * @bt_ch_announce: BT channel inhibition, default = enable | 130 | * @bt_ch_announce: BT channel inhibition, default = enable |
134 | * @wanted_ucode_alternative: ucode alternative to use, default = 1 | ||
135 | * @auto_agg: enable agg. without check, default = true | 131 | * @auto_agg: enable agg. without check, default = true |
136 | */ | 132 | */ |
137 | struct iwl_mod_params { | 133 | struct iwl_mod_params { |
138 | int sw_crypto; | 134 | int sw_crypto; |
139 | unsigned int disable_11n; | 135 | unsigned int disable_11n; |
140 | int amsdu_size_8K; | 136 | int amsdu_size_8K; |
141 | int antenna; | ||
142 | int restart_fw; | 137 | int restart_fw; |
143 | bool plcp_check; | 138 | bool plcp_check; |
144 | bool ack_check; | ||
145 | int wd_disable; | 139 | int wd_disable; |
146 | bool bt_coex_active; | 140 | bool bt_coex_active; |
147 | int led_mode; | 141 | int led_mode; |
148 | bool no_sleep_autoadjust; | ||
149 | bool power_save; | 142 | bool power_save; |
150 | int power_level; | 143 | int power_level; |
151 | u32 debug_level; | 144 | u32 debug_level; |
152 | int ant_coupling; | 145 | int ant_coupling; |
153 | bool bt_ch_announce; | 146 | bool bt_ch_announce; |
154 | int wanted_ucode_alternative; | ||
155 | bool auto_agg; | 147 | bool auto_agg; |
156 | }; | 148 | }; |
157 | 149 | ||
158 | /** | 150 | /** |
159 | * struct iwl_hw_params | ||
160 | * | ||
161 | * Holds the module parameters | ||
162 | * | ||
163 | * @tx_chains_num: Number of TX chains | ||
164 | * @rx_chains_num: Number of RX chains | ||
165 | * @valid_tx_ant: usable antennas for TX | ||
166 | * @valid_rx_ant: usable antennas for RX | ||
167 | * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) | ||
168 | * @sku: sku read from EEPROM | ||
169 | * @rx_page_order: Rx buffer page order | ||
170 | * @ct_kill_threshold: temperature threshold - in hw dependent unit | ||
171 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | ||
172 | * relevant for 1000, 6000 and up | ||
173 | * @wd_timeout: TX queues watchdog timeout | ||
174 | * @struct iwl_sensitivity_ranges: range of sensitivity values | ||
175 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
176 | */ | ||
177 | struct iwl_hw_params { | ||
178 | u8 tx_chains_num; | ||
179 | u8 rx_chains_num; | ||
180 | u8 valid_tx_ant; | ||
181 | u8 valid_rx_ant; | ||
182 | u8 ht40_channel; | ||
183 | bool use_rts_for_aggregation; | ||
184 | u16 sku; | ||
185 | u32 rx_page_order; | ||
186 | u32 ct_kill_threshold; | ||
187 | u32 ct_kill_exit_threshold; | ||
188 | unsigned int wd_timeout; | ||
189 | |||
190 | const struct iwl_sensitivity_ranges *sens; | ||
191 | }; | ||
192 | |||
193 | /* | ||
194 | * LED mode | ||
195 | * IWL_LED_DEFAULT: use device default | ||
196 | * IWL_LED_RF_STATE: turn LED on/off based on RF state | ||
197 | * LED ON = RF ON | ||
198 | * LED OFF = RF OFF | ||
199 | * IWL_LED_BLINK: adjust led blink rate based on blink table | ||
200 | * IWL_LED_DISABLE: led disabled | ||
201 | */ | ||
202 | enum iwl_led_mode { | ||
203 | IWL_LED_DEFAULT, | ||
204 | IWL_LED_RF_STATE, | ||
205 | IWL_LED_BLINK, | ||
206 | IWL_LED_DISABLE, | ||
207 | }; | ||
208 | |||
209 | /* | ||
210 | * @max_ll_items: max number of OTP blocks | ||
211 | * @shadow_ram_support: shadow support for OTP memory | ||
212 | * @led_compensation: compensate on the led on/off time per HW according | ||
213 | * to the deviation to achieve the desired led frequency. | ||
214 | * The detail algorithm is described in iwl-led.c | ||
215 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | ||
216 | * @adv_thermal_throttle: support advance thermal throttle | ||
217 | * @support_ct_kill_exit: support ct kill exit condition | ||
218 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
219 | * radio tuning when there is a high receiving plcp error rate | ||
220 | * @chain_noise_scale: default chain noise scale used for gain computation | ||
221 | * @wd_timeout: TX queues watchdog timeout | ||
222 | * @max_event_log_size: size of event log buffer size for ucode event logging | ||
223 | * @shadow_reg_enable: HW shadhow register bit | ||
224 | * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up | ||
225 | * @no_idle_support: do not support idle mode | ||
226 | * wd_disable: disable watchdog timer | ||
227 | */ | ||
228 | struct iwl_base_params { | ||
229 | int eeprom_size; | ||
230 | int num_of_queues; /* def: HW dependent */ | ||
231 | /* for iwl_apm_init() */ | ||
232 | u32 pll_cfg_val; | ||
233 | |||
234 | const u16 max_ll_items; | ||
235 | const bool shadow_ram_support; | ||
236 | u16 led_compensation; | ||
237 | bool adv_thermal_throttle; | ||
238 | bool support_ct_kill_exit; | ||
239 | u8 plcp_delta_threshold; | ||
240 | s32 chain_noise_scale; | ||
241 | unsigned int wd_timeout; | ||
242 | u32 max_event_log_size; | ||
243 | const bool shadow_reg_enable; | ||
244 | const bool hd_v2; | ||
245 | const bool no_idle_support; | ||
246 | const bool wd_disable; | ||
247 | }; | ||
248 | |||
249 | /* | ||
250 | * @advanced_bt_coexist: support advanced bt coexist | ||
251 | * @bt_init_traffic_load: specify initial bt traffic load | ||
252 | * @bt_prio_boost: default bt priority boost value | ||
253 | * @agg_time_limit: maximum number of uSec in aggregation | ||
254 | * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode | ||
255 | */ | ||
256 | struct iwl_bt_params { | ||
257 | bool advanced_bt_coexist; | ||
258 | u8 bt_init_traffic_load; | ||
259 | u8 bt_prio_boost; | ||
260 | u16 agg_time_limit; | ||
261 | bool bt_sco_disable; | ||
262 | bool bt_session_2; | ||
263 | }; | ||
264 | /* | ||
265 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||
266 | */ | ||
267 | struct iwl_ht_params { | ||
268 | const bool ht_greenfield_support; /* if used set to true */ | ||
269 | bool use_rts_for_aggregation; | ||
270 | enum ieee80211_smps_mode smps_mode; | ||
271 | }; | ||
272 | |||
273 | /** | ||
274 | * struct iwl_cfg | ||
275 | * @name: Offical name of the device | ||
276 | * @fw_name_pre: Firmware filename prefix. The api version and extension | ||
277 | * (.ucode) will be added to filename before loading from disk. The | ||
278 | * filename is constructed as fw_name_pre<api>.ucode. | ||
279 | * @ucode_api_max: Highest version of uCode API supported by driver. | ||
280 | * @ucode_api_ok: oldest version of the uCode API that is OK to load | ||
281 | * without a warning, for use in transitions | ||
282 | * @ucode_api_min: Lowest version of uCode API supported by driver. | ||
283 | * @max_inst_size: The maximal length of the fw inst section | ||
284 | * @max_data_size: The maximal length of the fw data section | ||
285 | * @valid_tx_ant: valid transmit antenna | ||
286 | * @valid_rx_ant: valid receive antenna | ||
287 | * @eeprom_ver: EEPROM version | ||
288 | * @eeprom_calib_ver: EEPROM calibration version | ||
289 | * @lib: pointer to the lib ops | ||
290 | * @additional_nic_config: additional nic configuration | ||
291 | * @base_params: pointer to basic parameters | ||
292 | * @ht_params: point to ht patameters | ||
293 | * @bt_params: pointer to bt parameters | ||
294 | * @need_temp_offset_calib: need to perform temperature offset calibration | ||
295 | * @no_xtal_calib: some devices do not need crystal calibration data, | ||
296 | * don't send it to those | ||
297 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) | ||
298 | * @adv_pm: advance power management | ||
299 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | ||
300 | * @internal_wimax_coex: internal wifi/wimax combo device | ||
301 | * @temp_offset_v2: support v2 of temperature offset calibration | ||
302 | * | ||
303 | * We enable the driver to be backward compatible wrt. hardware features. | ||
304 | * API differences in uCode shouldn't be handled here but through TLVs | ||
305 | * and/or the uCode API version instead. | ||
306 | */ | ||
307 | struct iwl_cfg { | ||
308 | /* params specific to an individual device within a device family */ | ||
309 | const char *name; | ||
310 | const char *fw_name_pre; | ||
311 | const unsigned int ucode_api_max; | ||
312 | const unsigned int ucode_api_ok; | ||
313 | const unsigned int ucode_api_min; | ||
314 | const u32 max_data_size; | ||
315 | const u32 max_inst_size; | ||
316 | u8 valid_tx_ant; | ||
317 | u8 valid_rx_ant; | ||
318 | u16 eeprom_ver; | ||
319 | u16 eeprom_calib_ver; | ||
320 | const struct iwl_lib_ops *lib; | ||
321 | void (*additional_nic_config)(struct iwl_priv *priv); | ||
322 | /* params not likely to change within a device family */ | ||
323 | const struct iwl_base_params *base_params; | ||
324 | /* params likely to change within a device family */ | ||
325 | const struct iwl_ht_params *ht_params; | ||
326 | const struct iwl_bt_params *bt_params; | ||
327 | const bool need_temp_offset_calib; /* if used set to true */ | ||
328 | const bool no_xtal_calib; | ||
329 | enum iwl_led_mode led_mode; | ||
330 | const bool adv_pm; | ||
331 | const bool rx_with_siso_diversity; | ||
332 | const bool internal_wimax_coex; | ||
333 | const bool temp_offset_v2; | ||
334 | }; | ||
335 | |||
336 | /** | ||
337 | * struct iwl_shared - shared fields for all the layers of the driver | 151 | * struct iwl_shared - shared fields for all the layers of the driver |
338 | * | 152 | * |
339 | * @status: STATUS_* | ||
340 | * @wowlan: are we running wowlan uCode | 153 | * @wowlan: are we running wowlan uCode |
341 | * @bus: pointer to the bus layer data | 154 | * @bus: pointer to the bus layer data |
342 | * @cfg: see struct iwl_cfg | 155 | * @cfg: see struct iwl_cfg |
343 | * @priv: pointer to the upper layer data | 156 | * @priv: pointer to the upper layer data |
344 | * @trans: pointer to the transport layer data | 157 | * @trans: pointer to the transport layer data |
345 | * @nic: pointer to the nic data | 158 | * @nic: pointer to the nic data |
346 | * @hw_params: see struct iwl_hw_params | ||
347 | * @lock: protect general shared data | 159 | * @lock: protect general shared data |
348 | * @eeprom: pointer to the eeprom/OTP image | 160 | * @eeprom: pointer to the eeprom/OTP image |
349 | */ | 161 | */ |
350 | struct iwl_shared { | 162 | struct iwl_shared { |
351 | unsigned long status; | ||
352 | |||
353 | const struct iwl_cfg *cfg; | 163 | const struct iwl_cfg *cfg; |
354 | struct iwl_trans *trans; | 164 | struct iwl_trans *trans; |
355 | void *drv; | 165 | void *drv; |
356 | struct iwl_hw_params hw_params; | ||
357 | |||
358 | /* eeprom -- this is in the card's little endian byte order */ | ||
359 | u8 *eeprom; | ||
360 | |||
361 | }; | 166 | }; |
362 | 167 | ||
363 | /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ | 168 | /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ |
364 | #define cfg(_m) ((_m)->shrd->cfg) | 169 | #define cfg(_m) ((_m)->shrd->cfg) |
365 | #define trans(_m) ((_m)->shrd->trans) | 170 | #define trans(_m) ((_m)->shrd->trans) |
366 | #define hw_params(_m) ((_m)->shrd->hw_params) | ||
367 | 171 | ||
368 | static inline bool iwl_have_debug_level(u32 level) | 172 | static inline bool iwl_have_debug_level(u32 level) |
369 | { | 173 | { |
@@ -377,33 +181,4 @@ enum iwl_rxon_context_id { | |||
377 | NUM_IWL_RXON_CTX | 181 | NUM_IWL_RXON_CTX |
378 | }; | 182 | }; |
379 | 183 | ||
380 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | ||
381 | const char *get_cmd_string(u8 cmd); | ||
382 | |||
383 | #define IWL_CMD(x) case x: return #x | ||
384 | |||
385 | /***************************************************** | ||
386 | * DRIVER STATUS FUNCTIONS | ||
387 | ******************************************************/ | ||
388 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | ||
389 | /* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ | ||
390 | #define STATUS_INT_ENABLED 2 | ||
391 | #define STATUS_RF_KILL_HW 3 | ||
392 | #define STATUS_CT_KILL 4 | ||
393 | #define STATUS_INIT 5 | ||
394 | #define STATUS_ALIVE 6 | ||
395 | #define STATUS_READY 7 | ||
396 | #define STATUS_TEMPERATURE 8 | ||
397 | #define STATUS_GEO_CONFIGURED 9 | ||
398 | #define STATUS_EXIT_PENDING 10 | ||
399 | #define STATUS_STATISTICS 12 | ||
400 | #define STATUS_SCANNING 13 | ||
401 | #define STATUS_SCAN_ABORTING 14 | ||
402 | #define STATUS_SCAN_HW 15 | ||
403 | #define STATUS_POWER_PMI 16 | ||
404 | #define STATUS_FW_ERROR 17 | ||
405 | #define STATUS_DEVICE_ENABLED 18 | ||
406 | #define STATUS_CHANNEL_SWITCH_PENDING 19 | ||
407 | #define STATUS_SCAN_COMPLETE 20 | ||
408 | |||
409 | #endif /* #__iwl_shared_h__ */ | 184 | #endif /* #__iwl_shared_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index f31a0629c6c6..bb275098bb10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -536,7 +536,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
536 | break; | 536 | break; |
537 | 537 | ||
538 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 538 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: |
539 | if (priv->shrd->eeprom) { | 539 | if (priv->eeprom) { |
540 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | 540 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, |
541 | cfg(priv)->base_params->eeprom_size + 20); | 541 | cfg(priv)->base_params->eeprom_size + 20); |
542 | if (!skb) { | 542 | if (!skb) { |
@@ -547,7 +547,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
547 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | 547 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || |
548 | nla_put(skb, IWL_TM_ATTR_EEPROM, | 548 | nla_put(skb, IWL_TM_ATTR_EEPROM, |
549 | cfg(priv)->base_params->eeprom_size, | 549 | cfg(priv)->base_params->eeprom_size, |
550 | priv->shrd->eeprom)) | 550 | priv->eeprom)) |
551 | goto nla_put_failure; | 551 | goto nla_put_failure; |
552 | status = cfg80211_testmode_reply(skb); | 552 | status = cfg80211_testmode_reply(skb); |
553 | if (status < 0) | 553 | if (status < 0) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 32adee3b54e3..70bdd0e2df38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/wait.h> | 35 | #include <linux/wait.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/timer.h> | ||
37 | 38 | ||
38 | #include "iwl-fh.h" | 39 | #include "iwl-fh.h" |
39 | #include "iwl-csr.h" | 40 | #include "iwl-csr.h" |
@@ -43,8 +44,6 @@ | |||
43 | #include "iwl-io.h" | 44 | #include "iwl-io.h" |
44 | #include "iwl-op-mode.h" | 45 | #include "iwl-op-mode.h" |
45 | 46 | ||
46 | struct iwl_tx_queue; | ||
47 | struct iwl_queue; | ||
48 | struct iwl_host_cmd; | 47 | struct iwl_host_cmd; |
49 | 48 | ||
50 | /*This file includes the declaration that are internal to the | 49 | /*This file includes the declaration that are internal to the |
@@ -140,10 +139,10 @@ struct iwl_cmd_meta { | |||
140 | /* only for SYNC commands, iff the reply skb is wanted */ | 139 | /* only for SYNC commands, iff the reply skb is wanted */ |
141 | struct iwl_host_cmd *source; | 140 | struct iwl_host_cmd *source; |
142 | 141 | ||
143 | u32 flags; | ||
144 | |||
145 | DEFINE_DMA_UNMAP_ADDR(mapping); | 142 | DEFINE_DMA_UNMAP_ADDR(mapping); |
146 | DEFINE_DMA_UNMAP_LEN(len); | 143 | DEFINE_DMA_UNMAP_LEN(len); |
144 | |||
145 | u32 flags; | ||
147 | }; | 146 | }; |
148 | 147 | ||
149 | /* | 148 | /* |
@@ -206,7 +205,8 @@ struct iwl_tx_queue { | |||
206 | struct iwl_cmd_meta *meta; | 205 | struct iwl_cmd_meta *meta; |
207 | struct sk_buff **skbs; | 206 | struct sk_buff **skbs; |
208 | spinlock_t lock; | 207 | spinlock_t lock; |
209 | unsigned long time_stamp; | 208 | struct timer_list stuck_timer; |
209 | struct iwl_trans_pcie *trans_pcie; | ||
210 | u8 need_update; | 210 | u8 need_update; |
211 | u8 active; | 211 | u8 active; |
212 | }; | 212 | }; |
@@ -227,6 +227,9 @@ struct iwl_tx_queue { | |||
227 | * @ucode_write_waitq: wait queue for uCode load | 227 | * @ucode_write_waitq: wait queue for uCode load |
228 | * @status - transport specific status flags | 228 | * @status - transport specific status flags |
229 | * @cmd_queue - command queue number | 229 | * @cmd_queue - command queue number |
230 | * @rx_buf_size_8k: 8 kB RX buffer size | ||
231 | * @rx_page_order: page order for receive buffer size | ||
232 | * @wd_timeout: queue watchdog timeout (jiffies) | ||
230 | */ | 233 | */ |
231 | struct iwl_trans_pcie { | 234 | struct iwl_trans_pcie { |
232 | struct iwl_rx_queue rxq; | 235 | struct iwl_rx_queue rxq; |
@@ -266,11 +269,34 @@ struct iwl_trans_pcie { | |||
266 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | 269 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; |
267 | u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES]; | 270 | u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES]; |
268 | u8 n_q_to_fifo; | 271 | u8 n_q_to_fifo; |
272 | |||
273 | bool rx_buf_size_8k; | ||
274 | u32 rx_page_order; | ||
275 | |||
276 | const char **command_names; | ||
277 | |||
278 | /* queue watchdog */ | ||
279 | unsigned long wd_timeout; | ||
269 | }; | 280 | }; |
270 | 281 | ||
282 | /***************************************************** | ||
283 | * DRIVER STATUS FUNCTIONS | ||
284 | ******************************************************/ | ||
285 | #define STATUS_HCMD_ACTIVE 0 | ||
286 | #define STATUS_DEVICE_ENABLED 1 | ||
287 | #define STATUS_TPOWER_PMI 2 | ||
288 | #define STATUS_INT_ENABLED 3 | ||
289 | |||
271 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 290 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
272 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) | 291 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) |
273 | 292 | ||
293 | static inline struct iwl_trans * | ||
294 | iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie) | ||
295 | { | ||
296 | return container_of((void *)trans_pcie, struct iwl_trans, | ||
297 | trans_specific); | ||
298 | } | ||
299 | |||
274 | /***************************************************** | 300 | /***************************************************** |
275 | * RX | 301 | * RX |
276 | ******************************************************/ | 302 | ******************************************************/ |
@@ -392,4 +418,12 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) | |||
392 | return index & (q->n_window - 1); | 418 | return index & (q->n_window - 1); |
393 | } | 419 | } |
394 | 420 | ||
421 | static inline const char * | ||
422 | trans_pcie_get_cmd_string(struct iwl_trans_pcie *trans_pcie, u8 cmd) | ||
423 | { | ||
424 | if (!trans_pcie->command_names || !trans_pcie->command_names[cmd]) | ||
425 | return "UNKNOWN"; | ||
426 | return trans_pcie->command_names[cmd]; | ||
427 | } | ||
428 | |||
395 | #endif /* __iwl_trans_int_pcie_h__ */ | 429 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index ab0f3fc22b87..de78fb8dca9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -150,7 +150,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
150 | IWL_TRANS_GET_PCIE_TRANS(trans); | 150 | IWL_TRANS_GET_PCIE_TRANS(trans); |
151 | 151 | ||
152 | /* If power-saving is in use, make sure device is awake */ | 152 | /* If power-saving is in use, make sure device is awake */ |
153 | if (test_bit(STATUS_POWER_PMI, &trans_pcie->status)) { | 153 | if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) { |
154 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); | 154 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
155 | 155 | ||
156 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 156 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
@@ -274,17 +274,17 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
274 | if (rxq->free_count > RX_LOW_WATERMARK) | 274 | if (rxq->free_count > RX_LOW_WATERMARK) |
275 | gfp_mask |= __GFP_NOWARN; | 275 | gfp_mask |= __GFP_NOWARN; |
276 | 276 | ||
277 | if (hw_params(trans).rx_page_order > 0) | 277 | if (trans_pcie->rx_page_order > 0) |
278 | gfp_mask |= __GFP_COMP; | 278 | gfp_mask |= __GFP_COMP; |
279 | 279 | ||
280 | /* Alloc a new receive buffer */ | 280 | /* Alloc a new receive buffer */ |
281 | page = alloc_pages(gfp_mask, | 281 | page = alloc_pages(gfp_mask, |
282 | hw_params(trans).rx_page_order); | 282 | trans_pcie->rx_page_order); |
283 | if (!page) { | 283 | if (!page) { |
284 | if (net_ratelimit()) | 284 | if (net_ratelimit()) |
285 | IWL_DEBUG_INFO(trans, "alloc_pages failed, " | 285 | IWL_DEBUG_INFO(trans, "alloc_pages failed, " |
286 | "order: %d\n", | 286 | "order: %d\n", |
287 | hw_params(trans).rx_page_order); | 287 | trans_pcie->rx_page_order); |
288 | 288 | ||
289 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | 289 | if ((rxq->free_count <= RX_LOW_WATERMARK) && |
290 | net_ratelimit()) | 290 | net_ratelimit()) |
@@ -303,7 +303,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
303 | 303 | ||
304 | if (list_empty(&rxq->rx_used)) { | 304 | if (list_empty(&rxq->rx_used)) { |
305 | spin_unlock_irqrestore(&rxq->lock, flags); | 305 | spin_unlock_irqrestore(&rxq->lock, flags); |
306 | __free_pages(page, hw_params(trans).rx_page_order); | 306 | __free_pages(page, trans_pcie->rx_page_order); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | element = rxq->rx_used.next; | 309 | element = rxq->rx_used.next; |
@@ -316,7 +316,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
316 | rxb->page = page; | 316 | rxb->page = page; |
317 | /* Get physical address of the RB */ | 317 | /* Get physical address of the RB */ |
318 | rxb->page_dma = dma_map_page(trans->dev, page, 0, | 318 | rxb->page_dma = dma_map_page(trans->dev, page, 0, |
319 | PAGE_SIZE << hw_params(trans).rx_page_order, | 319 | PAGE_SIZE << trans_pcie->rx_page_order, |
320 | DMA_FROM_DEVICE); | 320 | DMA_FROM_DEVICE); |
321 | /* dma address must be no more than 36 bits */ | 321 | /* dma address must be no more than 36 bits */ |
322 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | 322 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); |
@@ -367,7 +367,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
367 | struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; | 367 | struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; |
368 | unsigned long flags; | 368 | unsigned long flags; |
369 | bool page_stolen = false; | 369 | bool page_stolen = false; |
370 | int max_len = PAGE_SIZE << hw_params(trans).rx_page_order; | 370 | int max_len = PAGE_SIZE << trans_pcie->rx_page_order; |
371 | u32 offset = 0; | 371 | u32 offset = 0; |
372 | 372 | ||
373 | if (WARN_ON(!rxb)) | 373 | if (WARN_ON(!rxb)) |
@@ -393,8 +393,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
393 | break; | 393 | break; |
394 | 394 | ||
395 | IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n", | 395 | IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n", |
396 | rxcb._offset, get_cmd_string(pkt->hdr.cmd), | 396 | rxcb._offset, |
397 | pkt->hdr.cmd); | 397 | trans_pcie_get_cmd_string(trans_pcie, pkt->hdr.cmd), |
398 | pkt->hdr.cmd); | ||
398 | 399 | ||
399 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 400 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
400 | len += sizeof(u32); /* account for status word */ | 401 | len += sizeof(u32); /* account for status word */ |
@@ -452,7 +453,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
452 | 453 | ||
453 | /* page was stolen from us -- free our reference */ | 454 | /* page was stolen from us -- free our reference */ |
454 | if (page_stolen) { | 455 | if (page_stolen) { |
455 | __free_pages(rxb->page, hw_params(trans).rx_page_order); | 456 | __free_pages(rxb->page, trans_pcie->rx_page_order); |
456 | rxb->page = NULL; | 457 | rxb->page = NULL; |
457 | } | 458 | } |
458 | 459 | ||
@@ -463,7 +464,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
463 | if (rxb->page != NULL) { | 464 | if (rxb->page != NULL) { |
464 | rxb->page_dma = | 465 | rxb->page_dma = |
465 | dma_map_page(trans->dev, rxb->page, 0, | 466 | dma_map_page(trans->dev, rxb->page, 0, |
466 | PAGE_SIZE << hw_params(trans).rx_page_order, | 467 | PAGE_SIZE << trans_pcie->rx_page_order, |
467 | DMA_FROM_DEVICE); | 468 | DMA_FROM_DEVICE); |
468 | list_add_tail(&rxb->list, &rxq->rx_free); | 469 | list_add_tail(&rxb->list, &rxq->rx_free); |
469 | rxq->free_count++; | 470 | rxq->free_count++; |
@@ -547,14 +548,12 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
547 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 548 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
548 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & | 549 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & |
549 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 550 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
550 | /* | 551 | struct iwl_trans_pcie *trans_pcie; |
551 | * Keep the restart process from trying to send host | 552 | |
552 | * commands by clearing the ready bit. | 553 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
553 | */ | 554 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
554 | clear_bit(STATUS_READY, &trans->shrd->status); | 555 | iwl_op_mode_wimax_active(trans->op_mode); |
555 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | ||
556 | wake_up(&trans->wait_command_queue); | 556 | wake_up(&trans->wait_command_queue); |
557 | IWL_ERR(trans, "RF is used by WiMAX\n"); | ||
558 | return; | 557 | return; |
559 | } | 558 | } |
560 | 559 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 4684e2310cd8..918874067bd3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | |||
@@ -107,7 +107,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) | |||
107 | struct iwl_trans_pcie *trans_pcie = | 107 | struct iwl_trans_pcie *trans_pcie = |
108 | IWL_TRANS_GET_PCIE_TRANS(trans); | 108 | IWL_TRANS_GET_PCIE_TRANS(trans); |
109 | /* if we're trying to save power */ | 109 | /* if we're trying to save power */ |
110 | if (test_bit(STATUS_POWER_PMI, &trans_pcie->status)) { | 110 | if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) { |
111 | /* wake up nic if it's powered down ... | 111 | /* wake up nic if it's powered down ... |
112 | * uCode will wake up, and interrupt us again, so next | 112 | * uCode will wake up, and interrupt us again, so next |
113 | * time we'll skip this part. */ | 113 | * time we'll skip this part. */ |
@@ -605,12 +605,11 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
605 | cmd_dest += cmd->len[i]; | 605 | cmd_dest += cmd->len[i]; |
606 | } | 606 | } |
607 | 607 | ||
608 | IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, " | 608 | IWL_DEBUG_HC(trans, |
609 | "%d bytes at %d[%d]:%d\n", | 609 | "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", |
610 | get_cmd_string(out_cmd->hdr.cmd), | 610 | trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd), |
611 | out_cmd->hdr.cmd, | 611 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, |
612 | le16_to_cpu(out_cmd->hdr.sequence), cmd_size, | 612 | q->write_ptr, idx, trans_pcie->cmd_queue); |
613 | q->write_ptr, idx, trans_pcie->cmd_queue); | ||
614 | 613 | ||
615 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, | 614 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, |
616 | DMA_BIDIRECTIONAL); | 615 | DMA_BIDIRECTIONAL); |
@@ -668,6 +667,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
668 | trace_bufs[2], trace_lens[2]); | 667 | trace_bufs[2], trace_lens[2]); |
669 | #endif | 668 | #endif |
670 | 669 | ||
670 | /* start timer if queue currently empty */ | ||
671 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | ||
672 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | ||
673 | |||
671 | /* Increment and update queue's write index */ | 674 | /* Increment and update queue's write index */ |
672 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 675 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
673 | iwl_txq_update_write_ptr(trans, txq); | 676 | iwl_txq_update_write_ptr(trans, txq); |
@@ -677,6 +680,22 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
677 | return idx; | 680 | return idx; |
678 | } | 681 | } |
679 | 682 | ||
683 | static inline void iwl_queue_progress(struct iwl_trans_pcie *trans_pcie, | ||
684 | struct iwl_tx_queue *txq) | ||
685 | { | ||
686 | if (!trans_pcie->wd_timeout) | ||
687 | return; | ||
688 | |||
689 | /* | ||
690 | * if empty delete timer, otherwise move timer forward | ||
691 | * since we're making progress on this queue | ||
692 | */ | ||
693 | if (txq->q.read_ptr == txq->q.write_ptr) | ||
694 | del_timer(&txq->stuck_timer); | ||
695 | else | ||
696 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | ||
697 | } | ||
698 | |||
680 | /** | 699 | /** |
681 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd | 700 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd |
682 | * | 701 | * |
@@ -711,6 +730,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, | |||
711 | } | 730 | } |
712 | 731 | ||
713 | } | 732 | } |
733 | |||
734 | iwl_queue_progress(trans_pcie, txq); | ||
714 | } | 735 | } |
715 | 736 | ||
716 | /** | 737 | /** |
@@ -754,8 +775,6 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
754 | cmd = txq->cmd[cmd_index]; | 775 | cmd = txq->cmd[cmd_index]; |
755 | meta = &txq->meta[cmd_index]; | 776 | meta = &txq->meta[cmd_index]; |
756 | 777 | ||
757 | txq->time_stamp = jiffies; | ||
758 | |||
759 | iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], | 778 | iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], |
760 | DMA_BIDIRECTIONAL); | 779 | DMA_BIDIRECTIONAL); |
761 | 780 | ||
@@ -765,21 +784,23 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
765 | 784 | ||
766 | meta->source->resp_pkt = pkt; | 785 | meta->source->resp_pkt = pkt; |
767 | meta->source->_rx_page_addr = (unsigned long)page_address(p); | 786 | meta->source->_rx_page_addr = (unsigned long)page_address(p); |
768 | meta->source->_rx_page_order = hw_params(trans).rx_page_order; | 787 | meta->source->_rx_page_order = trans_pcie->rx_page_order; |
769 | meta->source->handler_status = handler_status; | 788 | meta->source->handler_status = handler_status; |
770 | } | 789 | } |
771 | 790 | ||
772 | iwl_hcmd_queue_reclaim(trans, txq_id, index); | 791 | iwl_hcmd_queue_reclaim(trans, txq_id, index); |
773 | 792 | ||
774 | if (!(meta->flags & CMD_ASYNC)) { | 793 | if (!(meta->flags & CMD_ASYNC)) { |
775 | if (!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { | 794 | if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { |
776 | IWL_WARN(trans, | 795 | IWL_WARN(trans, |
777 | "HCMD_ACTIVE already clear for command %s\n", | 796 | "HCMD_ACTIVE already clear for command %s\n", |
778 | get_cmd_string(cmd->hdr.cmd)); | 797 | trans_pcie_get_cmd_string(trans_pcie, |
798 | cmd->hdr.cmd)); | ||
779 | } | 799 | } |
780 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | 800 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
781 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", | 801 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", |
782 | get_cmd_string(cmd->hdr.cmd)); | 802 | trans_pcie_get_cmd_string(trans_pcie, |
803 | cmd->hdr.cmd)); | ||
783 | wake_up(&trans->wait_command_queue); | 804 | wake_up(&trans->wait_command_queue); |
784 | } | 805 | } |
785 | 806 | ||
@@ -792,6 +813,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, | |||
792 | 813 | ||
793 | static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | 814 | static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) |
794 | { | 815 | { |
816 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
795 | int ret; | 817 | int ret; |
796 | 818 | ||
797 | /* An asynchronous command can not expect an SKB to be set. */ | 819 | /* An asynchronous command can not expect an SKB to be set. */ |
@@ -803,7 +825,7 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
803 | if (ret < 0) { | 825 | if (ret < 0) { |
804 | IWL_ERR(trans, | 826 | IWL_ERR(trans, |
805 | "Error sending %s: enqueue_hcmd failed: %d\n", | 827 | "Error sending %s: enqueue_hcmd failed: %d\n", |
806 | get_cmd_string(cmd->id), ret); | 828 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret); |
807 | return ret; | 829 | return ret; |
808 | } | 830 | } |
809 | return 0; | 831 | return 0; |
@@ -816,49 +838,51 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
816 | int ret; | 838 | int ret; |
817 | 839 | ||
818 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 840 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
819 | get_cmd_string(cmd->id)); | 841 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); |
820 | 842 | ||
821 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, | 843 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, |
822 | &trans->shrd->status))) { | 844 | &trans_pcie->status))) { |
823 | IWL_ERR(trans, "Command %s: a command is already active!\n", | 845 | IWL_ERR(trans, "Command %s: a command is already active!\n", |
824 | get_cmd_string(cmd->id)); | 846 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); |
825 | return -EIO; | 847 | return -EIO; |
826 | } | 848 | } |
827 | 849 | ||
828 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", | 850 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", |
829 | get_cmd_string(cmd->id)); | 851 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); |
830 | 852 | ||
831 | cmd_idx = iwl_enqueue_hcmd(trans, cmd); | 853 | cmd_idx = iwl_enqueue_hcmd(trans, cmd); |
832 | if (cmd_idx < 0) { | 854 | if (cmd_idx < 0) { |
833 | ret = cmd_idx; | 855 | ret = cmd_idx; |
834 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | 856 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
835 | IWL_ERR(trans, | 857 | IWL_ERR(trans, |
836 | "Error sending %s: enqueue_hcmd failed: %d\n", | 858 | "Error sending %s: enqueue_hcmd failed: %d\n", |
837 | get_cmd_string(cmd->id), ret); | 859 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret); |
838 | return ret; | 860 | return ret; |
839 | } | 861 | } |
840 | 862 | ||
841 | ret = wait_event_timeout(trans->wait_command_queue, | 863 | ret = wait_event_timeout(trans->wait_command_queue, |
842 | !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), | 864 | !test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status), |
843 | HOST_COMPLETE_TIMEOUT); | 865 | HOST_COMPLETE_TIMEOUT); |
844 | if (!ret) { | 866 | if (!ret) { |
845 | if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { | 867 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { |
846 | struct iwl_tx_queue *txq = | 868 | struct iwl_tx_queue *txq = |
847 | &trans_pcie->txq[trans_pcie->cmd_queue]; | 869 | &trans_pcie->txq[trans_pcie->cmd_queue]; |
848 | struct iwl_queue *q = &txq->q; | 870 | struct iwl_queue *q = &txq->q; |
849 | 871 | ||
850 | IWL_ERR(trans, | 872 | IWL_ERR(trans, |
851 | "Error sending %s: time out after %dms.\n", | 873 | "Error sending %s: time out after %dms.\n", |
852 | get_cmd_string(cmd->id), | 874 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), |
853 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 875 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
854 | 876 | ||
855 | IWL_ERR(trans, | 877 | IWL_ERR(trans, |
856 | "Current CMD queue read_ptr %d write_ptr %d\n", | 878 | "Current CMD queue read_ptr %d write_ptr %d\n", |
857 | q->read_ptr, q->write_ptr); | 879 | q->read_ptr, q->write_ptr); |
858 | 880 | ||
859 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | 881 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); |
860 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command" | 882 | IWL_DEBUG_INFO(trans, |
861 | "%s\n", get_cmd_string(cmd->id)); | 883 | "Clearing HCMD_ACTIVE for command %s\n", |
884 | trans_pcie_get_cmd_string(trans_pcie, | ||
885 | cmd->id)); | ||
862 | ret = -ETIMEDOUT; | 886 | ret = -ETIMEDOUT; |
863 | goto cancel; | 887 | goto cancel; |
864 | } | 888 | } |
@@ -866,7 +890,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
866 | 890 | ||
867 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { | 891 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { |
868 | IWL_ERR(trans, "Error: Response NULL in '%s'\n", | 892 | IWL_ERR(trans, "Error: Response NULL in '%s'\n", |
869 | get_cmd_string(cmd->id)); | 893 | trans_pcie_get_cmd_string(trans_pcie, cmd->id)); |
870 | ret = -EIO; | 894 | ret = -EIO; |
871 | goto cancel; | 895 | goto cancel; |
872 | } | 896 | } |
@@ -949,5 +973,8 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | |||
949 | iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE); | 973 | iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE); |
950 | freed++; | 974 | freed++; |
951 | } | 975 | } |
976 | |||
977 | iwl_queue_progress(trans_pcie, txq); | ||
978 | |||
952 | return freed; | 979 | return freed; |
953 | } | 980 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 9f62283504e3..14a32c420fd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -132,10 +132,10 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | |||
132 | * to an SKB, so we need to unmap and free potential storage */ | 132 | * to an SKB, so we need to unmap and free potential storage */ |
133 | if (rxq->pool[i].page != NULL) { | 133 | if (rxq->pool[i].page != NULL) { |
134 | dma_unmap_page(trans->dev, rxq->pool[i].page_dma, | 134 | dma_unmap_page(trans->dev, rxq->pool[i].page_dma, |
135 | PAGE_SIZE << hw_params(trans).rx_page_order, | 135 | PAGE_SIZE << trans_pcie->rx_page_order, |
136 | DMA_FROM_DEVICE); | 136 | DMA_FROM_DEVICE); |
137 | __free_pages(rxq->pool[i].page, | 137 | __free_pages(rxq->pool[i].page, |
138 | hw_params(trans).rx_page_order); | 138 | trans_pcie->rx_page_order); |
139 | rxq->pool[i].page = NULL; | 139 | rxq->pool[i].page = NULL; |
140 | } | 140 | } |
141 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 141 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
@@ -145,11 +145,12 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | |||
145 | static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | 145 | static void iwl_trans_rx_hw_init(struct iwl_trans *trans, |
146 | struct iwl_rx_queue *rxq) | 146 | struct iwl_rx_queue *rxq) |
147 | { | 147 | { |
148 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
148 | u32 rb_size; | 149 | u32 rb_size; |
149 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | 150 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ |
150 | u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */ | 151 | u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */ |
151 | 152 | ||
152 | if (iwlagn_mod_params.amsdu_size_8K) | 153 | if (trans_pcie->rx_buf_size_8k) |
153 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | 154 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; |
154 | else | 155 | else |
155 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | 156 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; |
@@ -298,6 +299,33 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, | |||
298 | memset(ptr, 0, sizeof(*ptr)); | 299 | memset(ptr, 0, sizeof(*ptr)); |
299 | } | 300 | } |
300 | 301 | ||
302 | static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) | ||
303 | { | ||
304 | struct iwl_tx_queue *txq = (void *)data; | ||
305 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; | ||
306 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); | ||
307 | |||
308 | spin_lock(&txq->lock); | ||
309 | /* check if triggered erroneously */ | ||
310 | if (txq->q.read_ptr == txq->q.write_ptr) { | ||
311 | spin_unlock(&txq->lock); | ||
312 | return; | ||
313 | } | ||
314 | spin_unlock(&txq->lock); | ||
315 | |||
316 | |||
317 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, | ||
318 | jiffies_to_msecs(trans_pcie->wd_timeout)); | ||
319 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | ||
320 | txq->q.read_ptr, txq->q.write_ptr); | ||
321 | IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", | ||
322 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq->q.id)) | ||
323 | & (TFD_QUEUE_SIZE_MAX - 1), | ||
324 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq->q.id))); | ||
325 | |||
326 | iwl_op_mode_nic_error(trans->op_mode); | ||
327 | } | ||
328 | |||
301 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, | 329 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, |
302 | struct iwl_tx_queue *txq, int slots_num, | 330 | struct iwl_tx_queue *txq, int slots_num, |
303 | u32 txq_id) | 331 | u32 txq_id) |
@@ -309,6 +337,10 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, | |||
309 | if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) | 337 | if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) |
310 | return -EINVAL; | 338 | return -EINVAL; |
311 | 339 | ||
340 | setup_timer(&txq->stuck_timer, iwl_trans_pcie_queue_stuck_timer, | ||
341 | (unsigned long)txq); | ||
342 | txq->trans_pcie = trans_pcie; | ||
343 | |||
312 | txq->q.n_window = slots_num; | 344 | txq->q.n_window = slots_num; |
313 | 345 | ||
314 | txq->meta = kcalloc(slots_num, sizeof(txq->meta[0]), GFP_KERNEL); | 346 | txq->meta = kcalloc(slots_num, sizeof(txq->meta[0]), GFP_KERNEL); |
@@ -471,6 +503,8 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | |||
471 | txq->cmd = NULL; | 503 | txq->cmd = NULL; |
472 | txq->meta = NULL; | 504 | txq->meta = NULL; |
473 | 505 | ||
506 | del_timer_sync(&txq->stuck_timer); | ||
507 | |||
474 | /* 0-fill queue descriptor structure */ | 508 | /* 0-fill queue descriptor structure */ |
475 | memset(txq, 0, sizeof(*txq)); | 509 | memset(txq, 0, sizeof(*txq)); |
476 | } | 510 | } |
@@ -1214,6 +1248,12 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1214 | 1248 | ||
1215 | /* stop and reset the on-board processor */ | 1249 | /* stop and reset the on-board processor */ |
1216 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 1250 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
1251 | |||
1252 | /* clear all status bits */ | ||
1253 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | ||
1254 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); | ||
1255 | clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | ||
1256 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); | ||
1217 | } | 1257 | } |
1218 | 1258 | ||
1219 | static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) | 1259 | static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) |
@@ -1346,6 +1386,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1346 | &dev_cmd->hdr, firstlen, | 1386 | &dev_cmd->hdr, firstlen, |
1347 | skb->data + hdr_len, secondlen); | 1387 | skb->data + hdr_len, secondlen); |
1348 | 1388 | ||
1389 | /* start timer if queue currently empty */ | ||
1390 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | ||
1391 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | ||
1392 | |||
1349 | /* Tell device the write index *just past* this latest filled TFD */ | 1393 | /* Tell device the write index *just past* this latest filled TFD */ |
1350 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1394 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1351 | iwl_txq_update_write_ptr(trans, txq); | 1395 | iwl_txq_update_write_ptr(trans, txq); |
@@ -1441,8 +1485,6 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
1441 | 1485 | ||
1442 | spin_lock(&txq->lock); | 1486 | spin_lock(&txq->lock); |
1443 | 1487 | ||
1444 | txq->time_stamp = jiffies; | ||
1445 | |||
1446 | if (txq->q.read_ptr != tfd_num) { | 1488 | if (txq->q.read_ptr != tfd_num) { |
1447 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", | 1489 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", |
1448 | txq_id, txq->q.read_ptr, tfd_num, ssn); | 1490 | txq_id, txq->q.read_ptr, tfd_num, ssn); |
@@ -1493,6 +1535,17 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1493 | 1535 | ||
1494 | memcpy(trans_pcie->setup_q_to_fifo, trans_cfg->queue_to_fifo, | 1536 | memcpy(trans_pcie->setup_q_to_fifo, trans_cfg->queue_to_fifo, |
1495 | trans_pcie->n_q_to_fifo * sizeof(u8)); | 1537 | trans_pcie->n_q_to_fifo * sizeof(u8)); |
1538 | |||
1539 | trans_pcie->rx_buf_size_8k = trans_cfg->rx_buf_size_8k; | ||
1540 | if (trans_pcie->rx_buf_size_8k) | ||
1541 | trans_pcie->rx_page_order = get_order(8 * 1024); | ||
1542 | else | ||
1543 | trans_pcie->rx_page_order = get_order(4 * 1024); | ||
1544 | |||
1545 | trans_pcie->wd_timeout = | ||
1546 | msecs_to_jiffies(trans_cfg->queue_watchdog_timeout); | ||
1547 | |||
1548 | trans_pcie->command_names = trans_cfg->command_names; | ||
1496 | } | 1549 | } |
1497 | 1550 | ||
1498 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1551 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
@@ -1523,9 +1576,9 @@ static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state) | |||
1523 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1576 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1524 | 1577 | ||
1525 | if (state) | 1578 | if (state) |
1526 | set_bit(STATUS_POWER_PMI, &trans_pcie->status); | 1579 | set_bit(STATUS_TPOWER_PMI, &trans_pcie->status); |
1527 | else | 1580 | else |
1528 | clear_bit(STATUS_POWER_PMI, &trans_pcie->status); | 1581 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); |
1529 | } | 1582 | } |
1530 | 1583 | ||
1531 | #ifdef CONFIG_PM_SLEEP | 1584 | #ifdef CONFIG_PM_SLEEP |
@@ -1582,42 +1635,9 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) | |||
1582 | return ret; | 1635 | return ret; |
1583 | } | 1636 | } |
1584 | 1637 | ||
1585 | /* | ||
1586 | * On every watchdog tick we check (latest) time stamp. If it does not | ||
1587 | * change during timeout period and queue is not empty we reset firmware. | ||
1588 | */ | ||
1589 | static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) | ||
1590 | { | ||
1591 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1592 | struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; | ||
1593 | struct iwl_queue *q = &txq->q; | ||
1594 | unsigned long timeout; | ||
1595 | |||
1596 | if (q->read_ptr == q->write_ptr) { | ||
1597 | txq->time_stamp = jiffies; | ||
1598 | return 0; | ||
1599 | } | ||
1600 | |||
1601 | timeout = txq->time_stamp + | ||
1602 | msecs_to_jiffies(hw_params(trans).wd_timeout); | ||
1603 | |||
1604 | if (time_after(jiffies, timeout)) { | ||
1605 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, | ||
1606 | hw_params(trans).wd_timeout); | ||
1607 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | ||
1608 | q->read_ptr, q->write_ptr); | ||
1609 | IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", | ||
1610 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) | ||
1611 | & (TFD_QUEUE_SIZE_MAX - 1), | ||
1612 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); | ||
1613 | return 1; | ||
1614 | } | ||
1615 | |||
1616 | return 0; | ||
1617 | } | ||
1618 | |||
1619 | static const char *get_fh_string(int cmd) | 1638 | static const char *get_fh_string(int cmd) |
1620 | { | 1639 | { |
1640 | #define IWL_CMD(x) case x: return #x | ||
1621 | switch (cmd) { | 1641 | switch (cmd) { |
1622 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | 1642 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); |
1623 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | 1643 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); |
@@ -1631,6 +1651,7 @@ static const char *get_fh_string(int cmd) | |||
1631 | default: | 1651 | default: |
1632 | return "UNKNOWN"; | 1652 | return "UNKNOWN"; |
1633 | } | 1653 | } |
1654 | #undef IWL_CMD | ||
1634 | } | 1655 | } |
1635 | 1656 | ||
1636 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | 1657 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) |
@@ -1679,6 +1700,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | |||
1679 | 1700 | ||
1680 | static const char *get_csr_string(int cmd) | 1701 | static const char *get_csr_string(int cmd) |
1681 | { | 1702 | { |
1703 | #define IWL_CMD(x) case x: return #x | ||
1682 | switch (cmd) { | 1704 | switch (cmd) { |
1683 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | 1705 | IWL_CMD(CSR_HW_IF_CONFIG_REG); |
1684 | IWL_CMD(CSR_INT_COALESCING); | 1706 | IWL_CMD(CSR_INT_COALESCING); |
@@ -1706,6 +1728,7 @@ static const char *get_csr_string(int cmd) | |||
1706 | default: | 1728 | default: |
1707 | return "UNKNOWN"; | 1729 | return "UNKNOWN"; |
1708 | } | 1730 | } |
1731 | #undef IWL_CMD | ||
1709 | } | 1732 | } |
1710 | 1733 | ||
1711 | void iwl_dump_csr(struct iwl_trans *trans) | 1734 | void iwl_dump_csr(struct iwl_trans *trans) |
@@ -1983,11 +2006,26 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | |||
1983 | return ret; | 2006 | return ret; |
1984 | } | 2007 | } |
1985 | 2008 | ||
2009 | static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | ||
2010 | const char __user *user_buf, | ||
2011 | size_t count, loff_t *ppos) | ||
2012 | { | ||
2013 | struct iwl_trans *trans = file->private_data; | ||
2014 | |||
2015 | if (!trans->op_mode) | ||
2016 | return -EAGAIN; | ||
2017 | |||
2018 | iwl_op_mode_nic_error(trans->op_mode); | ||
2019 | |||
2020 | return count; | ||
2021 | } | ||
2022 | |||
1986 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 2023 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
1987 | DEBUGFS_READ_FILE_OPS(fh_reg); | 2024 | DEBUGFS_READ_FILE_OPS(fh_reg); |
1988 | DEBUGFS_READ_FILE_OPS(rx_queue); | 2025 | DEBUGFS_READ_FILE_OPS(rx_queue); |
1989 | DEBUGFS_READ_FILE_OPS(tx_queue); | 2026 | DEBUGFS_READ_FILE_OPS(tx_queue); |
1990 | DEBUGFS_WRITE_FILE_OPS(csr); | 2027 | DEBUGFS_WRITE_FILE_OPS(csr); |
2028 | DEBUGFS_WRITE_FILE_OPS(fw_restart); | ||
1991 | 2029 | ||
1992 | /* | 2030 | /* |
1993 | * Create the debugfs files and directories | 2031 | * Create the debugfs files and directories |
@@ -2001,6 +2039,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
2001 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | 2039 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); |
2002 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | 2040 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); |
2003 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | 2041 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); |
2042 | DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR); | ||
2004 | return 0; | 2043 | return 0; |
2005 | } | 2044 | } |
2006 | #else | 2045 | #else |
@@ -2032,7 +2071,6 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
2032 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 2071 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
2033 | 2072 | ||
2034 | .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, | 2073 | .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, |
2035 | .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, | ||
2036 | 2074 | ||
2037 | #ifdef CONFIG_PM_SLEEP | 2075 | #ifdef CONFIG_PM_SLEEP |
2038 | .suspend = iwl_trans_pcie_suspend, | 2076 | .suspend = iwl_trans_pcie_suspend, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 66c54c1b404e..f3496a0490f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -305,6 +305,12 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
305 | * list of such notifications to filter. Max length is | 305 | * list of such notifications to filter. Max length is |
306 | * %MAX_NO_RECLAIM_CMDS. | 306 | * %MAX_NO_RECLAIM_CMDS. |
307 | * @n_no_reclaim_cmds: # of commands in list | 307 | * @n_no_reclaim_cmds: # of commands in list |
308 | * @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs, | ||
309 | * if unset 4k will be the RX buffer size | ||
310 | * @queue_watchdog_timeout: time (in ms) after which queues | ||
311 | * are considered stuck and will trigger device restart | ||
312 | * @command_names: array of command names, must be 256 entries | ||
313 | * (one for each command); for debugging only | ||
308 | */ | 314 | */ |
309 | struct iwl_trans_config { | 315 | struct iwl_trans_config { |
310 | struct iwl_op_mode *op_mode; | 316 | struct iwl_op_mode *op_mode; |
@@ -314,6 +320,10 @@ struct iwl_trans_config { | |||
314 | u8 cmd_queue; | 320 | u8 cmd_queue; |
315 | const u8 *no_reclaim_cmds; | 321 | const u8 *no_reclaim_cmds; |
316 | int n_no_reclaim_cmds; | 322 | int n_no_reclaim_cmds; |
323 | |||
324 | bool rx_buf_size_8k; | ||
325 | unsigned int queue_watchdog_timeout; | ||
326 | const char **command_names; | ||
317 | }; | 327 | }; |
318 | 328 | ||
319 | /** | 329 | /** |
@@ -351,7 +361,6 @@ struct iwl_trans_config { | |||
351 | * irq, tasklet etc... From this point on, the device may not issue | 361 | * irq, tasklet etc... From this point on, the device may not issue |
352 | * any interrupt (incl. RFKILL). | 362 | * any interrupt (incl. RFKILL). |
353 | * May sleep | 363 | * May sleep |
354 | * @check_stuck_queue: check if a specific queue is stuck | ||
355 | * @wait_tx_queue_empty: wait until all tx queues are empty | 364 | * @wait_tx_queue_empty: wait until all tx queues are empty |
356 | * May sleep | 365 | * May sleep |
357 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | 366 | * @dbgfs_register: add the dbgfs files under this directory. Files will be |
@@ -390,7 +399,6 @@ struct iwl_trans_ops { | |||
390 | void (*free)(struct iwl_trans *trans); | 399 | void (*free)(struct iwl_trans *trans); |
391 | 400 | ||
392 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 401 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
393 | int (*check_stuck_queue)(struct iwl_trans *trans, int q); | ||
394 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 402 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); |
395 | #ifdef CONFIG_PM_SLEEP | 403 | #ifdef CONFIG_PM_SLEEP |
396 | int (*suspend)(struct iwl_trans *trans); | 404 | int (*suspend)(struct iwl_trans *trans); |
@@ -426,7 +434,6 @@ enum iwl_trans_state { | |||
426 | * @hw_id: a u32 with the ID of the device / subdevice. | 434 | * @hw_id: a u32 with the ID of the device / subdevice. |
427 | * Set during transport allocation. | 435 | * Set during transport allocation. |
428 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. | 436 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. |
429 | * @nvm_device_type: indicates OTP or eeprom | ||
430 | * @pm_support: set to true in start_hw if link pm is supported | 437 | * @pm_support: set to true in start_hw if link pm is supported |
431 | * @wait_command_queue: the wait_queue for SYNC host commands | 438 | * @wait_command_queue: the wait_queue for SYNC host commands |
432 | */ | 439 | */ |
@@ -442,7 +449,6 @@ struct iwl_trans { | |||
442 | u32 hw_id; | 449 | u32 hw_id; |
443 | char hw_id_str[52]; | 450 | char hw_id_str[52]; |
444 | 451 | ||
445 | int nvm_device_type; | ||
446 | bool pm_support; | 452 | bool pm_support; |
447 | 453 | ||
448 | wait_queue_head_t wait_command_queue; | 454 | wait_queue_head_t wait_command_queue; |
@@ -573,13 +579,6 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | |||
573 | return trans->ops->wait_tx_queue_empty(trans); | 579 | return trans->ops->wait_tx_queue_empty(trans); |
574 | } | 580 | } |
575 | 581 | ||
576 | static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q) | ||
577 | { | ||
578 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | ||
579 | "%s bad state = %d", __func__, trans->state); | ||
580 | |||
581 | return trans->ops->check_stuck_queue(trans, q); | ||
582 | } | ||
583 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 582 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
584 | struct dentry *dir) | 583 | struct dentry *dir) |
585 | { | 584 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index ba7c9f883cb6..539171945610 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -62,7 +62,7 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | |||
62 | { | 62 | { |
63 | struct iwl_calib_xtal_freq_cmd cmd; | 63 | struct iwl_calib_xtal_freq_cmd cmd; |
64 | __le16 *xtal_calib = | 64 | __le16 *xtal_calib = |
65 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL); | 65 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); |
66 | 66 | ||
67 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 67 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); |
68 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 68 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
@@ -74,8 +74,7 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
74 | { | 74 | { |
75 | struct iwl_calib_temperature_offset_cmd cmd; | 75 | struct iwl_calib_temperature_offset_cmd cmd; |
76 | __le16 *offset_calib = | 76 | __le16 *offset_calib = |
77 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, | 77 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); |
78 | EEPROM_RAW_TEMPERATURE); | ||
79 | 78 | ||
80 | memset(&cmd, 0, sizeof(cmd)); | 79 | memset(&cmd, 0, sizeof(cmd)); |
81 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 80 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
@@ -91,16 +90,15 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
91 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | 90 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) |
92 | { | 91 | { |
93 | struct iwl_calib_temperature_offset_v2_cmd cmd; | 92 | struct iwl_calib_temperature_offset_v2_cmd cmd; |
94 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd, | 93 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, |
95 | EEPROM_KELVIN_TEMPERATURE); | 94 | EEPROM_KELVIN_TEMPERATURE); |
96 | __le16 *offset_calib_low = | 95 | __le16 *offset_calib_low = |
97 | (__le16 *)iwl_eeprom_query_addr(priv->shrd, | 96 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); |
98 | EEPROM_RAW_TEMPERATURE); | ||
99 | struct iwl_eeprom_calib_hdr *hdr; | 97 | struct iwl_eeprom_calib_hdr *hdr; |
100 | 98 | ||
101 | memset(&cmd, 0, sizeof(cmd)); | 99 | memset(&cmd, 0, sizeof(cmd)); |
102 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 100 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
103 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd, | 101 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, |
104 | EEPROM_CALIB_ALL); | 102 | EEPROM_CALIB_ALL); |
105 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 103 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, |
106 | sizeof(*offset_calib_high)); | 104 | sizeof(*offset_calib_high)); |
@@ -180,7 +178,7 @@ int iwl_init_alive_start(struct iwl_priv *priv) | |||
180 | return 0; | 178 | return 0; |
181 | } | 179 | } |
182 | 180 | ||
183 | static int iwl_send_wimax_coex(struct iwl_priv *priv) | 181 | int iwl_send_wimax_coex(struct iwl_priv *priv) |
184 | { | 182 | { |
185 | struct iwl_wimax_coex_cmd coex_cmd; | 183 | struct iwl_wimax_coex_cmd coex_cmd; |
186 | 184 | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index f7d01bfa2e4a..eac72f7bd341 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -6,6 +6,7 @@ libertas-y += ethtool.o | |||
6 | libertas-y += main.o | 6 | libertas-y += main.o |
7 | libertas-y += rx.o | 7 | libertas-y += rx.o |
8 | libertas-y += tx.o | 8 | libertas-y += tx.o |
9 | libertas-y += firmware.o | ||
9 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | 10 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o |
10 | 11 | ||
11 | usb8xxx-objs += if_usb.o | 12 | usb8xxx-objs += if_usb.o |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index bc951ab4b681..84a3aa7ac570 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -19,6 +19,10 @@ struct lbs_fw_table { | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | struct lbs_private; | 21 | struct lbs_private; |
22 | typedef void (*lbs_fw_cb)(struct lbs_private *priv, int ret, | ||
23 | const struct firmware *helper, const struct firmware *mainfw); | ||
24 | |||
25 | struct lbs_private; | ||
22 | struct sk_buff; | 26 | struct sk_buff; |
23 | struct net_device; | 27 | struct net_device; |
24 | struct cmd_ds_command; | 28 | struct cmd_ds_command; |
@@ -66,10 +70,13 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | |||
66 | u32 lbs_fw_index_to_data_rate(u8 index); | 70 | u32 lbs_fw_index_to_data_rate(u8 index); |
67 | u8 lbs_data_rate_to_fw_index(u32 rate); | 71 | u8 lbs_data_rate_to_fw_index(u32 rate); |
68 | 72 | ||
69 | int lbs_get_firmware(struct device *dev, const char *user_helper, | 73 | int lbs_get_firmware(struct device *dev, u32 card_model, |
70 | const char *user_mainfw, u32 card_model, | ||
71 | const struct lbs_fw_table *fw_table, | 74 | const struct lbs_fw_table *fw_table, |
72 | const struct firmware **helper, | 75 | const struct firmware **helper, |
73 | const struct firmware **mainfw); | 76 | const struct firmware **mainfw); |
77 | int lbs_get_firmware_async(struct lbs_private *priv, struct device *device, | ||
78 | u32 card_model, const struct lbs_fw_table *fw_table, | ||
79 | lbs_fw_cb callback); | ||
80 | void lbs_wait_for_firmware_load(struct lbs_private *priv); | ||
74 | 81 | ||
75 | #endif | 82 | #endif |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index f3fd447131c2..672005430aca 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #define _LBS_DEV_H_ | 7 | #define _LBS_DEV_H_ |
8 | 8 | ||
9 | #include "defs.h" | 9 | #include "defs.h" |
10 | #include "decl.h" | ||
10 | #include "host.h" | 11 | #include "host.h" |
11 | 12 | ||
12 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
@@ -180,6 +181,15 @@ struct lbs_private { | |||
180 | wait_queue_head_t scan_q; | 181 | wait_queue_head_t scan_q; |
181 | /* Whether the scan was initiated internally and not by cfg80211 */ | 182 | /* Whether the scan was initiated internally and not by cfg80211 */ |
182 | bool internal_scan; | 183 | bool internal_scan; |
184 | |||
185 | /* Firmware load */ | ||
186 | u32 fw_model; | ||
187 | wait_queue_head_t fw_waitq; | ||
188 | struct device *fw_device; | ||
189 | const struct firmware *helper_fw; | ||
190 | const struct lbs_fw_table *fw_table; | ||
191 | const struct lbs_fw_table *fw_iter; | ||
192 | lbs_fw_cb fw_callback; | ||
183 | }; | 193 | }; |
184 | 194 | ||
185 | extern struct cmd_confirm_sleep confirm_sleep; | 195 | extern struct cmd_confirm_sleep confirm_sleep; |
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c new file mode 100644 index 000000000000..cd23f1a8c98a --- /dev/null +++ b/drivers/net/wireless/libertas/firmware.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * Firmware loading and handling functions. | ||
3 | */ | ||
4 | |||
5 | #include <linux/firmware.h> | ||
6 | #include <linux/firmware.h> | ||
7 | #include <linux/module.h> | ||
8 | |||
9 | #include "dev.h" | ||
10 | #include "decl.h" | ||
11 | |||
12 | static void load_next_firmware_from_table(struct lbs_private *private); | ||
13 | |||
14 | static void lbs_fw_loaded(struct lbs_private *priv, int ret, | ||
15 | const struct firmware *helper, const struct firmware *mainfw) | ||
16 | { | ||
17 | unsigned long flags; | ||
18 | |||
19 | lbs_deb_fw("firmware load complete, code %d\n", ret); | ||
20 | |||
21 | /* User must free helper/mainfw */ | ||
22 | priv->fw_callback(priv, ret, helper, mainfw); | ||
23 | |||
24 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
25 | priv->fw_callback = NULL; | ||
26 | wake_up(&priv->fw_waitq); | ||
27 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
28 | } | ||
29 | |||
30 | static void do_load_firmware(struct lbs_private *priv, const char *name, | ||
31 | void (*cb)(const struct firmware *fw, void *context)) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | lbs_deb_fw("Requesting %s\n", name); | ||
36 | ret = request_firmware_nowait(THIS_MODULE, true, name, | ||
37 | priv->fw_device, GFP_KERNEL, priv, cb); | ||
38 | if (ret) { | ||
39 | lbs_deb_fw("request_firmware_nowait error %d\n", ret); | ||
40 | lbs_fw_loaded(priv, ret, NULL, NULL); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | static void main_firmware_cb(const struct firmware *firmware, void *context) | ||
45 | { | ||
46 | struct lbs_private *priv = context; | ||
47 | |||
48 | if (!firmware) { | ||
49 | /* Failed to find firmware: try next table entry */ | ||
50 | load_next_firmware_from_table(priv); | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | /* Firmware found! */ | ||
55 | lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); | ||
56 | } | ||
57 | |||
58 | static void helper_firmware_cb(const struct firmware *firmware, void *context) | ||
59 | { | ||
60 | struct lbs_private *priv = context; | ||
61 | |||
62 | if (!firmware) { | ||
63 | /* Failed to find firmware: try next table entry */ | ||
64 | load_next_firmware_from_table(priv); | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | /* Firmware found! */ | ||
69 | if (priv->fw_iter->fwname) { | ||
70 | priv->helper_fw = firmware; | ||
71 | do_load_firmware(priv, priv->fw_iter->fwname, main_firmware_cb); | ||
72 | } else { | ||
73 | /* No main firmware needed for this helper --> success! */ | ||
74 | lbs_fw_loaded(priv, 0, firmware, NULL); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | static void load_next_firmware_from_table(struct lbs_private *priv) | ||
79 | { | ||
80 | const struct lbs_fw_table *iter; | ||
81 | |||
82 | if (!priv->fw_iter) | ||
83 | iter = priv->fw_table; | ||
84 | else | ||
85 | iter = ++priv->fw_iter; | ||
86 | |||
87 | if (priv->helper_fw) { | ||
88 | release_firmware(priv->helper_fw); | ||
89 | priv->helper_fw = NULL; | ||
90 | } | ||
91 | |||
92 | next: | ||
93 | if (!iter->helper) { | ||
94 | /* End of table hit. */ | ||
95 | lbs_fw_loaded(priv, -ENOENT, NULL, NULL); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | if (iter->model != priv->fw_model) { | ||
100 | iter++; | ||
101 | goto next; | ||
102 | } | ||
103 | |||
104 | priv->fw_iter = iter; | ||
105 | do_load_firmware(priv, iter->helper, helper_firmware_cb); | ||
106 | } | ||
107 | |||
108 | void lbs_wait_for_firmware_load(struct lbs_private *priv) | ||
109 | { | ||
110 | wait_event(priv->fw_waitq, priv->fw_callback == NULL); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * lbs_get_firmware_async - Retrieves firmware asynchronously. Can load | ||
115 | * either a helper firmware and a main firmware (2-stage), or just the helper. | ||
116 | * | ||
117 | * @priv: Pointer to lbs_private instance | ||
118 | * @dev: A pointer to &device structure | ||
119 | * @card_model: Bus-specific card model ID used to filter firmware table | ||
120 | * elements | ||
121 | * @fw_table: Table of firmware file names and device model numbers | ||
122 | * terminated by an entry with a NULL helper name | ||
123 | * @callback: User callback to invoke when firmware load succeeds or fails. | ||
124 | */ | ||
125 | int lbs_get_firmware_async(struct lbs_private *priv, struct device *device, | ||
126 | u32 card_model, const struct lbs_fw_table *fw_table, | ||
127 | lbs_fw_cb callback) | ||
128 | { | ||
129 | unsigned long flags; | ||
130 | |||
131 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
132 | if (priv->fw_callback) { | ||
133 | lbs_deb_fw("firmware load already in progress\n"); | ||
134 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
135 | return -EBUSY; | ||
136 | } | ||
137 | |||
138 | priv->fw_device = device; | ||
139 | priv->fw_callback = callback; | ||
140 | priv->fw_table = fw_table; | ||
141 | priv->fw_iter = NULL; | ||
142 | priv->fw_model = card_model; | ||
143 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
144 | |||
145 | lbs_deb_fw("Starting async firmware load\n"); | ||
146 | load_next_firmware_from_table(priv); | ||
147 | return 0; | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(lbs_get_firmware_async); | ||
150 | |||
151 | /** | ||
152 | * lbs_get_firmware - Retrieves two-stage firmware | ||
153 | * | ||
154 | * @dev: A pointer to &device structure | ||
155 | * @card_model: Bus-specific card model ID used to filter firmware table | ||
156 | * elements | ||
157 | * @fw_table: Table of firmware file names and device model numbers | ||
158 | * terminated by an entry with a NULL helper name | ||
159 | * @helper: On success, the helper firmware; caller must free | ||
160 | * @mainfw: On success, the main firmware; caller must free | ||
161 | * | ||
162 | * Deprecated: use lbs_get_firmware_async() instead. | ||
163 | * | ||
164 | * returns: 0 on success, non-zero on failure | ||
165 | */ | ||
166 | int lbs_get_firmware(struct device *dev, u32 card_model, | ||
167 | const struct lbs_fw_table *fw_table, | ||
168 | const struct firmware **helper, | ||
169 | const struct firmware **mainfw) | ||
170 | { | ||
171 | const struct lbs_fw_table *iter; | ||
172 | int ret; | ||
173 | |||
174 | BUG_ON(helper == NULL); | ||
175 | BUG_ON(mainfw == NULL); | ||
176 | |||
177 | /* Search for firmware to use from the table. */ | ||
178 | iter = fw_table; | ||
179 | while (iter && iter->helper) { | ||
180 | if (iter->model != card_model) | ||
181 | goto next; | ||
182 | |||
183 | if (*helper == NULL) { | ||
184 | ret = request_firmware(helper, iter->helper, dev); | ||
185 | if (ret) | ||
186 | goto next; | ||
187 | |||
188 | /* If the device has one-stage firmware (ie cf8305) and | ||
189 | * we've got it then we don't need to bother with the | ||
190 | * main firmware. | ||
191 | */ | ||
192 | if (iter->fwname == NULL) | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | if (*mainfw == NULL) { | ||
197 | ret = request_firmware(mainfw, iter->fwname, dev); | ||
198 | if (ret) { | ||
199 | /* Clear the helper to ensure we don't have | ||
200 | * mismatched firmware pairs. | ||
201 | */ | ||
202 | release_firmware(*helper); | ||
203 | *helper = NULL; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | if (*helper && *mainfw) | ||
208 | return 0; | ||
209 | |||
210 | next: | ||
211 | iter++; | ||
212 | } | ||
213 | |||
214 | /* Failed */ | ||
215 | release_firmware(*helper); | ||
216 | *helper = NULL; | ||
217 | release_firmware(*mainfw); | ||
218 | *mainfw = NULL; | ||
219 | |||
220 | return -ENOENT; | ||
221 | } | ||
222 | EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 234ee88dec95..cee50528522b 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -890,8 +890,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
890 | goto out2; | 890 | goto out2; |
891 | } | 891 | } |
892 | 892 | ||
893 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | 893 | ret = lbs_get_firmware(&p_dev->dev, card->model, &fw_table[0], |
894 | &fw_table[0], &helper, &mainfw); | 894 | &helper, &mainfw); |
895 | if (ret) { | 895 | if (ret) { |
896 | pr_err("failed to find firmware (%d)\n", ret); | 896 | pr_err("failed to find firmware (%d)\n", ret); |
897 | goto out2; | 897 | goto out2; |
@@ -951,10 +951,8 @@ out2: | |||
951 | out1: | 951 | out1: |
952 | pcmcia_disable_device(p_dev); | 952 | pcmcia_disable_device(p_dev); |
953 | out: | 953 | out: |
954 | if (helper) | 954 | release_firmware(helper); |
955 | release_firmware(helper); | 955 | release_firmware(mainfw); |
956 | if (mainfw) | ||
957 | release_firmware(mainfw); | ||
958 | 956 | ||
959 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 957 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
960 | return ret; | 958 | return ret; |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 9804ebc892d4..76caebaa4397 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -65,12 +65,6 @@ static void if_sdio_interrupt(struct sdio_func *func); | |||
65 | */ | 65 | */ |
66 | static u8 user_rmmod; | 66 | static u8 user_rmmod; |
67 | 67 | ||
68 | static char *lbs_helper_name = NULL; | ||
69 | module_param_named(helper_name, lbs_helper_name, charp, 0644); | ||
70 | |||
71 | static char *lbs_fw_name = NULL; | ||
72 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | ||
73 | |||
74 | static const struct sdio_device_id if_sdio_ids[] = { | 68 | static const struct sdio_device_id if_sdio_ids[] = { |
75 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, | 69 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, |
76 | SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, | 70 | SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, |
@@ -123,11 +117,8 @@ struct if_sdio_card { | |||
123 | int model; | 117 | int model; |
124 | unsigned long ioport; | 118 | unsigned long ioport; |
125 | unsigned int scratch_reg; | 119 | unsigned int scratch_reg; |
126 | 120 | bool started; | |
127 | const char *helper; | 121 | wait_queue_head_t pwron_waitq; |
128 | const char *firmware; | ||
129 | bool helper_allocated; | ||
130 | bool firmware_allocated; | ||
131 | 122 | ||
132 | u8 buffer[65536] __attribute__((aligned(4))); | 123 | u8 buffer[65536] __attribute__((aligned(4))); |
133 | 124 | ||
@@ -140,6 +131,9 @@ struct if_sdio_card { | |||
140 | u8 rx_unit; | 131 | u8 rx_unit; |
141 | }; | 132 | }; |
142 | 133 | ||
134 | static void if_sdio_finish_power_on(struct if_sdio_card *card); | ||
135 | static int if_sdio_power_off(struct if_sdio_card *card); | ||
136 | |||
143 | /********************************************************************/ | 137 | /********************************************************************/ |
144 | /* I/O */ | 138 | /* I/O */ |
145 | /********************************************************************/ | 139 | /********************************************************************/ |
@@ -680,12 +674,39 @@ out: | |||
680 | return ret; | 674 | return ret; |
681 | } | 675 | } |
682 | 676 | ||
677 | static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret, | ||
678 | const struct firmware *helper, | ||
679 | const struct firmware *mainfw) | ||
680 | { | ||
681 | struct if_sdio_card *card = priv->card; | ||
682 | |||
683 | if (ret) { | ||
684 | pr_err("failed to find firmware (%d)\n", ret); | ||
685 | return; | ||
686 | } | ||
687 | |||
688 | ret = if_sdio_prog_helper(card, helper); | ||
689 | if (ret) | ||
690 | goto out; | ||
691 | |||
692 | lbs_deb_sdio("Helper firmware loaded\n"); | ||
693 | |||
694 | ret = if_sdio_prog_real(card, mainfw); | ||
695 | if (ret) | ||
696 | goto out; | ||
697 | |||
698 | lbs_deb_sdio("Firmware loaded\n"); | ||
699 | if_sdio_finish_power_on(card); | ||
700 | |||
701 | out: | ||
702 | release_firmware(helper); | ||
703 | release_firmware(mainfw); | ||
704 | } | ||
705 | |||
683 | static int if_sdio_prog_firmware(struct if_sdio_card *card) | 706 | static int if_sdio_prog_firmware(struct if_sdio_card *card) |
684 | { | 707 | { |
685 | int ret; | 708 | int ret; |
686 | u16 scratch; | 709 | u16 scratch; |
687 | const struct firmware *helper = NULL; | ||
688 | const struct firmware *mainfw = NULL; | ||
689 | 710 | ||
690 | lbs_deb_enter(LBS_DEB_SDIO); | 711 | lbs_deb_enter(LBS_DEB_SDIO); |
691 | 712 | ||
@@ -719,43 +740,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
719 | */ | 740 | */ |
720 | if (scratch == IF_SDIO_FIRMWARE_OK) { | 741 | if (scratch == IF_SDIO_FIRMWARE_OK) { |
721 | lbs_deb_sdio("firmware already loaded\n"); | 742 | lbs_deb_sdio("firmware already loaded\n"); |
722 | goto success; | 743 | if_sdio_finish_power_on(card); |
744 | return 0; | ||
723 | } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) { | 745 | } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) { |
724 | lbs_deb_sdio("firmware may be running\n"); | 746 | lbs_deb_sdio("firmware may be running\n"); |
725 | goto success; | 747 | if_sdio_finish_power_on(card); |
726 | } | 748 | return 0; |
727 | |||
728 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, | ||
729 | card->model, &fw_table[0], &helper, &mainfw); | ||
730 | if (ret) { | ||
731 | pr_err("failed to find firmware (%d)\n", ret); | ||
732 | goto out; | ||
733 | } | 749 | } |
734 | 750 | ||
735 | ret = if_sdio_prog_helper(card, helper); | 751 | ret = lbs_get_firmware_async(card->priv, &card->func->dev, card->model, |
736 | if (ret) | 752 | fw_table, if_sdio_do_prog_firmware); |
737 | goto out; | ||
738 | |||
739 | lbs_deb_sdio("Helper firmware loaded\n"); | ||
740 | |||
741 | ret = if_sdio_prog_real(card, mainfw); | ||
742 | if (ret) | ||
743 | goto out; | ||
744 | |||
745 | lbs_deb_sdio("Firmware loaded\n"); | ||
746 | |||
747 | success: | ||
748 | sdio_claim_host(card->func); | ||
749 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | ||
750 | sdio_release_host(card->func); | ||
751 | ret = 0; | ||
752 | 753 | ||
753 | out: | 754 | out: |
754 | if (helper) | ||
755 | release_firmware(helper); | ||
756 | if (mainfw) | ||
757 | release_firmware(mainfw); | ||
758 | |||
759 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 755 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
760 | return ret; | 756 | return ret; |
761 | } | 757 | } |
@@ -764,55 +760,15 @@ out: | |||
764 | /* Power management */ | 760 | /* Power management */ |
765 | /********************************************************************/ | 761 | /********************************************************************/ |
766 | 762 | ||
767 | static int if_sdio_power_on(struct if_sdio_card *card) | 763 | /* Finish power on sequence (after firmware is loaded) */ |
764 | static void if_sdio_finish_power_on(struct if_sdio_card *card) | ||
768 | { | 765 | { |
769 | struct sdio_func *func = card->func; | 766 | struct sdio_func *func = card->func; |
770 | struct lbs_private *priv = card->priv; | 767 | struct lbs_private *priv = card->priv; |
771 | struct mmc_host *host = func->card->host; | ||
772 | int ret; | 768 | int ret; |
773 | 769 | ||
774 | sdio_claim_host(func); | 770 | sdio_claim_host(func); |
775 | 771 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | |
776 | ret = sdio_enable_func(func); | ||
777 | if (ret) | ||
778 | goto release; | ||
779 | |||
780 | /* For 1-bit transfers to the 8686 model, we need to enable the | ||
781 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
782 | * bit to allow access to non-vendor registers. */ | ||
783 | if ((card->model == MODEL_8686) && | ||
784 | (host->caps & MMC_CAP_SDIO_IRQ) && | ||
785 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
786 | u8 reg; | ||
787 | |||
788 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
789 | reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
790 | if (ret) | ||
791 | goto disable; | ||
792 | |||
793 | reg |= SDIO_BUS_ECSI; | ||
794 | sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
795 | if (ret) | ||
796 | goto disable; | ||
797 | } | ||
798 | |||
799 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | ||
800 | if (ret) | ||
801 | goto disable; | ||
802 | |||
803 | card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; | ||
804 | if (ret) | ||
805 | goto disable; | ||
806 | |||
807 | card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; | ||
808 | if (ret) | ||
809 | goto disable; | ||
810 | |||
811 | sdio_release_host(func); | ||
812 | ret = if_sdio_prog_firmware(card); | ||
813 | sdio_claim_host(func); | ||
814 | if (ret) | ||
815 | goto disable; | ||
816 | 772 | ||
817 | /* | 773 | /* |
818 | * Get rx_unit if the chip is SD8688 or newer. | 774 | * Get rx_unit if the chip is SD8688 or newer. |
@@ -837,7 +793,7 @@ static int if_sdio_power_on(struct if_sdio_card *card) | |||
837 | */ | 793 | */ |
838 | ret = sdio_claim_irq(func, if_sdio_interrupt); | 794 | ret = sdio_claim_irq(func, if_sdio_interrupt); |
839 | if (ret) | 795 | if (ret) |
840 | goto disable; | 796 | goto release; |
841 | 797 | ||
842 | /* | 798 | /* |
843 | * Enable interrupts now that everything is set up | 799 | * Enable interrupts now that everything is set up |
@@ -863,11 +819,79 @@ static int if_sdio_power_on(struct if_sdio_card *card) | |||
863 | } | 819 | } |
864 | 820 | ||
865 | priv->fw_ready = 1; | 821 | priv->fw_ready = 1; |
822 | wake_up(&card->pwron_waitq); | ||
866 | 823 | ||
867 | return 0; | 824 | if (!card->started) { |
825 | ret = lbs_start_card(priv); | ||
826 | if_sdio_power_off(card); | ||
827 | if (ret == 0) { | ||
828 | card->started = true; | ||
829 | /* Tell PM core that we don't need the card to be | ||
830 | * powered now */ | ||
831 | pm_runtime_put_noidle(&func->dev); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | return; | ||
868 | 836 | ||
869 | release_irq: | 837 | release_irq: |
870 | sdio_release_irq(func); | 838 | sdio_release_irq(func); |
839 | release: | ||
840 | sdio_release_host(func); | ||
841 | } | ||
842 | |||
843 | static int if_sdio_power_on(struct if_sdio_card *card) | ||
844 | { | ||
845 | struct sdio_func *func = card->func; | ||
846 | struct mmc_host *host = func->card->host; | ||
847 | int ret; | ||
848 | |||
849 | sdio_claim_host(func); | ||
850 | |||
851 | ret = sdio_enable_func(func); | ||
852 | if (ret) | ||
853 | goto release; | ||
854 | |||
855 | /* For 1-bit transfers to the 8686 model, we need to enable the | ||
856 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
857 | * bit to allow access to non-vendor registers. */ | ||
858 | if ((card->model == MODEL_8686) && | ||
859 | (host->caps & MMC_CAP_SDIO_IRQ) && | ||
860 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
861 | u8 reg; | ||
862 | |||
863 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
864 | reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
865 | if (ret) | ||
866 | goto disable; | ||
867 | |||
868 | reg |= SDIO_BUS_ECSI; | ||
869 | sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
870 | if (ret) | ||
871 | goto disable; | ||
872 | } | ||
873 | |||
874 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | ||
875 | if (ret) | ||
876 | goto disable; | ||
877 | |||
878 | card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; | ||
879 | if (ret) | ||
880 | goto disable; | ||
881 | |||
882 | card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; | ||
883 | if (ret) | ||
884 | goto disable; | ||
885 | |||
886 | sdio_release_host(func); | ||
887 | ret = if_sdio_prog_firmware(card); | ||
888 | if (ret) { | ||
889 | sdio_disable_func(func); | ||
890 | return ret; | ||
891 | } | ||
892 | |||
893 | return 0; | ||
894 | |||
871 | disable: | 895 | disable: |
872 | sdio_disable_func(func); | 896 | sdio_disable_func(func); |
873 | release: | 897 | release: |
@@ -1074,11 +1098,17 @@ static int if_sdio_power_save(struct lbs_private *priv) | |||
1074 | static int if_sdio_power_restore(struct lbs_private *priv) | 1098 | static int if_sdio_power_restore(struct lbs_private *priv) |
1075 | { | 1099 | { |
1076 | struct if_sdio_card *card = priv->card; | 1100 | struct if_sdio_card *card = priv->card; |
1101 | int r; | ||
1077 | 1102 | ||
1078 | /* Make sure the card will not be powered off by runtime PM */ | 1103 | /* Make sure the card will not be powered off by runtime PM */ |
1079 | pm_runtime_get_sync(&card->func->dev); | 1104 | pm_runtime_get_sync(&card->func->dev); |
1080 | 1105 | ||
1081 | return if_sdio_power_on(card); | 1106 | r = if_sdio_power_on(card); |
1107 | if (r) | ||
1108 | return r; | ||
1109 | |||
1110 | wait_event(card->pwron_waitq, priv->fw_ready); | ||
1111 | return 0; | ||
1082 | } | 1112 | } |
1083 | 1113 | ||
1084 | 1114 | ||
@@ -1179,6 +1209,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1179 | spin_lock_init(&card->lock); | 1209 | spin_lock_init(&card->lock); |
1180 | card->workqueue = create_workqueue("libertas_sdio"); | 1210 | card->workqueue = create_workqueue("libertas_sdio"); |
1181 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); | 1211 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); |
1212 | init_waitqueue_head(&card->pwron_waitq); | ||
1182 | 1213 | ||
1183 | /* Check if we support this card */ | 1214 | /* Check if we support this card */ |
1184 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | 1215 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
@@ -1220,14 +1251,6 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1220 | if (ret) | 1251 | if (ret) |
1221 | goto err_activate_card; | 1252 | goto err_activate_card; |
1222 | 1253 | ||
1223 | ret = lbs_start_card(priv); | ||
1224 | if_sdio_power_off(card); | ||
1225 | if (ret) | ||
1226 | goto err_activate_card; | ||
1227 | |||
1228 | /* Tell PM core that we don't need the card to be powered now */ | ||
1229 | pm_runtime_put_noidle(&func->dev); | ||
1230 | |||
1231 | out: | 1254 | out: |
1232 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 1255 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
1233 | 1256 | ||
@@ -1244,10 +1267,6 @@ free: | |||
1244 | kfree(packet); | 1267 | kfree(packet); |
1245 | } | 1268 | } |
1246 | 1269 | ||
1247 | if (card->helper_allocated) | ||
1248 | kfree(card->helper); | ||
1249 | if (card->firmware_allocated) | ||
1250 | kfree(card->firmware); | ||
1251 | kfree(card); | 1270 | kfree(card); |
1252 | 1271 | ||
1253 | goto out; | 1272 | goto out; |
@@ -1295,12 +1314,6 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1295 | kfree(packet); | 1314 | kfree(packet); |
1296 | } | 1315 | } |
1297 | 1316 | ||
1298 | if (card->helper_allocated) | ||
1299 | kfree(card->helper); | ||
1300 | if (card->firmware_allocated) | ||
1301 | kfree(card->firmware); | ||
1302 | kfree(card); | ||
1303 | |||
1304 | lbs_deb_leave(LBS_DEB_SDIO); | 1317 | lbs_deb_leave(LBS_DEB_SDIO); |
1305 | } | 1318 | } |
1306 | 1319 | ||
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 50b1ee7721e9..9604a1c4a74d 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -1064,9 +1064,8 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
1064 | goto out; | 1064 | goto out; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | 1067 | err = lbs_get_firmware(&card->spi->dev, card->card_id, |
1068 | card->card_id, &fw_table[0], &helper, | 1068 | &fw_table[0], &helper, &mainfw); |
1069 | &mainfw); | ||
1070 | if (err) { | 1069 | if (err) { |
1071 | netdev_err(priv->dev, "failed to find firmware (%d)\n", | 1070 | netdev_err(priv->dev, "failed to find firmware (%d)\n", |
1072 | err); | 1071 | err); |
@@ -1095,10 +1094,8 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
1095 | goto out; | 1094 | goto out; |
1096 | 1095 | ||
1097 | out: | 1096 | out: |
1098 | if (helper) | 1097 | release_firmware(helper); |
1099 | release_firmware(helper); | 1098 | release_firmware(mainfw); |
1100 | if (mainfw) | ||
1101 | release_firmware(mainfw); | ||
1102 | 1099 | ||
1103 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1100 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1104 | 1101 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 74da5f1ea243..75403e6e3990 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -29,9 +29,6 @@ | |||
29 | 29 | ||
30 | #define MESSAGE_HEADER_LEN 4 | 30 | #define MESSAGE_HEADER_LEN 4 |
31 | 31 | ||
32 | static char *lbs_fw_name = NULL; | ||
33 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | ||
34 | |||
35 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); | 32 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); |
36 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); | 33 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); |
37 | MODULE_FIRMWARE("libertas/usb8388.bin"); | 34 | MODULE_FIRMWARE("libertas/usb8388.bin"); |
@@ -44,6 +41,16 @@ enum { | |||
44 | MODEL_8682 = 0x2 | 41 | MODEL_8682 = 0x2 |
45 | }; | 42 | }; |
46 | 43 | ||
44 | /* table of firmware file names */ | ||
45 | static const struct lbs_fw_table fw_table[] = { | ||
46 | { MODEL_8388, "libertas/usb8388_olpc.bin", NULL }, | ||
47 | { MODEL_8388, "libertas/usb8388_v9.bin", NULL }, | ||
48 | { MODEL_8388, "libertas/usb8388_v5.bin", NULL }, | ||
49 | { MODEL_8388, "libertas/usb8388.bin", NULL }, | ||
50 | { MODEL_8388, "usb8388.bin", NULL }, | ||
51 | { MODEL_8682, "libertas/usb8682.bin", NULL } | ||
52 | }; | ||
53 | |||
47 | static struct usb_device_id if_usb_table[] = { | 54 | static struct usb_device_id if_usb_table[] = { |
48 | /* Enter the device signature inside */ | 55 | /* Enter the device signature inside */ |
49 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, | 56 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, |
@@ -55,10 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); | |||
55 | 62 | ||
56 | static void if_usb_receive(struct urb *urb); | 63 | static void if_usb_receive(struct urb *urb); |
57 | static void if_usb_receive_fwload(struct urb *urb); | 64 | static void if_usb_receive_fwload(struct urb *urb); |
58 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, | 65 | static void if_usb_prog_firmware(struct lbs_private *priv, int ret, |
59 | const char *fwname, int cmd); | 66 | const struct firmware *fw, |
60 | static int if_usb_prog_firmware(struct if_usb_card *cardp, | 67 | const struct firmware *unused); |
61 | const char *fwname, int cmd); | ||
62 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | 68 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, |
63 | uint8_t *payload, uint16_t nb); | 69 | uint8_t *payload, uint16_t nb); |
64 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | 70 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, |
@@ -67,69 +73,6 @@ static void if_usb_free(struct if_usb_card *cardp); | |||
67 | static int if_usb_submit_rx_urb(struct if_usb_card *cardp); | 73 | static int if_usb_submit_rx_urb(struct if_usb_card *cardp); |
68 | static int if_usb_reset_device(struct if_usb_card *cardp); | 74 | static int if_usb_reset_device(struct if_usb_card *cardp); |
69 | 75 | ||
70 | /* sysfs hooks */ | ||
71 | |||
72 | /* | ||
73 | * Set function to write firmware to device's persistent memory | ||
74 | */ | ||
75 | static ssize_t if_usb_firmware_set(struct device *dev, | ||
76 | struct device_attribute *attr, const char *buf, size_t count) | ||
77 | { | ||
78 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
79 | struct if_usb_card *cardp = priv->card; | ||
80 | int ret; | ||
81 | |||
82 | BUG_ON(buf == NULL); | ||
83 | |||
84 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); | ||
85 | if (ret == 0) | ||
86 | return count; | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * lbs_flash_fw attribute to be exported per ethX interface through sysfs | ||
93 | * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to | ||
94 | * the device's persistent memory: | ||
95 | * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw | ||
96 | */ | ||
97 | static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); | ||
98 | |||
99 | /** | ||
100 | * if_usb_boot2_set - write firmware to device's persistent memory | ||
101 | * | ||
102 | * @dev: target device | ||
103 | * @attr: device attributes | ||
104 | * @buf: firmware buffer to write | ||
105 | * @count: number of bytes to write | ||
106 | * | ||
107 | * returns: number of bytes written or negative error code | ||
108 | */ | ||
109 | static ssize_t if_usb_boot2_set(struct device *dev, | ||
110 | struct device_attribute *attr, const char *buf, size_t count) | ||
111 | { | ||
112 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
113 | struct if_usb_card *cardp = priv->card; | ||
114 | int ret; | ||
115 | |||
116 | BUG_ON(buf == NULL); | ||
117 | |||
118 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); | ||
119 | if (ret == 0) | ||
120 | return count; | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs | ||
127 | * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware | ||
128 | * to the device's persistent memory: | ||
129 | * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2 | ||
130 | */ | ||
131 | static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); | ||
132 | |||
133 | /** | 76 | /** |
134 | * if_usb_write_bulk_callback - callback function to handle the status | 77 | * if_usb_write_bulk_callback - callback function to handle the status |
135 | * of the URB | 78 | * of the URB |
@@ -256,6 +199,7 @@ static int if_usb_probe(struct usb_interface *intf, | |||
256 | struct usb_endpoint_descriptor *endpoint; | 199 | struct usb_endpoint_descriptor *endpoint; |
257 | struct lbs_private *priv; | 200 | struct lbs_private *priv; |
258 | struct if_usb_card *cardp; | 201 | struct if_usb_card *cardp; |
202 | int r = -ENOMEM; | ||
259 | int i; | 203 | int i; |
260 | 204 | ||
261 | udev = interface_to_usbdev(intf); | 205 | udev = interface_to_usbdev(intf); |
@@ -313,20 +257,10 @@ static int if_usb_probe(struct usb_interface *intf, | |||
313 | goto dealloc; | 257 | goto dealloc; |
314 | } | 258 | } |
315 | 259 | ||
316 | /* Upload firmware */ | ||
317 | kparam_block_sysfs_write(fw_name); | ||
318 | if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { | ||
319 | kparam_unblock_sysfs_write(fw_name); | ||
320 | lbs_deb_usbd(&udev->dev, "FW upload failed\n"); | ||
321 | goto err_prog_firmware; | ||
322 | } | ||
323 | kparam_unblock_sysfs_write(fw_name); | ||
324 | |||
325 | if (!(priv = lbs_add_card(cardp, &intf->dev))) | 260 | if (!(priv = lbs_add_card(cardp, &intf->dev))) |
326 | goto err_prog_firmware; | 261 | goto err_add_card; |
327 | 262 | ||
328 | cardp->priv = priv; | 263 | cardp->priv = priv; |
329 | cardp->priv->fw_ready = 1; | ||
330 | 264 | ||
331 | priv->hw_host_to_card = if_usb_host_to_card; | 265 | priv->hw_host_to_card = if_usb_host_to_card; |
332 | priv->enter_deep_sleep = NULL; | 266 | priv->enter_deep_sleep = NULL; |
@@ -339,42 +273,25 @@ static int if_usb_probe(struct usb_interface *intf, | |||
339 | 273 | ||
340 | cardp->boot2_version = udev->descriptor.bcdDevice; | 274 | cardp->boot2_version = udev->descriptor.bcdDevice; |
341 | 275 | ||
342 | if_usb_submit_rx_urb(cardp); | ||
343 | |||
344 | if (lbs_start_card(priv)) | ||
345 | goto err_start_card; | ||
346 | |||
347 | if_usb_setup_firmware(priv); | ||
348 | |||
349 | usb_get_dev(udev); | 276 | usb_get_dev(udev); |
350 | usb_set_intfdata(intf, cardp); | 277 | usb_set_intfdata(intf, cardp); |
351 | 278 | ||
352 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) | 279 | r = lbs_get_firmware_async(priv, &udev->dev, cardp->model, |
353 | netdev_err(priv->dev, | 280 | fw_table, if_usb_prog_firmware); |
354 | "cannot register lbs_flash_fw attribute\n"); | 281 | if (r) |
355 | 282 | goto err_get_fw; | |
356 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) | ||
357 | netdev_err(priv->dev, | ||
358 | "cannot register lbs_flash_boot2 attribute\n"); | ||
359 | |||
360 | /* | ||
361 | * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | ||
362 | */ | ||
363 | priv->wol_criteria = EHS_REMOVE_WAKEUP; | ||
364 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | ||
365 | priv->ehs_remove_supported = false; | ||
366 | 283 | ||
367 | return 0; | 284 | return 0; |
368 | 285 | ||
369 | err_start_card: | 286 | err_get_fw: |
370 | lbs_remove_card(priv); | 287 | lbs_remove_card(priv); |
371 | err_prog_firmware: | 288 | err_add_card: |
372 | if_usb_reset_device(cardp); | 289 | if_usb_reset_device(cardp); |
373 | dealloc: | 290 | dealloc: |
374 | if_usb_free(cardp); | 291 | if_usb_free(cardp); |
375 | 292 | ||
376 | error: | 293 | error: |
377 | return -ENOMEM; | 294 | return r; |
378 | } | 295 | } |
379 | 296 | ||
380 | /** | 297 | /** |
@@ -389,9 +306,6 @@ static void if_usb_disconnect(struct usb_interface *intf) | |||
389 | 306 | ||
390 | lbs_deb_enter(LBS_DEB_MAIN); | 307 | lbs_deb_enter(LBS_DEB_MAIN); |
391 | 308 | ||
392 | device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2); | ||
393 | device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw); | ||
394 | |||
395 | cardp->surprise_removed = 1; | 309 | cardp->surprise_removed = 1; |
396 | 310 | ||
397 | if (priv) { | 311 | if (priv) { |
@@ -912,121 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) | |||
912 | return ret; | 826 | return ret; |
913 | } | 827 | } |
914 | 828 | ||
915 | 829 | static void if_usb_prog_firmware(struct lbs_private *priv, int ret, | |
916 | /** | 830 | const struct firmware *fw, |
917 | * if_usb_prog_firmware - programs the firmware subject to cmd | 831 | const struct firmware *unused) |
918 | * | ||
919 | * @cardp: the if_usb_card descriptor | ||
920 | * @fwname: firmware or boot2 image file name | ||
921 | * @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, | ||
922 | * or BOOT_CMD_UPDATE_BOOT2. | ||
923 | * returns: 0 or error code | ||
924 | */ | ||
925 | static int if_usb_prog_firmware(struct if_usb_card *cardp, | ||
926 | const char *fwname, int cmd) | ||
927 | { | ||
928 | struct lbs_private *priv = cardp->priv; | ||
929 | unsigned long flags, caps; | ||
930 | int ret; | ||
931 | |||
932 | caps = priv->fwcapinfo; | ||
933 | if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) || | ||
934 | ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE))) | ||
935 | return -EOPNOTSUPP; | ||
936 | |||
937 | /* Ensure main thread is idle. */ | ||
938 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
939 | while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) { | ||
940 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
941 | if (wait_event_interruptible(priv->waitq, | ||
942 | (priv->cur_cmd == NULL && | ||
943 | priv->dnld_sent == DNLD_RES_RECEIVED))) { | ||
944 | return -ERESTARTSYS; | ||
945 | } | ||
946 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
947 | } | ||
948 | priv->dnld_sent = DNLD_BOOTCMD_SENT; | ||
949 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
950 | |||
951 | ret = __if_usb_prog_firmware(cardp, fwname, cmd); | ||
952 | |||
953 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
954 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
955 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
956 | |||
957 | wake_up(&priv->waitq); | ||
958 | |||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | /* table of firmware file names */ | ||
963 | static const struct { | ||
964 | u32 model; | ||
965 | const char *fwname; | ||
966 | } fw_table[] = { | ||
967 | { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
968 | { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
969 | { MODEL_8388, "libertas/usb8388.bin" }, | ||
970 | { MODEL_8388, "usb8388.bin" }, | ||
971 | { MODEL_8682, "libertas/usb8682.bin" } | ||
972 | }; | ||
973 | |||
974 | #ifdef CONFIG_OLPC | ||
975 | |||
976 | static int try_olpc_fw(struct if_usb_card *cardp) | ||
977 | { | ||
978 | int retval = -ENOENT; | ||
979 | |||
980 | /* try the OLPC firmware first; fall back to fw_table list */ | ||
981 | if (machine_is_olpc() && cardp->model == MODEL_8388) | ||
982 | retval = request_firmware(&cardp->fw, | ||
983 | "libertas/usb8388_olpc.bin", &cardp->udev->dev); | ||
984 | return retval; | ||
985 | } | ||
986 | |||
987 | #else | ||
988 | static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; } | ||
989 | #endif /* !CONFIG_OLPC */ | ||
990 | |||
991 | static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
992 | { | ||
993 | int i; | ||
994 | |||
995 | /* Try user-specified firmware first */ | ||
996 | if (fwname) | ||
997 | return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | ||
998 | |||
999 | /* Handle OLPC firmware */ | ||
1000 | if (try_olpc_fw(cardp) == 0) | ||
1001 | return 0; | ||
1002 | |||
1003 | /* Otherwise search for firmware to use */ | ||
1004 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
1005 | if (fw_table[i].model != cardp->model) | ||
1006 | continue; | ||
1007 | if (request_firmware(&cardp->fw, fw_table[i].fwname, | ||
1008 | &cardp->udev->dev) == 0) | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | return -ENOENT; | ||
1013 | } | ||
1014 | |||
1015 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, | ||
1016 | const char *fwname, int cmd) | ||
1017 | { | 832 | { |
833 | struct if_usb_card *cardp = priv->card; | ||
1018 | int i = 0; | 834 | int i = 0; |
1019 | static int reset_count = 10; | 835 | static int reset_count = 10; |
1020 | int ret = 0; | ||
1021 | 836 | ||
1022 | lbs_deb_enter(LBS_DEB_USB); | 837 | lbs_deb_enter(LBS_DEB_USB); |
1023 | 838 | ||
1024 | ret = get_fw(cardp, fwname); | ||
1025 | if (ret) { | 839 | if (ret) { |
1026 | pr_err("failed to find firmware (%d)\n", ret); | 840 | pr_err("failed to find firmware (%d)\n", ret); |
1027 | goto done; | 841 | goto done; |
1028 | } | 842 | } |
1029 | 843 | ||
844 | cardp->fw = fw; | ||
1030 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { | 845 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { |
1031 | ret = -EINVAL; | 846 | ret = -EINVAL; |
1032 | goto release_fw; | 847 | goto release_fw; |
@@ -1053,7 +868,7 @@ restart: | |||
1053 | do { | 868 | do { |
1054 | int j = 0; | 869 | int j = 0; |
1055 | i++; | 870 | i++; |
1056 | if_usb_issue_boot_command(cardp, cmd); | 871 | if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB); |
1057 | /* wait for command response */ | 872 | /* wait for command response */ |
1058 | do { | 873 | do { |
1059 | j++; | 874 | j++; |
@@ -1109,13 +924,27 @@ restart: | |||
1109 | goto release_fw; | 924 | goto release_fw; |
1110 | } | 925 | } |
1111 | 926 | ||
927 | cardp->priv->fw_ready = 1; | ||
928 | if_usb_submit_rx_urb(cardp); | ||
929 | |||
930 | if (lbs_start_card(priv)) | ||
931 | goto release_fw; | ||
932 | |||
933 | if_usb_setup_firmware(priv); | ||
934 | |||
935 | /* | ||
936 | * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | ||
937 | */ | ||
938 | priv->wol_criteria = EHS_REMOVE_WAKEUP; | ||
939 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | ||
940 | priv->ehs_remove_supported = false; | ||
941 | |||
1112 | release_fw: | 942 | release_fw: |
1113 | release_firmware(cardp->fw); | 943 | release_firmware(cardp->fw); |
1114 | cardp->fw = NULL; | 944 | cardp->fw = NULL; |
1115 | 945 | ||
1116 | done: | 946 | done: |
1117 | lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); | 947 | lbs_deb_leave(LBS_DEB_USB); |
1118 | return ret; | ||
1119 | } | 948 | } |
1120 | 949 | ||
1121 | 950 | ||
@@ -1128,8 +957,10 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) | |||
1128 | 957 | ||
1129 | lbs_deb_enter(LBS_DEB_USB); | 958 | lbs_deb_enter(LBS_DEB_USB); |
1130 | 959 | ||
1131 | if (priv->psstate != PS_STATE_FULL_POWER) | 960 | if (priv->psstate != PS_STATE_FULL_POWER) { |
1132 | return -1; | 961 | ret = -1; |
962 | goto out; | ||
963 | } | ||
1133 | 964 | ||
1134 | #ifdef CONFIG_OLPC | 965 | #ifdef CONFIG_OLPC |
1135 | if (machine_is_olpc()) { | 966 | if (machine_is_olpc()) { |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 957681dede17..e96ee0aa8439 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -878,6 +878,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
878 | priv->is_host_sleep_configured = 0; | 878 | priv->is_host_sleep_configured = 0; |
879 | priv->is_host_sleep_activated = 0; | 879 | priv->is_host_sleep_activated = 0; |
880 | init_waitqueue_head(&priv->host_sleep_q); | 880 | init_waitqueue_head(&priv->host_sleep_q); |
881 | init_waitqueue_head(&priv->fw_waitq); | ||
881 | mutex_init(&priv->lock); | 882 | mutex_init(&priv->lock); |
882 | 883 | ||
883 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, | 884 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, |
@@ -1033,7 +1034,11 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1033 | lbs_deb_enter(LBS_DEB_MAIN); | 1034 | lbs_deb_enter(LBS_DEB_MAIN); |
1034 | 1035 | ||
1035 | lbs_remove_mesh(priv); | 1036 | lbs_remove_mesh(priv); |
1036 | lbs_scan_deinit(priv); | 1037 | |
1038 | if (priv->wiphy_registered) | ||
1039 | lbs_scan_deinit(priv); | ||
1040 | |||
1041 | lbs_wait_for_firmware_load(priv); | ||
1037 | 1042 | ||
1038 | /* worker thread destruction blocks on the in-flight command which | 1043 | /* worker thread destruction blocks on the in-flight command which |
1039 | * should have been cleared already in lbs_stop_card(). | 1044 | * should have been cleared already in lbs_stop_card(). |
@@ -1128,6 +1133,11 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1128 | goto out; | 1133 | goto out; |
1129 | dev = priv->dev; | 1134 | dev = priv->dev; |
1130 | 1135 | ||
1136 | /* If the netdev isn't registered, it means that lbs_start_card() was | ||
1137 | * never called so we have nothing to do here. */ | ||
1138 | if (dev->reg_state != NETREG_REGISTERED) | ||
1139 | goto out; | ||
1140 | |||
1131 | netif_stop_queue(dev); | 1141 | netif_stop_queue(dev); |
1132 | netif_carrier_off(dev); | 1142 | netif_carrier_off(dev); |
1133 | 1143 | ||
@@ -1177,111 +1187,6 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | |||
1177 | } | 1187 | } |
1178 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); | 1188 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1179 | 1189 | ||
1180 | /** | ||
1181 | * lbs_get_firmware - Retrieves two-stage firmware | ||
1182 | * | ||
1183 | * @dev: A pointer to &device structure | ||
1184 | * @user_helper: User-defined helper firmware file | ||
1185 | * @user_mainfw: User-defined main firmware file | ||
1186 | * @card_model: Bus-specific card model ID used to filter firmware table | ||
1187 | * elements | ||
1188 | * @fw_table: Table of firmware file names and device model numbers | ||
1189 | * terminated by an entry with a NULL helper name | ||
1190 | * @helper: On success, the helper firmware; caller must free | ||
1191 | * @mainfw: On success, the main firmware; caller must free | ||
1192 | * | ||
1193 | * returns: 0 on success, non-zero on failure | ||
1194 | */ | ||
1195 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
1196 | const char *user_mainfw, u32 card_model, | ||
1197 | const struct lbs_fw_table *fw_table, | ||
1198 | const struct firmware **helper, | ||
1199 | const struct firmware **mainfw) | ||
1200 | { | ||
1201 | const struct lbs_fw_table *iter; | ||
1202 | int ret; | ||
1203 | |||
1204 | BUG_ON(helper == NULL); | ||
1205 | BUG_ON(mainfw == NULL); | ||
1206 | |||
1207 | /* Try user-specified firmware first */ | ||
1208 | if (user_helper) { | ||
1209 | ret = request_firmware(helper, user_helper, dev); | ||
1210 | if (ret) { | ||
1211 | dev_err(dev, "couldn't find helper firmware %s\n", | ||
1212 | user_helper); | ||
1213 | goto fail; | ||
1214 | } | ||
1215 | } | ||
1216 | if (user_mainfw) { | ||
1217 | ret = request_firmware(mainfw, user_mainfw, dev); | ||
1218 | if (ret) { | ||
1219 | dev_err(dev, "couldn't find main firmware %s\n", | ||
1220 | user_mainfw); | ||
1221 | goto fail; | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | if (*helper && *mainfw) | ||
1226 | return 0; | ||
1227 | |||
1228 | /* Otherwise search for firmware to use. If neither the helper or | ||
1229 | * the main firmware were specified by the user, then we need to | ||
1230 | * make sure that found helper & main are from the same entry in | ||
1231 | * fw_table. | ||
1232 | */ | ||
1233 | iter = fw_table; | ||
1234 | while (iter && iter->helper) { | ||
1235 | if (iter->model != card_model) | ||
1236 | goto next; | ||
1237 | |||
1238 | if (*helper == NULL) { | ||
1239 | ret = request_firmware(helper, iter->helper, dev); | ||
1240 | if (ret) | ||
1241 | goto next; | ||
1242 | |||
1243 | /* If the device has one-stage firmware (ie cf8305) and | ||
1244 | * we've got it then we don't need to bother with the | ||
1245 | * main firmware. | ||
1246 | */ | ||
1247 | if (iter->fwname == NULL) | ||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | if (*mainfw == NULL) { | ||
1252 | ret = request_firmware(mainfw, iter->fwname, dev); | ||
1253 | if (ret && !user_helper) { | ||
1254 | /* Clear the helper if it wasn't user-specified | ||
1255 | * and the main firmware load failed, to ensure | ||
1256 | * we don't have mismatched firmware pairs. | ||
1257 | */ | ||
1258 | release_firmware(*helper); | ||
1259 | *helper = NULL; | ||
1260 | } | ||
1261 | } | ||
1262 | |||
1263 | if (*helper && *mainfw) | ||
1264 | return 0; | ||
1265 | |||
1266 | next: | ||
1267 | iter++; | ||
1268 | } | ||
1269 | |||
1270 | fail: | ||
1271 | /* Failed */ | ||
1272 | if (*helper) { | ||
1273 | release_firmware(*helper); | ||
1274 | *helper = NULL; | ||
1275 | } | ||
1276 | if (*mainfw) { | ||
1277 | release_firmware(*mainfw); | ||
1278 | *mainfw = NULL; | ||
1279 | } | ||
1280 | |||
1281 | return -ENOENT; | ||
1282 | } | ||
1283 | EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
1284 | |||
1285 | static int __init lbs_init_module(void) | 1190 | static int __init lbs_init_module(void) |
1286 | { | 1191 | { |
1287 | lbs_deb_enter(LBS_DEB_MAIN); | 1192 | lbs_deb_enter(LBS_DEB_MAIN); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2d913644d92b..03c0c6b1372c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -699,6 +699,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
699 | ieee80211_is_probe_resp(mgmt->frame_control)) | 699 | ieee80211_is_probe_resp(mgmt->frame_control)) |
700 | mgmt->u.beacon.timestamp = cpu_to_le64( | 700 | mgmt->u.beacon.timestamp = cpu_to_le64( |
701 | rx_status.mactime + | 701 | rx_status.mactime + |
702 | (data->tsf_offset - data2->tsf_offset) + | ||
702 | 24 * 8 * 10 / txrate->bitrate); | 703 | 24 * 8 * 10 / txrate->bitrate); |
703 | 704 | ||
704 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 705 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c7e89188c350..c78ea873a63a 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1162,6 +1162,17 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1162 | priv->user_scan_cfg->num_ssids = request->n_ssids; | 1162 | priv->user_scan_cfg->num_ssids = request->n_ssids; |
1163 | priv->user_scan_cfg->ssid_list = request->ssids; | 1163 | priv->user_scan_cfg->ssid_list = request->ssids; |
1164 | 1164 | ||
1165 | if (request->ie && request->ie_len) { | ||
1166 | for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { | ||
1167 | if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) | ||
1168 | continue; | ||
1169 | priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN; | ||
1170 | memcpy(&priv->vs_ie[i].ie, request->ie, | ||
1171 | request->ie_len); | ||
1172 | break; | ||
1173 | } | ||
1174 | } | ||
1175 | |||
1165 | for (i = 0; i < request->n_channels; i++) { | 1176 | for (i = 0; i < request->n_channels; i++) { |
1166 | chan = request->channels[i]; | 1177 | chan = request->channels[i]; |
1167 | priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; | 1178 | priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; |
@@ -1179,6 +1190,15 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1179 | if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg)) | 1190 | if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg)) |
1180 | return -EFAULT; | 1191 | return -EFAULT; |
1181 | 1192 | ||
1193 | if (request->ie && request->ie_len) { | ||
1194 | for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { | ||
1195 | if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) { | ||
1196 | priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR; | ||
1197 | memset(&priv->vs_ie[i].ie, 0, | ||
1198 | MWIFIEX_MAX_VSIE_LEN); | ||
1199 | } | ||
1200 | } | ||
1201 | } | ||
1182 | return 0; | 1202 | return 0; |
1183 | } | 1203 | } |
1184 | 1204 | ||
@@ -1422,6 +1442,7 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1422 | void *wdev_priv; | 1442 | void *wdev_priv; |
1423 | struct wireless_dev *wdev; | 1443 | struct wireless_dev *wdev; |
1424 | struct ieee80211_sta_ht_cap *ht_info; | 1444 | struct ieee80211_sta_ht_cap *ht_info; |
1445 | u8 *country_code; | ||
1425 | 1446 | ||
1426 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1447 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); |
1427 | if (!wdev) { | 1448 | if (!wdev) { |
@@ -1438,6 +1459,7 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1438 | } | 1459 | } |
1439 | wdev->iftype = NL80211_IFTYPE_STATION; | 1460 | wdev->iftype = NL80211_IFTYPE_STATION; |
1440 | wdev->wiphy->max_scan_ssids = 10; | 1461 | wdev->wiphy->max_scan_ssids = 10; |
1462 | wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; | ||
1441 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1463 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1442 | BIT(NL80211_IFTYPE_ADHOC); | 1464 | BIT(NL80211_IFTYPE_ADHOC); |
1443 | 1465 | ||
@@ -1460,8 +1482,8 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1460 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 1482 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
1461 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1483 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
1462 | 1484 | ||
1463 | /* Reserve space for bss band information */ | 1485 | /* Reserve space for mwifiex specific private data for BSS */ |
1464 | wdev->wiphy->bss_priv_size = sizeof(u8); | 1486 | wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
1465 | 1487 | ||
1466 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; | 1488 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; |
1467 | 1489 | ||
@@ -1484,6 +1506,11 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv) | |||
1484 | "info: successfully registered wiphy device\n"); | 1506 | "info: successfully registered wiphy device\n"); |
1485 | } | 1507 | } |
1486 | 1508 | ||
1509 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); | ||
1510 | if (country_code && regulatory_hint(wdev->wiphy, country_code)) | ||
1511 | dev_err(priv->adapter->dev, | ||
1512 | "%s: regulatory_hint failed\n", __func__); | ||
1513 | |||
1487 | priv->wdev = wdev; | 1514 | priv->wdev = wdev; |
1488 | 1515 | ||
1489 | return ret; | 1516 | return ret; |
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index 2fe1c33765b8..560871b0e236 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c | |||
@@ -71,6 +71,37 @@ u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, | |||
71 | 71 | ||
72 | static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; | 72 | static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; |
73 | 73 | ||
74 | struct region_code_mapping { | ||
75 | u8 code; | ||
76 | u8 region[IEEE80211_COUNTRY_STRING_LEN]; | ||
77 | }; | ||
78 | |||
79 | static struct region_code_mapping region_code_mapping_t[] = { | ||
80 | { 0x10, "US " }, /* US FCC */ | ||
81 | { 0x20, "CA " }, /* IC Canada */ | ||
82 | { 0x30, "EU " }, /* ETSI */ | ||
83 | { 0x31, "ES " }, /* Spain */ | ||
84 | { 0x32, "FR " }, /* France */ | ||
85 | { 0x40, "JP " }, /* Japan */ | ||
86 | { 0x41, "JP " }, /* Japan */ | ||
87 | { 0x50, "CN " }, /* China */ | ||
88 | }; | ||
89 | |||
90 | /* This function converts integer code to region string */ | ||
91 | u8 *mwifiex_11d_code_2_region(u8 code) | ||
92 | { | ||
93 | u8 i; | ||
94 | u8 size = sizeof(region_code_mapping_t)/ | ||
95 | sizeof(struct region_code_mapping); | ||
96 | |||
97 | /* Look for code in mapping table */ | ||
98 | for (i = 0; i < size; i++) | ||
99 | if (region_code_mapping_t[i].code == code) | ||
100 | return region_code_mapping_t[i].region; | ||
101 | |||
102 | return NULL; | ||
103 | } | ||
104 | |||
74 | /* | 105 | /* |
75 | * This function maps an index in supported rates table into | 106 | * This function maps an index in supported rates table into |
76 | * the corresponding data rate. | 107 | * the corresponding data rate. |
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 1a845074c52a..a870b5885c09 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c | |||
@@ -212,7 +212,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, | |||
212 | p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); | 212 | p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); |
213 | p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); | 213 | p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); |
214 | p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); | 214 | p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); |
215 | p += sprintf(p, "region_code = \"%02x\"\n", info.region_code); | 215 | p += sprintf(p, "country_code = \"%s\"\n", info.country_code); |
216 | 216 | ||
217 | netdev_for_each_mc_addr(ha, netdev) | 217 | netdev_for_each_mc_addr(ha, netdev) |
218 | p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", | 218 | p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index bb26114bdb96..6b15449a4cb7 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -104,6 +104,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
104 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) | 104 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) |
105 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 105 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
106 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 106 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
107 | #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) | ||
107 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) | 108 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) |
108 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) | 109 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) |
109 | 110 | ||
@@ -818,7 +819,7 @@ struct host_cmd_ds_txpwr_cfg { | |||
818 | struct mwifiex_bcn_param { | 819 | struct mwifiex_bcn_param { |
819 | u8 bssid[ETH_ALEN]; | 820 | u8 bssid[ETH_ALEN]; |
820 | u8 rssi; | 821 | u8 rssi; |
821 | __le32 timestamp[2]; | 822 | __le64 timestamp; |
822 | __le16 beacon_period; | 823 | __le16 beacon_period; |
823 | __le16 cap_info_bitmap; | 824 | __le16 cap_info_bitmap; |
824 | } __packed; | 825 | } __packed; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 54bb4839b57c..0d55c5b542d7 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -131,6 +131,8 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) | |||
131 | priv->wmm_qosinfo = 0; | 131 | priv->wmm_qosinfo = 0; |
132 | priv->curr_bcn_buf = NULL; | 132 | priv->curr_bcn_buf = NULL; |
133 | priv->curr_bcn_size = 0; | 133 | priv->curr_bcn_size = 0; |
134 | priv->wps_ie = NULL; | ||
135 | priv->wps_ie_len = 0; | ||
134 | 136 | ||
135 | priv->scan_block = false; | 137 | priv->scan_block = false; |
136 | 138 | ||
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 99c06649f94c..f0f95524e96b 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -96,7 +96,7 @@ struct mwifiex_bss_info { | |||
96 | u32 bss_mode; | 96 | u32 bss_mode; |
97 | struct cfg80211_ssid ssid; | 97 | struct cfg80211_ssid ssid; |
98 | u32 bss_chan; | 98 | u32 bss_chan; |
99 | u32 region_code; | 99 | u8 country_code[3]; |
100 | u32 media_connected; | 100 | u32 media_connected; |
101 | u32 max_power_level; | 101 | u32 max_power_level; |
102 | u32 min_power_level; | 102 | u32 min_power_level; |
@@ -303,6 +303,7 @@ struct mwifiex_ds_misc_subsc_evt { | |||
303 | 303 | ||
304 | #define MWIFIEX_MAX_VSIE_LEN (256) | 304 | #define MWIFIEX_MAX_VSIE_LEN (256) |
305 | #define MWIFIEX_MAX_VSIE_NUM (8) | 305 | #define MWIFIEX_MAX_VSIE_NUM (8) |
306 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 | ||
306 | #define MWIFIEX_VSIE_MASK_SCAN 0x01 | 307 | #define MWIFIEX_VSIE_MASK_SCAN 0x01 |
307 | #define MWIFIEX_VSIE_MASK_ASSOC 0x02 | 308 | #define MWIFIEX_VSIE_MASK_ASSOC 0x02 |
308 | #define MWIFIEX_VSIE_MASK_ADHOC 0x04 | 309 | #define MWIFIEX_VSIE_MASK_ADHOC 0x04 |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index bca8b6d52273..8a390982463e 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -118,15 +118,15 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, | |||
118 | *buffer += sizeof(tsf_tlv.header); | 118 | *buffer += sizeof(tsf_tlv.header); |
119 | 119 | ||
120 | /* TSF at the time when beacon/probe_response was received */ | 120 | /* TSF at the time when beacon/probe_response was received */ |
121 | tsf_val = cpu_to_le64(bss_desc->network_tsf); | 121 | tsf_val = cpu_to_le64(bss_desc->fw_tsf); |
122 | memcpy(*buffer, &tsf_val, sizeof(tsf_val)); | 122 | memcpy(*buffer, &tsf_val, sizeof(tsf_val)); |
123 | *buffer += sizeof(tsf_val); | 123 | *buffer += sizeof(tsf_val); |
124 | 124 | ||
125 | memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); | 125 | tsf_val = cpu_to_le64(bss_desc->timestamp); |
126 | 126 | ||
127 | dev_dbg(priv->adapter->dev, | 127 | dev_dbg(priv->adapter->dev, |
128 | "info: %s: TSF offset calc: %016llx - %016llx\n", | 128 | "info: %s: TSF offset calc: %016llx - %016llx\n", |
129 | __func__, tsf_val, bss_desc->network_tsf); | 129 | __func__, bss_desc->timestamp, bss_desc->fw_tsf); |
130 | 130 | ||
131 | memcpy(*buffer, &tsf_val, sizeof(tsf_val)); | 131 | memcpy(*buffer, &tsf_val, sizeof(tsf_val)); |
132 | *buffer += sizeof(tsf_val); | 132 | *buffer += sizeof(tsf_val); |
@@ -225,6 +225,48 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, | |||
225 | } | 225 | } |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * This function appends a WPS IE. It is called from the network join command | ||
229 | * preparation routine. | ||
230 | * | ||
231 | * If the IE buffer has been setup by the application, this routine appends | ||
232 | * the buffer as a WPS TLV type to the request. | ||
233 | */ | ||
234 | static int | ||
235 | mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer) | ||
236 | { | ||
237 | int retLen = 0; | ||
238 | struct mwifiex_ie_types_header ie_header; | ||
239 | |||
240 | if (!buffer || !*buffer) | ||
241 | return 0; | ||
242 | |||
243 | /* | ||
244 | * If there is a wps ie buffer setup, append it to the return | ||
245 | * parameter buffer pointer. | ||
246 | */ | ||
247 | if (priv->wps_ie_len) { | ||
248 | dev_dbg(priv->adapter->dev, "cmd: append wps ie %d to %p\n", | ||
249 | priv->wps_ie_len, *buffer); | ||
250 | |||
251 | /* Wrap the generic IE buffer with a pass through TLV type */ | ||
252 | ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
253 | ie_header.len = cpu_to_le16(priv->wps_ie_len); | ||
254 | memcpy(*buffer, &ie_header, sizeof(ie_header)); | ||
255 | *buffer += sizeof(ie_header); | ||
256 | retLen += sizeof(ie_header); | ||
257 | |||
258 | memcpy(*buffer, priv->wps_ie, priv->wps_ie_len); | ||
259 | *buffer += priv->wps_ie_len; | ||
260 | retLen += priv->wps_ie_len; | ||
261 | |||
262 | } | ||
263 | |||
264 | kfree(priv->wps_ie); | ||
265 | priv->wps_ie_len = 0; | ||
266 | return retLen; | ||
267 | } | ||
268 | |||
269 | /* | ||
228 | * This function appends a WAPI IE. | 270 | * This function appends a WAPI IE. |
229 | * | 271 | * |
230 | * This function is called from the network join command preparation routine. | 272 | * This function is called from the network join command preparation routine. |
@@ -480,6 +522,8 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, | |||
480 | if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) | 522 | if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) |
481 | mwifiex_cmd_append_wapi_ie(priv, &pos); | 523 | mwifiex_cmd_append_wapi_ie(priv, &pos); |
482 | 524 | ||
525 | if (priv->wps.session_enable && priv->wps_ie_len) | ||
526 | mwifiex_cmd_append_wps_ie(priv, &pos); | ||
483 | 527 | ||
484 | mwifiex_cmd_append_generic_ie(priv, &pos); | 528 | mwifiex_cmd_append_generic_ie(priv, &pos); |
485 | 529 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9d1b3ca6334b..245b7329e0c9 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -292,29 +292,28 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) | |||
292 | } | 292 | } |
293 | 293 | ||
294 | /* | 294 | /* |
295 | * This function initializes the hardware and firmware. | 295 | * This function gets firmware and initializes it. |
296 | * | 296 | * |
297 | * The main initialization steps followed are - | 297 | * The main initialization steps followed are - |
298 | * - Download the correct firmware to card | 298 | * - Download the correct firmware to card |
299 | * - Allocate and initialize the adapter structure | ||
300 | * - Initialize the private structures | ||
301 | * - Issue the init commands to firmware | 299 | * - Issue the init commands to firmware |
302 | */ | 300 | */ |
303 | static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | 301 | static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) |
304 | { | 302 | { |
305 | int ret, err; | 303 | int ret; |
304 | char fmt[64]; | ||
305 | struct mwifiex_private *priv; | ||
306 | struct mwifiex_adapter *adapter = context; | ||
306 | struct mwifiex_fw_image fw; | 307 | struct mwifiex_fw_image fw; |
307 | 308 | ||
308 | memset(&fw, 0, sizeof(struct mwifiex_fw_image)); | 309 | if (!firmware) { |
309 | 310 | dev_err(adapter->dev, | |
310 | err = request_firmware(&adapter->firmware, adapter->fw_name, | 311 | "Failed to get firmware %s\n", adapter->fw_name); |
311 | adapter->dev); | ||
312 | if (err < 0) { | ||
313 | dev_err(adapter->dev, "request_firmware() returned" | ||
314 | " error code %#x\n", err); | ||
315 | ret = -1; | ||
316 | goto done; | 312 | goto done; |
317 | } | 313 | } |
314 | |||
315 | memset(&fw, 0, sizeof(struct mwifiex_fw_image)); | ||
316 | adapter->firmware = firmware; | ||
318 | fw.fw_buf = (u8 *) adapter->firmware->data; | 317 | fw.fw_buf = (u8 *) adapter->firmware->data; |
319 | fw.fw_len = adapter->firmware->size; | 318 | fw.fw_len = adapter->firmware->size; |
320 | 319 | ||
@@ -335,17 +334,54 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | |||
335 | /* Wait for mwifiex_init to complete */ | 334 | /* Wait for mwifiex_init to complete */ |
336 | wait_event_interruptible(adapter->init_wait_q, | 335 | wait_event_interruptible(adapter->init_wait_q, |
337 | adapter->init_wait_q_woken); | 336 | adapter->init_wait_q_woken); |
338 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) { | 337 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) |
339 | ret = -1; | ||
340 | goto done; | 338 | goto done; |
339 | |||
340 | priv = adapter->priv[0]; | ||
341 | if (mwifiex_register_cfg80211(priv) != 0) { | ||
342 | dev_err(adapter->dev, "cannot register with cfg80211\n"); | ||
343 | goto err_init_fw; | ||
344 | } | ||
345 | |||
346 | rtnl_lock(); | ||
347 | /* Create station interface by default */ | ||
348 | if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", | ||
349 | NL80211_IFTYPE_STATION, NULL, NULL)) { | ||
350 | dev_err(adapter->dev, "cannot create default STA interface\n"); | ||
351 | goto err_add_intf; | ||
341 | } | 352 | } |
342 | ret = 0; | 353 | rtnl_unlock(); |
354 | |||
355 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | ||
356 | dev_notice(adapter->dev, "driver_version = %s\n", fmt); | ||
357 | goto done; | ||
343 | 358 | ||
359 | err_add_intf: | ||
360 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); | ||
361 | rtnl_unlock(); | ||
362 | err_init_fw: | ||
363 | pr_debug("info: %s: unregister device\n", __func__); | ||
364 | adapter->if_ops.unregister_dev(adapter); | ||
344 | done: | 365 | done: |
345 | if (adapter->firmware) | 366 | release_firmware(adapter->firmware); |
346 | release_firmware(adapter->firmware); | 367 | complete(&adapter->fw_load); |
347 | if (ret) | 368 | return; |
348 | ret = -1; | 369 | } |
370 | |||
371 | /* | ||
372 | * This function initializes the hardware and gets firmware. | ||
373 | */ | ||
374 | static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | ||
375 | { | ||
376 | int ret; | ||
377 | |||
378 | init_completion(&adapter->fw_load); | ||
379 | ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name, | ||
380 | adapter->dev, GFP_KERNEL, adapter, | ||
381 | mwifiex_fw_dpc); | ||
382 | if (ret < 0) | ||
383 | dev_err(adapter->dev, | ||
384 | "request_firmware_nowait() returned error %d\n", ret); | ||
349 | return ret; | 385 | return ret; |
350 | } | 386 | } |
351 | 387 | ||
@@ -650,8 +686,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
650 | struct mwifiex_if_ops *if_ops, u8 iface_type) | 686 | struct mwifiex_if_ops *if_ops, u8 iface_type) |
651 | { | 687 | { |
652 | struct mwifiex_adapter *adapter; | 688 | struct mwifiex_adapter *adapter; |
653 | char fmt[64]; | ||
654 | struct mwifiex_private *priv; | ||
655 | 689 | ||
656 | if (down_interruptible(sem)) | 690 | if (down_interruptible(sem)) |
657 | goto exit_sem_err; | 691 | goto exit_sem_err; |
@@ -692,37 +726,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
692 | goto err_init_fw; | 726 | goto err_init_fw; |
693 | } | 727 | } |
694 | 728 | ||
695 | priv = adapter->priv[0]; | ||
696 | |||
697 | if (mwifiex_register_cfg80211(priv) != 0) { | ||
698 | dev_err(adapter->dev, "cannot register netdevice" | ||
699 | " with cfg80211\n"); | ||
700 | goto err_init_fw; | ||
701 | } | ||
702 | |||
703 | rtnl_lock(); | ||
704 | /* Create station interface by default */ | ||
705 | if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", | ||
706 | NL80211_IFTYPE_STATION, NULL, NULL)) { | ||
707 | rtnl_unlock(); | ||
708 | dev_err(adapter->dev, "cannot create default station" | ||
709 | " interface\n"); | ||
710 | goto err_add_intf; | ||
711 | } | ||
712 | |||
713 | rtnl_unlock(); | ||
714 | |||
715 | up(sem); | 729 | up(sem); |
716 | |||
717 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | ||
718 | dev_notice(adapter->dev, "driver_version = %s\n", fmt); | ||
719 | |||
720 | return 0; | 730 | return 0; |
721 | 731 | ||
722 | err_add_intf: | ||
723 | rtnl_lock(); | ||
724 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); | ||
725 | rtnl_unlock(); | ||
726 | err_init_fw: | 732 | err_init_fw: |
727 | pr_debug("info: %s: unregister device\n", __func__); | 733 | pr_debug("info: %s: unregister device\n", __func__); |
728 | adapter->if_ops.unregister_dev(adapter); | 734 | adapter->if_ops.unregister_dev(adapter); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index fcccf6b1373f..a4000f9608d5 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -260,8 +260,8 @@ struct mwifiex_bssdescriptor { | |||
260 | * BAND_A(0X04): 'a' band | 260 | * BAND_A(0X04): 'a' band |
261 | */ | 261 | */ |
262 | u16 bss_band; | 262 | u16 bss_band; |
263 | u64 network_tsf; | 263 | u64 fw_tsf; |
264 | u8 time_stamp[8]; | 264 | u64 timestamp; |
265 | union ieee_types_phy_param_set phy_param_set; | 265 | union ieee_types_phy_param_set phy_param_set; |
266 | union ieee_types_ss_param_set ss_param_set; | 266 | union ieee_types_ss_param_set ss_param_set; |
267 | u16 cap_info_bitmap; | 267 | u16 cap_info_bitmap; |
@@ -407,6 +407,8 @@ struct mwifiex_private { | |||
407 | struct host_cmd_ds_802_11_key_material aes_key; | 407 | struct host_cmd_ds_802_11_key_material aes_key; |
408 | u8 wapi_ie[256]; | 408 | u8 wapi_ie[256]; |
409 | u8 wapi_ie_len; | 409 | u8 wapi_ie_len; |
410 | u8 *wps_ie; | ||
411 | u8 wps_ie_len; | ||
410 | u8 wmm_required; | 412 | u8 wmm_required; |
411 | u8 wmm_enabled; | 413 | u8 wmm_enabled; |
412 | u8 wmm_qosinfo; | 414 | u8 wmm_qosinfo; |
@@ -520,6 +522,11 @@ struct cmd_ctrl_node { | |||
520 | u8 cmd_wait_q_woken; | 522 | u8 cmd_wait_q_woken; |
521 | }; | 523 | }; |
522 | 524 | ||
525 | struct mwifiex_bss_priv { | ||
526 | u8 band; | ||
527 | u64 fw_tsf; | ||
528 | }; | ||
529 | |||
523 | struct mwifiex_if_ops { | 530 | struct mwifiex_if_ops { |
524 | int (*init_if) (struct mwifiex_adapter *); | 531 | int (*init_if) (struct mwifiex_adapter *); |
525 | void (*cleanup_if) (struct mwifiex_adapter *); | 532 | void (*cleanup_if) (struct mwifiex_adapter *); |
@@ -653,6 +660,7 @@ struct mwifiex_adapter { | |||
653 | u8 scan_wait_q_woken; | 660 | u8 scan_wait_q_woken; |
654 | struct cmd_ctrl_node *cmd_queued; | 661 | struct cmd_ctrl_node *cmd_queued; |
655 | spinlock_t queue_lock; /* lock for tx queues */ | 662 | spinlock_t queue_lock; /* lock for tx queues */ |
663 | struct completion fw_load; | ||
656 | }; | 664 | }; |
657 | 665 | ||
658 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 666 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -950,13 +958,10 @@ int mwifiex_bss_set_channel(struct mwifiex_private *, | |||
950 | int mwifiex_get_bss_info(struct mwifiex_private *, | 958 | int mwifiex_get_bss_info(struct mwifiex_private *, |
951 | struct mwifiex_bss_info *); | 959 | struct mwifiex_bss_info *); |
952 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | 960 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, |
953 | u8 *bssid, s32 rssi, u8 *ie_buf, | 961 | struct cfg80211_bss *bss, |
954 | size_t ie_len, u16 beacon_period, | ||
955 | u16 cap_info_bitmap, u8 band, | ||
956 | struct mwifiex_bssdescriptor *bss_desc); | 962 | struct mwifiex_bssdescriptor *bss_desc); |
957 | int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | 963 | int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, |
958 | struct mwifiex_bssdescriptor *bss_entry, | 964 | struct mwifiex_bssdescriptor *bss_entry); |
959 | u8 *ie_buf, u32 ie_len); | ||
960 | int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | 965 | int mwifiex_check_network_compatibility(struct mwifiex_private *priv, |
961 | struct mwifiex_bssdescriptor *bss_desc); | 966 | struct mwifiex_bssdescriptor *bss_desc); |
962 | 967 | ||
@@ -965,6 +970,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
965 | u32 *flags, struct vif_params *params); | 970 | u32 *flags, struct vif_params *params); |
966 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); | 971 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); |
967 | 972 | ||
973 | u8 *mwifiex_11d_code_2_region(u8 code); | ||
968 | 974 | ||
969 | #ifdef CONFIG_DEBUG_FS | 975 | #ifdef CONFIG_DEBUG_FS |
970 | void mwifiex_debugfs_init(void); | 976 | void mwifiex_debugfs_init(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 5867facd415d..13fbc4eb1595 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -119,6 +119,9 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
119 | if (!adapter || !adapter->priv_num) | 119 | if (!adapter || !adapter->priv_num) |
120 | return; | 120 | return; |
121 | 121 | ||
122 | /* In case driver is removed when asynchronous FW load is in progress */ | ||
123 | wait_for_completion(&adapter->fw_load); | ||
124 | |||
122 | if (user_rmmod) { | 125 | if (user_rmmod) { |
123 | #ifdef CONFIG_PM | 126 | #ifdef CONFIG_PM |
124 | if (adapter->is_suspended) | 127 | if (adapter->is_suspended) |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index ef84a1a6742f..74f045715723 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1048,10 +1048,8 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, | |||
1048 | * This function parses provided beacon buffer and updates | 1048 | * This function parses provided beacon buffer and updates |
1049 | * respective fields in bss descriptor structure. | 1049 | * respective fields in bss descriptor structure. |
1050 | */ | 1050 | */ |
1051 | int | 1051 | int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, |
1052 | mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | 1052 | struct mwifiex_bssdescriptor *bss_entry) |
1053 | struct mwifiex_bssdescriptor *bss_entry, | ||
1054 | u8 *ie_buf, u32 ie_len) | ||
1055 | { | 1053 | { |
1056 | int ret = 0; | 1054 | int ret = 0; |
1057 | u8 element_id; | 1055 | u8 element_id; |
@@ -1073,10 +1071,8 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1073 | 1071 | ||
1074 | found_data_rate_ie = false; | 1072 | found_data_rate_ie = false; |
1075 | rate_size = 0; | 1073 | rate_size = 0; |
1076 | current_ptr = ie_buf; | 1074 | current_ptr = bss_entry->beacon_buf; |
1077 | bytes_left = ie_len; | 1075 | bytes_left = bss_entry->beacon_buf_size; |
1078 | bss_entry->beacon_buf = ie_buf; | ||
1079 | bss_entry->beacon_buf_size = ie_len; | ||
1080 | 1076 | ||
1081 | /* Process variable IE */ | 1077 | /* Process variable IE */ |
1082 | while (bytes_left >= 2) { | 1078 | while (bytes_left >= 2) { |
@@ -1447,15 +1443,12 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | |||
1447 | return ret; | 1443 | return ret; |
1448 | } | 1444 | } |
1449 | 1445 | ||
1450 | static int | 1446 | static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv, |
1451 | mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, | 1447 | struct cfg80211_bss *bss) |
1452 | s32 rssi, const u8 *ie_buf, size_t ie_len, | ||
1453 | u16 beacon_period, u16 cap_info_bitmap, u8 band) | ||
1454 | { | 1448 | { |
1455 | struct mwifiex_bssdescriptor *bss_desc; | 1449 | struct mwifiex_bssdescriptor *bss_desc; |
1456 | int ret; | 1450 | int ret; |
1457 | unsigned long flags; | 1451 | unsigned long flags; |
1458 | u8 *beacon_ie; | ||
1459 | 1452 | ||
1460 | /* Allocate and fill new bss descriptor */ | 1453 | /* Allocate and fill new bss descriptor */ |
1461 | bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), | 1454 | bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), |
@@ -1465,16 +1458,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, | |||
1465 | return -ENOMEM; | 1458 | return -ENOMEM; |
1466 | } | 1459 | } |
1467 | 1460 | ||
1468 | beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL); | 1461 | ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); |
1469 | if (!beacon_ie) { | ||
1470 | kfree(bss_desc); | ||
1471 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); | ||
1472 | return -ENOMEM; | ||
1473 | } | ||
1474 | |||
1475 | ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, | ||
1476 | ie_len, beacon_period, | ||
1477 | cap_info_bitmap, band, bss_desc); | ||
1478 | if (ret) | 1462 | if (ret) |
1479 | goto done; | 1463 | goto done; |
1480 | 1464 | ||
@@ -1514,7 +1498,6 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, | |||
1514 | 1498 | ||
1515 | done: | 1499 | done: |
1516 | kfree(bss_desc); | 1500 | kfree(bss_desc); |
1517 | kfree(beacon_ie); | ||
1518 | return 0; | 1501 | return 0; |
1519 | } | 1502 | } |
1520 | 1503 | ||
@@ -1620,14 +1603,16 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1620 | const u8 *ie_buf; | 1603 | const u8 *ie_buf; |
1621 | size_t ie_len; | 1604 | size_t ie_len; |
1622 | u16 channel = 0; | 1605 | u16 channel = 0; |
1623 | u64 network_tsf = 0; | 1606 | u64 fw_tsf = 0; |
1624 | u16 beacon_size = 0; | 1607 | u16 beacon_size = 0; |
1625 | u32 curr_bcn_bytes; | 1608 | u32 curr_bcn_bytes; |
1626 | u32 freq; | 1609 | u32 freq; |
1627 | u16 beacon_period; | 1610 | u16 beacon_period; |
1628 | u16 cap_info_bitmap; | 1611 | u16 cap_info_bitmap; |
1629 | u8 *current_ptr; | 1612 | u8 *current_ptr; |
1613 | u64 timestamp; | ||
1630 | struct mwifiex_bcn_param *bcn_param; | 1614 | struct mwifiex_bcn_param *bcn_param; |
1615 | struct mwifiex_bss_priv *bss_priv; | ||
1631 | 1616 | ||
1632 | if (bytes_left >= sizeof(beacon_size)) { | 1617 | if (bytes_left >= sizeof(beacon_size)) { |
1633 | /* Extract & convert beacon size from command buffer */ | 1618 | /* Extract & convert beacon size from command buffer */ |
@@ -1671,6 +1656,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1671 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ | 1656 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ |
1672 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | 1657 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); |
1673 | 1658 | ||
1659 | timestamp = le64_to_cpu(bcn_param->timestamp); | ||
1674 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | 1660 | beacon_period = le16_to_cpu(bcn_param->beacon_period); |
1675 | 1661 | ||
1676 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); | 1662 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); |
@@ -1710,14 +1696,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1710 | 1696 | ||
1711 | /* | 1697 | /* |
1712 | * If the TSF TLV was appended to the scan results, save this | 1698 | * If the TSF TLV was appended to the scan results, save this |
1713 | * entry's TSF value in the networkTSF field.The networkTSF is | 1699 | * entry's TSF value in the fw_tsf field. It is the firmware's |
1714 | * the firmware's TSF value at the time the beacon or probe | 1700 | * TSF value at the time the beacon or probe response was |
1715 | * response was received. | 1701 | * received. |
1716 | */ | 1702 | */ |
1717 | if (tsf_tlv) | 1703 | if (tsf_tlv) |
1718 | memcpy(&network_tsf, | 1704 | memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], |
1719 | &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], | 1705 | sizeof(fw_tsf)); |
1720 | sizeof(network_tsf)); | ||
1721 | 1706 | ||
1722 | if (channel) { | 1707 | if (channel) { |
1723 | struct ieee80211_channel *chan; | 1708 | struct ieee80211_channel *chan; |
@@ -1740,21 +1725,19 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1740 | 1725 | ||
1741 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | 1726 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
1742 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | 1727 | bss = cfg80211_inform_bss(priv->wdev->wiphy, |
1743 | chan, bssid, network_tsf, | 1728 | chan, bssid, timestamp, |
1744 | cap_info_bitmap, beacon_period, | 1729 | cap_info_bitmap, beacon_period, |
1745 | ie_buf, ie_len, rssi, GFP_KERNEL); | 1730 | ie_buf, ie_len, rssi, GFP_KERNEL); |
1746 | *(u8 *)bss->priv = band; | 1731 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; |
1747 | cfg80211_put_bss(bss); | 1732 | bss_priv->band = band; |
1748 | 1733 | bss_priv->fw_tsf = fw_tsf; | |
1749 | if (priv->media_connected && | 1734 | if (priv->media_connected && |
1750 | !memcmp(bssid, | 1735 | !memcmp(bssid, |
1751 | priv->curr_bss_params.bss_descriptor | 1736 | priv->curr_bss_params.bss_descriptor |
1752 | .mac_address, ETH_ALEN)) | 1737 | .mac_address, ETH_ALEN)) |
1753 | mwifiex_update_curr_bss_params | 1738 | mwifiex_update_curr_bss_params(priv, |
1754 | (priv, bssid, rssi, | 1739 | bss); |
1755 | ie_buf, ie_len, | 1740 | cfg80211_put_bss(bss); |
1756 | beacon_period, | ||
1757 | cap_info_bitmap, band); | ||
1758 | } | 1741 | } |
1759 | } else { | 1742 | } else { |
1760 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 1743 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f8012e2b7f7c..1aa45c4295bb 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -123,6 +123,9 @@ mwifiex_sdio_remove(struct sdio_func *func) | |||
123 | if (!adapter || !adapter->priv_num) | 123 | if (!adapter || !adapter->priv_num) |
124 | return; | 124 | return; |
125 | 125 | ||
126 | /* In case driver is removed when asynchronous FW load is in progress */ | ||
127 | wait_for_completion(&adapter->fw_load); | ||
128 | |||
126 | if (user_rmmod) { | 129 | if (user_rmmod) { |
127 | if (adapter->is_suspended) | 130 | if (adapter->is_suspended) |
128 | mwifiex_sdio_resume(adapter->dev); | 131 | mwifiex_sdio_resume(adapter->dev); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index e90c34d9c63d..1f7110577b9d 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -988,7 +988,7 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | |||
988 | rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; | 988 | rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; |
989 | rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; | 989 | rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; |
990 | 990 | ||
991 | dev_dbg(priv->adapter->dev, "Cfg Beacon Low Rssi event, " | 991 | dev_dbg(priv->adapter->dev, "Cfg Beacon High Rssi event, " |
992 | "RSSI:-%d dBm, Freq:%d\n", | 992 | "RSSI:-%d dBm, Freq:%d\n", |
993 | subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, | 993 | subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, |
994 | subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); | 994 | subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 8ba58d935328..58970e0f7d13 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -155,20 +155,29 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
155 | * information. | 155 | * information. |
156 | */ | 156 | */ |
157 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | 157 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, |
158 | u8 *bssid, s32 rssi, u8 *ie_buf, | 158 | struct cfg80211_bss *bss, |
159 | size_t ie_len, u16 beacon_period, | ||
160 | u16 cap_info_bitmap, u8 band, | ||
161 | struct mwifiex_bssdescriptor *bss_desc) | 159 | struct mwifiex_bssdescriptor *bss_desc) |
162 | { | 160 | { |
163 | int ret; | 161 | int ret; |
162 | u8 *beacon_ie; | ||
163 | struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; | ||
164 | 164 | ||
165 | memcpy(bss_desc->mac_address, bssid, ETH_ALEN); | 165 | beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies, |
166 | bss_desc->rssi = rssi; | 166 | GFP_KERNEL); |
167 | bss_desc->beacon_buf = ie_buf; | 167 | if (!beacon_ie) { |
168 | bss_desc->beacon_buf_size = ie_len; | 168 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); |
169 | bss_desc->beacon_period = beacon_period; | 169 | return -ENOMEM; |
170 | bss_desc->cap_info_bitmap = cap_info_bitmap; | 170 | } |
171 | bss_desc->bss_band = band; | 171 | |
172 | memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); | ||
173 | bss_desc->rssi = bss->signal; | ||
174 | bss_desc->beacon_buf = beacon_ie; | ||
175 | bss_desc->beacon_buf_size = bss->len_beacon_ies; | ||
176 | bss_desc->beacon_period = bss->beacon_interval; | ||
177 | bss_desc->cap_info_bitmap = bss->capability; | ||
178 | bss_desc->bss_band = bss_priv->band; | ||
179 | bss_desc->fw_tsf = bss_priv->fw_tsf; | ||
180 | bss_desc->timestamp = bss->tsf; | ||
172 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { | 181 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { |
173 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); | 182 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); |
174 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; | 183 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; |
@@ -180,9 +189,9 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
180 | else | 189 | else |
181 | bss_desc->bss_mode = NL80211_IFTYPE_STATION; | 190 | bss_desc->bss_mode = NL80211_IFTYPE_STATION; |
182 | 191 | ||
183 | ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc, | 192 | ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); |
184 | ie_buf, ie_len); | ||
185 | 193 | ||
194 | kfree(beacon_ie); | ||
186 | return ret; | 195 | return ret; |
187 | } | 196 | } |
188 | 197 | ||
@@ -197,7 +206,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
197 | int ret; | 206 | int ret; |
198 | struct mwifiex_adapter *adapter = priv->adapter; | 207 | struct mwifiex_adapter *adapter = priv->adapter; |
199 | struct mwifiex_bssdescriptor *bss_desc = NULL; | 208 | struct mwifiex_bssdescriptor *bss_desc = NULL; |
200 | u8 *beacon_ie = NULL; | ||
201 | 209 | ||
202 | priv->scan_block = false; | 210 | priv->scan_block = false; |
203 | 211 | ||
@@ -210,19 +218,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
210 | return -ENOMEM; | 218 | return -ENOMEM; |
211 | } | 219 | } |
212 | 220 | ||
213 | beacon_ie = kmemdup(bss->information_elements, | 221 | ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); |
214 | bss->len_beacon_ies, GFP_KERNEL); | ||
215 | if (!beacon_ie) { | ||
216 | kfree(bss_desc); | ||
217 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, | ||
222 | beacon_ie, bss->len_beacon_ies, | ||
223 | bss->beacon_interval, | ||
224 | bss->capability, | ||
225 | *(u8 *)bss->priv, bss_desc); | ||
226 | if (ret) | 222 | if (ret) |
227 | goto done; | 223 | goto done; |
228 | } | 224 | } |
@@ -269,7 +265,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
269 | (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor. | 265 | (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor. |
270 | ssid, &bss_desc->ssid))) { | 266 | ssid, &bss_desc->ssid))) { |
271 | kfree(bss_desc); | 267 | kfree(bss_desc); |
272 | kfree(beacon_ie); | ||
273 | return 0; | 268 | return 0; |
274 | } | 269 | } |
275 | 270 | ||
@@ -304,7 +299,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
304 | 299 | ||
305 | done: | 300 | done: |
306 | kfree(bss_desc); | 301 | kfree(bss_desc); |
307 | kfree(beacon_ie); | ||
308 | return ret; | 302 | return ret; |
309 | } | 303 | } |
310 | 304 | ||
@@ -468,7 +462,8 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, | |||
468 | 462 | ||
469 | info->bss_chan = bss_desc->channel; | 463 | info->bss_chan = bss_desc->channel; |
470 | 464 | ||
471 | info->region_code = adapter->region_code; | 465 | memcpy(info->country_code, priv->country_code, |
466 | IEEE80211_COUNTRY_STRING_LEN); | ||
472 | 467 | ||
473 | info->media_connected = priv->media_connected; | 468 | info->media_connected = priv->media_connected; |
474 | 469 | ||
@@ -996,6 +991,39 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, | |||
996 | } | 991 | } |
997 | 992 | ||
998 | /* | 993 | /* |
994 | * IOCTL request handler to set/reset WPS IE. | ||
995 | * | ||
996 | * The supplied WPS IE is treated as a opaque buffer. Only the first field | ||
997 | * is checked to internally enable WPS. If buffer length is zero, the existing | ||
998 | * WPS IE is reset. | ||
999 | */ | ||
1000 | static int mwifiex_set_wps_ie(struct mwifiex_private *priv, | ||
1001 | u8 *ie_data_ptr, u16 ie_len) | ||
1002 | { | ||
1003 | if (ie_len) { | ||
1004 | priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL); | ||
1005 | if (!priv->wps_ie) | ||
1006 | return -ENOMEM; | ||
1007 | if (ie_len > sizeof(priv->wps_ie)) { | ||
1008 | dev_dbg(priv->adapter->dev, | ||
1009 | "info: failed to copy WPS IE, too big\n"); | ||
1010 | kfree(priv->wps_ie); | ||
1011 | return -1; | ||
1012 | } | ||
1013 | memcpy(priv->wps_ie, ie_data_ptr, ie_len); | ||
1014 | priv->wps_ie_len = ie_len; | ||
1015 | dev_dbg(priv->adapter->dev, "cmd: Set wps_ie_len=%d IE=%#x\n", | ||
1016 | priv->wps_ie_len, priv->wps_ie[0]); | ||
1017 | } else { | ||
1018 | kfree(priv->wps_ie); | ||
1019 | priv->wps_ie_len = ie_len; | ||
1020 | dev_dbg(priv->adapter->dev, | ||
1021 | "info: Reset wps_ie_len=%d\n", priv->wps_ie_len); | ||
1022 | } | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | /* | ||
999 | * IOCTL request handler to set WAPI key. | 1027 | * IOCTL request handler to set WAPI key. |
1000 | * | 1028 | * |
1001 | * This function prepares the correct firmware command and | 1029 | * This function prepares the correct firmware command and |
@@ -1408,6 +1436,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, | |||
1408 | priv->wps.session_enable = true; | 1436 | priv->wps.session_enable = true; |
1409 | dev_dbg(priv->adapter->dev, | 1437 | dev_dbg(priv->adapter->dev, |
1410 | "info: WPS Session Enabled.\n"); | 1438 | "info: WPS Session Enabled.\n"); |
1439 | ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len); | ||
1411 | } | 1440 | } |
1412 | 1441 | ||
1413 | /* Append the passed data to the end of the | 1442 | /* Append the passed data to the end of the |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b48674b577e6..e30cc32f8279 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -5893,18 +5893,7 @@ static struct pci_driver mwl8k_driver = { | |||
5893 | .shutdown = __devexit_p(mwl8k_shutdown), | 5893 | .shutdown = __devexit_p(mwl8k_shutdown), |
5894 | }; | 5894 | }; |
5895 | 5895 | ||
5896 | static int __init mwl8k_init(void) | 5896 | module_pci_driver(mwl8k_driver); |
5897 | { | ||
5898 | return pci_register_driver(&mwl8k_driver); | ||
5899 | } | ||
5900 | |||
5901 | static void __exit mwl8k_exit(void) | ||
5902 | { | ||
5903 | pci_unregister_driver(&mwl8k_driver); | ||
5904 | } | ||
5905 | |||
5906 | module_init(mwl8k_init); | ||
5907 | module_exit(mwl8k_exit); | ||
5908 | 5897 | ||
5909 | MODULE_DESCRIPTION(MWL8K_DESC); | 5898 | MODULE_DESCRIPTION(MWL8K_DESC); |
5910 | MODULE_VERSION(MWL8K_VERSION); | 5899 | MODULE_VERSION(MWL8K_VERSION); |
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 4df8cf64b56c..400a35217644 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c | |||
@@ -379,11 +379,8 @@ void orinoco_cache_fw(struct orinoco_private *priv, int ap) | |||
379 | 379 | ||
380 | void orinoco_uncache_fw(struct orinoco_private *priv) | 380 | void orinoco_uncache_fw(struct orinoco_private *priv) |
381 | { | 381 | { |
382 | if (priv->cached_pri_fw) | 382 | release_firmware(priv->cached_pri_fw); |
383 | release_firmware(priv->cached_pri_fw); | 383 | release_firmware(priv->cached_fw); |
384 | if (priv->cached_fw) | ||
385 | release_firmware(priv->cached_fw); | ||
386 | |||
387 | priv->cached_pri_fw = NULL; | 384 | priv->cached_pri_fw = NULL; |
388 | priv->cached_fw = NULL; | 385 | priv->cached_fw = NULL; |
389 | } | 386 | } |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 45df728183fd..89318adc8c7f 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -667,15 +667,4 @@ static struct pci_driver p54p_driver = { | |||
667 | .driver.pm = P54P_PM_OPS, | 667 | .driver.pm = P54P_PM_OPS, |
668 | }; | 668 | }; |
669 | 669 | ||
670 | static int __init p54p_init(void) | 670 | module_pci_driver(p54p_driver); |
671 | { | ||
672 | return pci_register_driver(&p54p_driver); | ||
673 | } | ||
674 | |||
675 | static void __exit p54p_exit(void) | ||
676 | { | ||
677 | pci_unregister_driver(&p54p_driver); | ||
678 | } | ||
679 | |||
680 | module_init(p54p_init); | ||
681 | module_exit(p54p_exit); | ||
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 9b796cae4afe..a01606b36e03 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c | |||
@@ -693,8 +693,6 @@ mgt_update_addr(islpci_private *priv) | |||
693 | return ret; | 693 | return ret; |
694 | } | 694 | } |
695 | 695 | ||
696 | #define VEC_SIZE(a) ARRAY_SIZE(a) | ||
697 | |||
698 | int | 696 | int |
699 | mgt_commit(islpci_private *priv) | 697 | mgt_commit(islpci_private *priv) |
700 | { | 698 | { |
@@ -704,10 +702,10 @@ mgt_commit(islpci_private *priv) | |||
704 | if (islpci_get_state(priv) < PRV_STATE_INIT) | 702 | if (islpci_get_state(priv) < PRV_STATE_INIT) |
705 | return 0; | 703 | return 0; |
706 | 704 | ||
707 | rvalue = mgt_commit_list(priv, commit_part1, VEC_SIZE(commit_part1)); | 705 | rvalue = mgt_commit_list(priv, commit_part1, ARRAY_SIZE(commit_part1)); |
708 | 706 | ||
709 | if (priv->iw_mode != IW_MODE_MONITOR) | 707 | if (priv->iw_mode != IW_MODE_MONITOR) |
710 | rvalue |= mgt_commit_list(priv, commit_part2, VEC_SIZE(commit_part2)); | 708 | rvalue |= mgt_commit_list(priv, commit_part2, ARRAY_SIZE(commit_part2)); |
711 | 709 | ||
712 | u = OID_INL_MODE; | 710 | u = OID_INL_MODE; |
713 | rvalue |= mgt_commit_list(priv, &u, 1); | 711 | rvalue |= mgt_commit_list(priv, &u, 1); |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3a6b40239bc1..5e6b50143165 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1828,15 +1828,4 @@ static struct pci_driver rt2400pci_driver = { | |||
1828 | .resume = rt2x00pci_resume, | 1828 | .resume = rt2x00pci_resume, |
1829 | }; | 1829 | }; |
1830 | 1830 | ||
1831 | static int __init rt2400pci_init(void) | 1831 | module_pci_driver(rt2400pci_driver); |
1832 | { | ||
1833 | return pci_register_driver(&rt2400pci_driver); | ||
1834 | } | ||
1835 | |||
1836 | static void __exit rt2400pci_exit(void) | ||
1837 | { | ||
1838 | pci_unregister_driver(&rt2400pci_driver); | ||
1839 | } | ||
1840 | |||
1841 | module_init(rt2400pci_init); | ||
1842 | module_exit(rt2400pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index dcc0e1fcca77..136b849f11b5 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -2119,15 +2119,4 @@ static struct pci_driver rt2500pci_driver = { | |||
2119 | .resume = rt2x00pci_resume, | 2119 | .resume = rt2x00pci_resume, |
2120 | }; | 2120 | }; |
2121 | 2121 | ||
2122 | static int __init rt2500pci_init(void) | 2122 | module_pci_driver(rt2500pci_driver); |
2123 | { | ||
2124 | return pci_register_driver(&rt2500pci_driver); | ||
2125 | } | ||
2126 | |||
2127 | static void __exit rt2500pci_exit(void) | ||
2128 | { | ||
2129 | pci_unregister_driver(&rt2500pci_driver); | ||
2130 | } | ||
2131 | |||
2132 | module_init(rt2500pci_init); | ||
2133 | module_exit(rt2500pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 1de9c752c88b..c88fd3e61090 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1912,7 +1912,7 @@ static struct usb_device_id rt2500usb_device_table[] = { | |||
1912 | { USB_DEVICE(0x0b05, 0x1706) }, | 1912 | { USB_DEVICE(0x0b05, 0x1706) }, |
1913 | { USB_DEVICE(0x0b05, 0x1707) }, | 1913 | { USB_DEVICE(0x0b05, 0x1707) }, |
1914 | /* Belkin */ | 1914 | /* Belkin */ |
1915 | { USB_DEVICE(0x050d, 0x7050) }, | 1915 | { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050A ver. 2.x */ |
1916 | { USB_DEVICE(0x050d, 0x7051) }, | 1916 | { USB_DEVICE(0x050d, 0x7051) }, |
1917 | /* Cisco Systems */ | 1917 | /* Cisco Systems */ |
1918 | { USB_DEVICE(0x13b1, 0x000d) }, | 1918 | { USB_DEVICE(0x13b1, 0x000d) }, |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6c0a12ea6a15..bd1980202f19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -290,11 +290,25 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | |||
290 | msleep(10); | 290 | msleep(10); |
291 | } | 291 | } |
292 | 292 | ||
293 | ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); | 293 | ERROR(rt2x00dev, "WPDMA TX/RX busy [0x%08x].\n", reg); |
294 | return -EACCES; | 294 | return -EACCES; |
295 | } | 295 | } |
296 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | 296 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); |
297 | 297 | ||
298 | void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev) | ||
299 | { | ||
300 | u32 reg; | ||
301 | |||
302 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
303 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
304 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
305 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
306 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
307 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
308 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(rt2800_disable_wpdma); | ||
311 | |||
298 | static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) | 312 | static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) |
299 | { | 313 | { |
300 | u16 fw_crc; | 314 | u16 fw_crc; |
@@ -412,6 +426,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
412 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | 426 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); |
413 | } | 427 | } |
414 | 428 | ||
429 | rt2800_disable_wpdma(rt2x00dev); | ||
430 | |||
415 | /* | 431 | /* |
416 | * Write firmware to the device. | 432 | * Write firmware to the device. |
417 | */ | 433 | */ |
@@ -436,10 +452,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
436 | * Disable DMA, will be reenabled later when enabling | 452 | * Disable DMA, will be reenabled later when enabling |
437 | * the radio. | 453 | * the radio. |
438 | */ | 454 | */ |
439 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 455 | rt2800_disable_wpdma(rt2x00dev); |
440 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
441 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
442 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
443 | 456 | ||
444 | /* | 457 | /* |
445 | * Initialize firmware. | 458 | * Initialize firmware. |
@@ -2717,13 +2730,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
2717 | unsigned int i; | 2730 | unsigned int i; |
2718 | int ret; | 2731 | int ret; |
2719 | 2732 | ||
2720 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 2733 | rt2800_disable_wpdma(rt2x00dev); |
2721 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
2722 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
2723 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
2724 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
2725 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
2726 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
2727 | 2734 | ||
2728 | ret = rt2800_drv_init_registers(rt2x00dev); | 2735 | ret = rt2800_drv_init_registers(rt2x00dev); |
2729 | if (ret) | 2736 | if (ret) |
@@ -3997,10 +4004,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
3997 | { | 4004 | { |
3998 | u32 reg; | 4005 | u32 reg; |
3999 | 4006 | ||
4000 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 4007 | rt2800_disable_wpdma(rt2x00dev); |
4001 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
4002 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
4003 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
4004 | 4008 | ||
4005 | /* Wait for DMA, ignore error */ | 4009 | /* Wait for DMA, ignore error */ |
4006 | rt2800_wait_wpdma_ready(rt2x00dev); | 4010 | rt2800_wait_wpdma_ready(rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 419e36cb06be..18a0b67b4c68 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -208,5 +208,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
208 | u8 buf_size); | 208 | u8 buf_size); |
209 | int rt2800_get_survey(struct ieee80211_hw *hw, int idx, | 209 | int rt2800_get_survey(struct ieee80211_hw *hw, int idx, |
210 | struct survey_info *survey); | 210 | struct survey_info *survey); |
211 | void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); | ||
211 | 212 | ||
212 | #endif /* RT2800LIB_H */ | 213 | #endif /* RT2800LIB_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 0397bbf0ce01..931331d95217 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -361,7 +361,6 @@ static void rt2800pci_clear_entry(struct queue_entry *entry) | |||
361 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | 361 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) |
362 | { | 362 | { |
363 | struct queue_entry_priv_pci *entry_priv; | 363 | struct queue_entry_priv_pci *entry_priv; |
364 | u32 reg; | ||
365 | 364 | ||
366 | /* | 365 | /* |
367 | * Initialize registers. | 366 | * Initialize registers. |
@@ -394,6 +393,16 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
394 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); | 393 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); |
395 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); | 394 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); |
396 | 395 | ||
396 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR4, 0); | ||
397 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT4, 0); | ||
398 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX4, 0); | ||
399 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX4, 0); | ||
400 | |||
401 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR5, 0); | ||
402 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT5, 0); | ||
403 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX5, 0); | ||
404 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
405 | |||
397 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | 406 | entry_priv = rt2x00dev->rx->entries[0].priv_data; |
398 | rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); | 407 | rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); |
399 | rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, | 408 | rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, |
@@ -402,14 +411,7 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
402 | rt2x00dev->rx[0].limit - 1); | 411 | rt2x00dev->rx[0].limit - 1); |
403 | rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); | 412 | rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); |
404 | 413 | ||
405 | /* | 414 | rt2800_disable_wpdma(rt2x00dev); |
406 | * Enable global DMA configuration | ||
407 | */ | ||
408 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
409 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
410 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
411 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
412 | rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
413 | 415 | ||
414 | rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); | 416 | rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); |
415 | 417 | ||
@@ -504,8 +506,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
504 | { | 506 | { |
505 | int retval; | 507 | int retval; |
506 | 508 | ||
507 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || | 509 | /* Wait for DMA, ignore error until we initialize queues. */ |
508 | rt2800pci_init_queues(rt2x00dev))) | 510 | rt2800_wait_wpdma_ready(rt2x00dev); |
511 | |||
512 | if (unlikely(rt2800pci_init_queues(rt2x00dev))) | ||
509 | return -EIO; | 513 | return -EIO; |
510 | 514 | ||
511 | retval = rt2800_enable_radio(rt2x00dev); | 515 | retval = rt2800_enable_radio(rt2x00dev); |
@@ -1184,7 +1188,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1184 | { PCI_DEVICE(0x1814, 0x3593) }, | 1188 | { PCI_DEVICE(0x1814, 0x3593) }, |
1185 | #endif | 1189 | #endif |
1186 | #ifdef CONFIG_RT2800PCI_RT53XX | 1190 | #ifdef CONFIG_RT2800PCI_RT53XX |
1191 | { PCI_DEVICE(0x1814, 0x5362) }, | ||
1187 | { PCI_DEVICE(0x1814, 0x5390) }, | 1192 | { PCI_DEVICE(0x1814, 0x5390) }, |
1193 | { PCI_DEVICE(0x1814, 0x5392) }, | ||
1188 | { PCI_DEVICE(0x1814, 0x539a) }, | 1194 | { PCI_DEVICE(0x1814, 0x539a) }, |
1189 | { PCI_DEVICE(0x1814, 0x539f) }, | 1195 | { PCI_DEVICE(0x1814, 0x539f) }, |
1190 | #endif | 1196 | #endif |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 90cc5e772650..dd87d41ac936 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -391,9 +391,10 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
391 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; | 391 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; |
392 | tx_info->status.ampdu_len = 1; | 392 | tx_info->status.ampdu_len = 1; |
393 | tx_info->status.ampdu_ack_len = success ? 1 : 0; | 393 | tx_info->status.ampdu_ack_len = success ? 1 : 0; |
394 | 394 | /* | |
395 | if (!success) | 395 | * TODO: Need to tear down BA session here |
396 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 396 | * if not successful. |
397 | */ | ||
397 | } | 398 | } |
398 | 399 | ||
399 | if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 400 | if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e0c6d117429d..ee22bd74579d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -3092,15 +3092,4 @@ static struct pci_driver rt61pci_driver = { | |||
3092 | .resume = rt2x00pci_resume, | 3092 | .resume = rt2x00pci_resume, |
3093 | }; | 3093 | }; |
3094 | 3094 | ||
3095 | static int __init rt61pci_init(void) | 3095 | module_pci_driver(rt61pci_driver); |
3096 | { | ||
3097 | return pci_register_driver(&rt61pci_driver); | ||
3098 | } | ||
3099 | |||
3100 | static void __exit rt61pci_exit(void) | ||
3101 | { | ||
3102 | pci_unregister_driver(&rt61pci_driver); | ||
3103 | } | ||
3104 | |||
3105 | module_init(rt61pci_init); | ||
3106 | module_exit(rt61pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e477a964081d..155136691a38 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2412,6 +2412,7 @@ static struct usb_device_id rt73usb_device_table[] = { | |||
2412 | { USB_DEVICE(0x0b05, 0x1723) }, | 2412 | { USB_DEVICE(0x0b05, 0x1723) }, |
2413 | { USB_DEVICE(0x0b05, 0x1724) }, | 2413 | { USB_DEVICE(0x0b05, 0x1724) }, |
2414 | /* Belkin */ | 2414 | /* Belkin */ |
2415 | { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050B ver. 3.x */ | ||
2415 | { USB_DEVICE(0x050d, 0x705a) }, | 2416 | { USB_DEVICE(0x050d, 0x705a) }, |
2416 | { USB_DEVICE(0x050d, 0x905b) }, | 2417 | { USB_DEVICE(0x050d, 0x905b) }, |
2417 | { USB_DEVICE(0x050d, 0x905c) }, | 2418 | { USB_DEVICE(0x050d, 0x905c) }, |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 2f14a5fb0cbb..2bebcb71a1e9 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -1173,15 +1173,4 @@ static struct pci_driver rtl8180_driver = { | |||
1173 | #endif /* CONFIG_PM */ | 1173 | #endif /* CONFIG_PM */ |
1174 | }; | 1174 | }; |
1175 | 1175 | ||
1176 | static int __init rtl8180_init(void) | 1176 | module_pci_driver(rtl8180_driver); |
1177 | { | ||
1178 | return pci_register_driver(&rtl8180_driver); | ||
1179 | } | ||
1180 | |||
1181 | static void __exit rtl8180_exit(void) | ||
1182 | { | ||
1183 | pci_unregister_driver(&rtl8180_driver); | ||
1184 | } | ||
1185 | |||
1186 | module_init(rtl8180_init); | ||
1187 | module_exit(rtl8180_exit); | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index cf53ac9d6f23..d8114962b0c9 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
@@ -294,6 +294,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
294 | hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); | 294 | hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); |
295 | hdr->tx_duration = | 295 | hdr->tx_duration = |
296 | ieee80211_generic_frame_duration(dev, priv->vif, | 296 | ieee80211_generic_frame_duration(dev, priv->vif, |
297 | info->band, | ||
297 | skb->len, txrate); | 298 | skb->len, txrate); |
298 | buf = hdr; | 299 | buf = hdr; |
299 | 300 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 288b035a3579..81d0c9b34328 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "ps.h" | 34 | #include "ps.h" |
35 | #include "efuse.h" | 35 | #include "efuse.h" |
36 | #include <linux/export.h> | 36 | #include <linux/export.h> |
37 | #include <linux/kmemleak.h> | ||
37 | 38 | ||
38 | static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { | 39 | static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { |
39 | PCI_VENDOR_ID_INTEL, | 40 | PCI_VENDOR_ID_INTEL, |
@@ -1099,6 +1100,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) | |||
1099 | u32 bufferaddress; | 1100 | u32 bufferaddress; |
1100 | if (!skb) | 1101 | if (!skb) |
1101 | return 0; | 1102 | return 0; |
1103 | kmemleak_not_leak(skb); | ||
1102 | entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; | 1104 | entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; |
1103 | 1105 | ||
1104 | /*skb->dev = dev; */ | 1106 | /*skb->dev = dev; */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index c20b3c30f62e..692c8ef5ee89 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "../rtl8192ce/def.h" | 34 | #include "../rtl8192ce/def.h" |
35 | #include "fw_common.h" | 35 | #include "fw_common.h" |
36 | #include <linux/export.h> | 36 | #include <linux/export.h> |
37 | #include <linux/kmemleak.h> | ||
37 | 38 | ||
38 | static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) | 39 | static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) |
39 | { | 40 | { |
@@ -776,6 +777,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) | |||
776 | skb = dev_alloc_skb(totalpacketlen); | 777 | skb = dev_alloc_skb(totalpacketlen); |
777 | if (!skb) | 778 | if (!skb) |
778 | return; | 779 | return; |
780 | kmemleak_not_leak(skb); | ||
781 | |||
779 | memcpy((u8 *) skb_put(skb, totalpacketlen), | 782 | memcpy((u8 *) skb_put(skb, totalpacketlen), |
780 | &reserved_page_packet, totalpacketlen); | 783 | &reserved_page_packet, totalpacketlen); |
781 | 784 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 2c3b73366cd2..3aa927f8b9b9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -389,21 +389,4 @@ static struct pci_driver rtl92ce_driver = { | |||
389 | .driver.pm = &rtlwifi_pm_ops, | 389 | .driver.pm = &rtlwifi_pm_ops, |
390 | }; | 390 | }; |
391 | 391 | ||
392 | static int __init rtl92ce_module_init(void) | 392 | module_pci_driver(rtl92ce_driver); |
393 | { | ||
394 | int ret; | ||
395 | |||
396 | ret = pci_register_driver(&rtl92ce_driver); | ||
397 | if (ret) | ||
398 | RT_ASSERT(false, "No device found\n"); | ||
399 | |||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | static void __exit rtl92ce_module_exit(void) | ||
404 | { | ||
405 | pci_unregister_driver(&rtl92ce_driver); | ||
406 | } | ||
407 | |||
408 | module_init(rtl92ce_module_init); | ||
409 | module_exit(rtl92ce_module_exit); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 82c85286ab2e..7737fb0c6661 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -338,6 +338,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { | |||
338 | {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/ | 338 | {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/ |
339 | 339 | ||
340 | /****** 8192CU ********/ | 340 | /****** 8192CU ********/ |
341 | {RTL_USB_DEVICE(0x050d, 0x1004, rtl92cu_hal_cfg)}, /*Belcom-SurfN300*/ | ||
341 | {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/ | 342 | {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/ |
342 | {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/ | 343 | {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/ |
343 | {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/ | 344 | {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h index eafdf76ed64d..939c905f547f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h | |||
@@ -151,9 +151,6 @@ enum version_8192d { | |||
151 | 151 | ||
152 | /* for 92D */ | 152 | /* for 92D */ |
153 | #define CHIP_92D_SINGLEPHY BIT(9) | 153 | #define CHIP_92D_SINGLEPHY BIT(9) |
154 | #define C_CUT_VERSION BIT(13) | ||
155 | #define D_CUT_VERSION ((BIT(12)|BIT(13))) | ||
156 | #define E_CUT_VERSION BIT(14) | ||
157 | 154 | ||
158 | /* Chip specific */ | 155 | /* Chip specific */ |
159 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) | 156 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) |
@@ -173,7 +170,10 @@ enum version_8192d { | |||
173 | #define RF_TYPE_1T2R BIT(4) | 170 | #define RF_TYPE_1T2R BIT(4) |
174 | #define RF_TYPE_2T2R BIT(5) | 171 | #define RF_TYPE_2T2R BIT(5) |
175 | #define CHIP_VENDOR_UMC BIT(7) | 172 | #define CHIP_VENDOR_UMC BIT(7) |
176 | #define B_CUT_VERSION BIT(12) | 173 | #define CHIP_92D_B_CUT BIT(12) |
174 | #define CHIP_92D_C_CUT BIT(13) | ||
175 | #define CHIP_92D_D_CUT (BIT(13)|BIT(12)) | ||
176 | #define CHIP_92D_E_CUT BIT(14) | ||
177 | 177 | ||
178 | /* MASK */ | 178 | /* MASK */ |
179 | #define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) | 179 | #define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) |
@@ -205,15 +205,13 @@ enum version_8192d { | |||
205 | CHIP_92D) ? true : false) | 205 | CHIP_92D) ? true : false) |
206 | #define IS_92D_C_CUT(version) ((IS_92D(version)) ? \ | 206 | #define IS_92D_C_CUT(version) ((IS_92D(version)) ? \ |
207 | ((GET_CVID_CUT_VERSION(version) == \ | 207 | ((GET_CVID_CUT_VERSION(version) == \ |
208 | 0x2000) ? true : false) : false) | 208 | CHIP_92D_C_CUT) ? true : false) : false) |
209 | #define IS_92D_D_CUT(version) ((IS_92D(version)) ? \ | 209 | #define IS_92D_D_CUT(version) ((IS_92D(version)) ? \ |
210 | ((GET_CVID_CUT_VERSION(version) == \ | 210 | ((GET_CVID_CUT_VERSION(version) == \ |
211 | 0x3000) ? true : false) : false) | 211 | CHIP_92D_D_CUT) ? true : false) : false) |
212 | #define IS_92D_E_CUT(version) ((IS_92D(version)) ? \ | 212 | #define IS_92D_E_CUT(version) ((IS_92D(version)) ? \ |
213 | ((GET_CVID_CUT_VERSION(version) == \ | 213 | ((GET_CVID_CUT_VERSION(version) == \ |
214 | 0x4000) ? true : false) : false) | 214 | CHIP_92D_E_CUT) ? true : false) : false) |
215 | #define CHIP_92D_C_CUT BIT(10) | ||
216 | #define CHIP_92D_D_CUT BIT(11) | ||
217 | 215 | ||
218 | enum rf_optype { | 216 | enum rf_optype { |
219 | RF_OP_BY_SW_3WIRE = 0, | 217 | RF_OP_BY_SW_3WIRE = 0, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 7ac9b8cb2ced..b338d526c422 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
@@ -1743,6 +1743,10 @@ static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw) | |||
1743 | chipver |= CHIP_92D_D_CUT; | 1743 | chipver |= CHIP_92D_D_CUT; |
1744 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "D-CUT!!!\n"); | 1744 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "D-CUT!!!\n"); |
1745 | break; | 1745 | break; |
1746 | case 0xCC33: | ||
1747 | chipver |= CHIP_92D_E_CUT; | ||
1748 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "E-CUT!!!\n"); | ||
1749 | break; | ||
1746 | default: | 1750 | default: |
1747 | chipver |= CHIP_92D_D_CUT; | 1751 | chipver |= CHIP_92D_D_CUT; |
1748 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown CUT!\n"); | 1752 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown CUT!\n"); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index f1b36005c6a2..730bcc919529 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -450,21 +450,4 @@ static struct pci_driver rtl92se_driver = { | |||
450 | .driver.pm = &rtlwifi_pm_ops, | 450 | .driver.pm = &rtlwifi_pm_ops, |
451 | }; | 451 | }; |
452 | 452 | ||
453 | static int __init rtl92se_module_init(void) | 453 | module_pci_driver(rtl92se_driver); |
454 | { | ||
455 | int ret = 0; | ||
456 | |||
457 | ret = pci_register_driver(&rtl92se_driver); | ||
458 | if (ret) | ||
459 | RT_ASSERT(false, "No device found\n"); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static void __exit rtl92se_module_exit(void) | ||
465 | { | ||
466 | pci_unregister_driver(&rtl92se_driver); | ||
467 | } | ||
468 | |||
469 | module_init(rtl92se_module_init); | ||
470 | module_exit(rtl92se_module_exit); | ||
diff --git a/drivers/net/wireless/ti/Kconfig b/drivers/net/wireless/ti/Kconfig new file mode 100644 index 000000000000..1a72932e2213 --- /dev/null +++ b/drivers/net/wireless/ti/Kconfig | |||
@@ -0,0 +1,14 @@ | |||
1 | menuconfig WL_TI | ||
2 | bool "TI Wireless LAN support" | ||
3 | ---help--- | ||
4 | This section contains support for all the wireless drivers | ||
5 | for Texas Instruments WLAN chips, such as wl1251 and the wl12xx | ||
6 | family. | ||
7 | |||
8 | if WL_TI | ||
9 | source "drivers/net/wireless/ti/wl1251/Kconfig" | ||
10 | source "drivers/net/wireless/ti/wl12xx/Kconfig" | ||
11 | |||
12 | # keep last for automatic dependencies | ||
13 | source "drivers/net/wireless/ti/wlcore/Kconfig" | ||
14 | endif # WL_TI | ||
diff --git a/drivers/net/wireless/ti/Makefile b/drivers/net/wireless/ti/Makefile new file mode 100644 index 000000000000..0a565622d4a4 --- /dev/null +++ b/drivers/net/wireless/ti/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-$(CONFIG_WLCORE) += wlcore/ | ||
2 | obj-$(CONFIG_WL12XX) += wl12xx/ | ||
3 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/ | ||
4 | obj-$(CONFIG_WL1251) += wl1251/ | ||
diff --git a/drivers/net/wireless/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig index 1fb65849414f..1fb65849414f 100644 --- a/drivers/net/wireless/wl1251/Kconfig +++ b/drivers/net/wireless/ti/wl1251/Kconfig | |||
diff --git a/drivers/net/wireless/wl1251/Makefile b/drivers/net/wireless/ti/wl1251/Makefile index a5c6328b5f72..a5c6328b5f72 100644 --- a/drivers/net/wireless/wl1251/Makefile +++ b/drivers/net/wireless/ti/wl1251/Makefile | |||
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index ad87a1ac6462..ad87a1ac6462 100644 --- a/drivers/net/wireless/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c | |||
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h index c2ba100f9b1a..c2ba100f9b1a 100644 --- a/drivers/net/wireless/wl1251/acx.h +++ b/drivers/net/wireless/ti/wl1251/acx.h | |||
diff --git a/drivers/net/wireless/wl1251/boot.c b/drivers/net/wireless/ti/wl1251/boot.c index a2e5241382da..a2e5241382da 100644 --- a/drivers/net/wireless/wl1251/boot.c +++ b/drivers/net/wireless/ti/wl1251/boot.c | |||
diff --git a/drivers/net/wireless/wl1251/boot.h b/drivers/net/wireless/ti/wl1251/boot.h index 7661bc5e4662..7661bc5e4662 100644 --- a/drivers/net/wireless/wl1251/boot.h +++ b/drivers/net/wireless/ti/wl1251/boot.h | |||
diff --git a/drivers/net/wireless/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index d14d69d733a0..d14d69d733a0 100644 --- a/drivers/net/wireless/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c | |||
diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h index ee4f2b391822..ee4f2b391822 100644 --- a/drivers/net/wireless/wl1251/cmd.h +++ b/drivers/net/wireless/ti/wl1251/cmd.h | |||
diff --git a/drivers/net/wireless/wl1251/debugfs.c b/drivers/net/wireless/ti/wl1251/debugfs.c index 448da1f8c22f..448da1f8c22f 100644 --- a/drivers/net/wireless/wl1251/debugfs.c +++ b/drivers/net/wireless/ti/wl1251/debugfs.c | |||
diff --git a/drivers/net/wireless/wl1251/debugfs.h b/drivers/net/wireless/ti/wl1251/debugfs.h index b3417c02a218..b3417c02a218 100644 --- a/drivers/net/wireless/wl1251/debugfs.h +++ b/drivers/net/wireless/ti/wl1251/debugfs.h | |||
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index 9f15ccaf8f05..9f15ccaf8f05 100644 --- a/drivers/net/wireless/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c | |||
diff --git a/drivers/net/wireless/wl1251/event.h b/drivers/net/wireless/ti/wl1251/event.h index 30eb5d150bf7..30eb5d150bf7 100644 --- a/drivers/net/wireless/wl1251/event.h +++ b/drivers/net/wireless/ti/wl1251/event.h | |||
diff --git a/drivers/net/wireless/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c index 89b43d35473c..89b43d35473c 100644 --- a/drivers/net/wireless/wl1251/init.c +++ b/drivers/net/wireless/ti/wl1251/init.c | |||
diff --git a/drivers/net/wireless/wl1251/init.h b/drivers/net/wireless/ti/wl1251/init.h index 543f17582ead..543f17582ead 100644 --- a/drivers/net/wireless/wl1251/init.h +++ b/drivers/net/wireless/ti/wl1251/init.h | |||
diff --git a/drivers/net/wireless/wl1251/io.c b/drivers/net/wireless/ti/wl1251/io.c index cdcadbf6ac2c..cdcadbf6ac2c 100644 --- a/drivers/net/wireless/wl1251/io.c +++ b/drivers/net/wireless/ti/wl1251/io.c | |||
diff --git a/drivers/net/wireless/wl1251/io.h b/drivers/net/wireless/ti/wl1251/io.h index d382877c34cc..d382877c34cc 100644 --- a/drivers/net/wireless/wl1251/io.h +++ b/drivers/net/wireless/ti/wl1251/io.h | |||
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 41302c7b1ad0..41302c7b1ad0 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/ti/wl1251/ps.c index db719f7d2692..db719f7d2692 100644 --- a/drivers/net/wireless/wl1251/ps.c +++ b/drivers/net/wireless/ti/wl1251/ps.c | |||
diff --git a/drivers/net/wireless/wl1251/ps.h b/drivers/net/wireless/ti/wl1251/ps.h index 75efad246d67..75efad246d67 100644 --- a/drivers/net/wireless/wl1251/ps.h +++ b/drivers/net/wireless/ti/wl1251/ps.h | |||
diff --git a/drivers/net/wireless/wl1251/reg.h b/drivers/net/wireless/ti/wl1251/reg.h index a5809019c5c1..a5809019c5c1 100644 --- a/drivers/net/wireless/wl1251/reg.h +++ b/drivers/net/wireless/ti/wl1251/reg.h | |||
diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c index 6af35265c900..6af35265c900 100644 --- a/drivers/net/wireless/wl1251/rx.c +++ b/drivers/net/wireless/ti/wl1251/rx.c | |||
diff --git a/drivers/net/wireless/wl1251/rx.h b/drivers/net/wireless/ti/wl1251/rx.h index 4448f635a4d8..4448f635a4d8 100644 --- a/drivers/net/wireless/wl1251/rx.h +++ b/drivers/net/wireless/ti/wl1251/rx.h | |||
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index f78694295c39..f78694295c39 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c | |||
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 6248c354fc5c..6248c354fc5c 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c | |||
diff --git a/drivers/net/wireless/wl1251/spi.h b/drivers/net/wireless/ti/wl1251/spi.h index 16d506955cc0..16d506955cc0 100644 --- a/drivers/net/wireless/wl1251/spi.h +++ b/drivers/net/wireless/ti/wl1251/spi.h | |||
diff --git a/drivers/net/wireless/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c index 28121c590a2b..28121c590a2b 100644 --- a/drivers/net/wireless/wl1251/tx.c +++ b/drivers/net/wireless/ti/wl1251/tx.c | |||
diff --git a/drivers/net/wireless/wl1251/tx.h b/drivers/net/wireless/ti/wl1251/tx.h index 81338d39b43e..81338d39b43e 100644 --- a/drivers/net/wireless/wl1251/tx.h +++ b/drivers/net/wireless/ti/wl1251/tx.h | |||
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index 9d8f5816c6f9..9d8f5816c6f9 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/ti/wl1251/wl12xx_80211.h index 04ed51495772..04ed51495772 100644 --- a/drivers/net/wireless/wl1251/wl12xx_80211.h +++ b/drivers/net/wireless/ti/wl1251/wl12xx_80211.h | |||
diff --git a/drivers/net/wireless/ti/wl12xx/Kconfig b/drivers/net/wireless/ti/wl12xx/Kconfig new file mode 100644 index 000000000000..5b92329122c4 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/Kconfig | |||
@@ -0,0 +1,8 @@ | |||
1 | config WL12XX | ||
2 | tristate "TI wl12xx support" | ||
3 | select WLCORE | ||
4 | ---help--- | ||
5 | This module adds support for wireless adapters based on TI wl1271, | ||
6 | wl1273, wl1281 and wl1283 chipsets. This module does *not* include | ||
7 | support for wl1251. For wl1251 support, use the separate homonymous | ||
8 | driver instead. | ||
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile new file mode 100644 index 000000000000..87f64b14db35 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | wl12xx-objs = main.o cmd.o acx.o | ||
2 | |||
3 | obj-$(CONFIG_WL12XX) += wl12xx.o | ||
diff --git a/drivers/net/wireless/ti/wl12xx/acx.c b/drivers/net/wireless/ti/wl12xx/acx.c new file mode 100644 index 000000000000..bea06b2d7bf4 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/acx.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation | ||
5 | * Copyright (C) 2011 Texas Instruments Inc. | ||
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/cmd.h" | ||
24 | #include "../wlcore/debug.h" | ||
25 | #include "../wlcore/acx.h" | ||
26 | |||
27 | #include "acx.h" | ||
28 | |||
29 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) | ||
30 | { | ||
31 | struct wl1271_acx_host_config_bitmap *bitmap_conf; | ||
32 | int ret; | ||
33 | |||
34 | bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); | ||
35 | if (!bitmap_conf) { | ||
36 | ret = -ENOMEM; | ||
37 | goto out; | ||
38 | } | ||
39 | |||
40 | bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); | ||
41 | |||
42 | ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, | ||
43 | bitmap_conf, sizeof(*bitmap_conf)); | ||
44 | if (ret < 0) { | ||
45 | wl1271_warning("wl1271 bitmap config opt failed: %d", ret); | ||
46 | goto out; | ||
47 | } | ||
48 | |||
49 | out: | ||
50 | kfree(bitmap_conf); | ||
51 | |||
52 | return ret; | ||
53 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h new file mode 100644 index 000000000000..d1f5aba0afce --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/acx.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
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 | #ifndef __WL12XX_ACX_H__ | ||
24 | #define __WL12XX_ACX_H__ | ||
25 | |||
26 | #include "../wlcore/wlcore.h" | ||
27 | |||
28 | struct wl1271_acx_host_config_bitmap { | ||
29 | struct acx_header header; | ||
30 | |||
31 | __le32 host_cfg_bitmap; | ||
32 | } __packed; | ||
33 | |||
34 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); | ||
35 | |||
36 | #endif /* __WL12XX_ACX_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c new file mode 100644 index 000000000000..8ffaeb5f2147 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/cmd.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * Copyright (C) 2011 Texas Instruments Inc. | ||
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/cmd.h" | ||
24 | #include "../wlcore/debug.h" | ||
25 | |||
26 | #include "wl12xx.h" | ||
27 | #include "cmd.h" | ||
28 | |||
29 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) | ||
30 | { | ||
31 | struct wl1271_ext_radio_parms_cmd *ext_radio_parms; | ||
32 | struct wl12xx_priv *priv = wl->priv; | ||
33 | struct wl12xx_conf_rf *rf = &priv->conf.rf; | ||
34 | int ret; | ||
35 | |||
36 | if (!wl->nvs) | ||
37 | return -ENODEV; | ||
38 | |||
39 | ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); | ||
40 | if (!ext_radio_parms) | ||
41 | return -ENOMEM; | ||
42 | |||
43 | ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; | ||
44 | |||
45 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, | ||
46 | rf->tx_per_channel_power_compensation_2, | ||
47 | CONF_TX_PWR_COMPENSATION_LEN_2); | ||
48 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, | ||
49 | rf->tx_per_channel_power_compensation_5, | ||
50 | CONF_TX_PWR_COMPENSATION_LEN_5); | ||
51 | |||
52 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", | ||
53 | ext_radio_parms, sizeof(*ext_radio_parms)); | ||
54 | |||
55 | ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); | ||
56 | if (ret < 0) | ||
57 | wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); | ||
58 | |||
59 | kfree(ext_radio_parms); | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | int wl1271_cmd_general_parms(struct wl1271 *wl) | ||
64 | { | ||
65 | struct wl1271_general_parms_cmd *gen_parms; | ||
66 | struct wl1271_ini_general_params *gp = | ||
67 | &((struct wl1271_nvs_file *)wl->nvs)->general_params; | ||
68 | bool answer = false; | ||
69 | int ret; | ||
70 | |||
71 | if (!wl->nvs) | ||
72 | return -ENODEV; | ||
73 | |||
74 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
75 | wl1271_warning("FEM index from INI out of bounds"); | ||
76 | return -EINVAL; | ||
77 | } | ||
78 | |||
79 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | ||
80 | if (!gen_parms) | ||
81 | return -ENOMEM; | ||
82 | |||
83 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | ||
84 | |||
85 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); | ||
86 | |||
87 | if (gp->tx_bip_fem_auto_detect) | ||
88 | answer = true; | ||
89 | |||
90 | /* Override the REF CLK from the NVS with the one from platform data */ | ||
91 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
92 | |||
93 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
94 | if (ret < 0) { | ||
95 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | gp->tx_bip_fem_manufacturer = | ||
100 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
101 | |||
102 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
103 | wl1271_warning("FEM index from FW out of bounds"); | ||
104 | ret = -EINVAL; | ||
105 | goto out; | ||
106 | } | ||
107 | |||
108 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
109 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
110 | |||
111 | out: | ||
112 | kfree(gen_parms); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | int wl128x_cmd_general_parms(struct wl1271 *wl) | ||
117 | { | ||
118 | struct wl128x_general_parms_cmd *gen_parms; | ||
119 | struct wl128x_ini_general_params *gp = | ||
120 | &((struct wl128x_nvs_file *)wl->nvs)->general_params; | ||
121 | bool answer = false; | ||
122 | int ret; | ||
123 | |||
124 | if (!wl->nvs) | ||
125 | return -ENODEV; | ||
126 | |||
127 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
128 | wl1271_warning("FEM index from ini out of bounds"); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | ||
133 | if (!gen_parms) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | ||
137 | |||
138 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); | ||
139 | |||
140 | if (gp->tx_bip_fem_auto_detect) | ||
141 | answer = true; | ||
142 | |||
143 | /* Replace REF and TCXO CLKs with the ones from platform data */ | ||
144 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
145 | gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; | ||
146 | |||
147 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
148 | if (ret < 0) { | ||
149 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | ||
150 | goto out; | ||
151 | } | ||
152 | |||
153 | gp->tx_bip_fem_manufacturer = | ||
154 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
155 | |||
156 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
157 | wl1271_warning("FEM index from FW out of bounds"); | ||
158 | ret = -EINVAL; | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
163 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
164 | |||
165 | out: | ||
166 | kfree(gen_parms); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | int wl1271_cmd_radio_parms(struct wl1271 *wl) | ||
171 | { | ||
172 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; | ||
173 | struct wl1271_radio_parms_cmd *radio_parms; | ||
174 | struct wl1271_ini_general_params *gp = &nvs->general_params; | ||
175 | int ret; | ||
176 | |||
177 | if (!wl->nvs) | ||
178 | return -ENODEV; | ||
179 | |||
180 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | ||
181 | if (!radio_parms) | ||
182 | return -ENOMEM; | ||
183 | |||
184 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | ||
185 | |||
186 | /* 2.4GHz parameters */ | ||
187 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | ||
188 | sizeof(struct wl1271_ini_band_params_2)); | ||
189 | memcpy(&radio_parms->dyn_params_2, | ||
190 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | ||
191 | sizeof(struct wl1271_ini_fem_params_2)); | ||
192 | |||
193 | /* 5GHz parameters */ | ||
194 | memcpy(&radio_parms->static_params_5, | ||
195 | &nvs->stat_radio_params_5, | ||
196 | sizeof(struct wl1271_ini_band_params_5)); | ||
197 | memcpy(&radio_parms->dyn_params_5, | ||
198 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | ||
199 | sizeof(struct wl1271_ini_fem_params_5)); | ||
200 | |||
201 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | ||
202 | radio_parms, sizeof(*radio_parms)); | ||
203 | |||
204 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); | ||
205 | if (ret < 0) | ||
206 | wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); | ||
207 | |||
208 | kfree(radio_parms); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | int wl128x_cmd_radio_parms(struct wl1271 *wl) | ||
213 | { | ||
214 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | ||
215 | struct wl128x_radio_parms_cmd *radio_parms; | ||
216 | struct wl128x_ini_general_params *gp = &nvs->general_params; | ||
217 | int ret; | ||
218 | |||
219 | if (!wl->nvs) | ||
220 | return -ENODEV; | ||
221 | |||
222 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | ||
223 | if (!radio_parms) | ||
224 | return -ENOMEM; | ||
225 | |||
226 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | ||
227 | |||
228 | /* 2.4GHz parameters */ | ||
229 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | ||
230 | sizeof(struct wl128x_ini_band_params_2)); | ||
231 | memcpy(&radio_parms->dyn_params_2, | ||
232 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | ||
233 | sizeof(struct wl128x_ini_fem_params_2)); | ||
234 | |||
235 | /* 5GHz parameters */ | ||
236 | memcpy(&radio_parms->static_params_5, | ||
237 | &nvs->stat_radio_params_5, | ||
238 | sizeof(struct wl128x_ini_band_params_5)); | ||
239 | memcpy(&radio_parms->dyn_params_5, | ||
240 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | ||
241 | sizeof(struct wl128x_ini_fem_params_5)); | ||
242 | |||
243 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; | ||
244 | |||
245 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | ||
246 | radio_parms, sizeof(*radio_parms)); | ||
247 | |||
248 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); | ||
249 | if (ret < 0) | ||
250 | wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); | ||
251 | |||
252 | kfree(radio_parms); | ||
253 | return ret; | ||
254 | } | ||
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.h b/drivers/net/wireless/ti/wl12xx/cmd.h new file mode 100644 index 000000000000..140a0e8829d5 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/cmd.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2009 Nokia Corporation | ||
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 | #ifndef __WL12XX_CMD_H__ | ||
24 | #define __WL12XX_CMD_H__ | ||
25 | |||
26 | #include "conf.h" | ||
27 | |||
28 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 | ||
29 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E | ||
30 | |||
31 | struct wl1271_general_parms_cmd { | ||
32 | struct wl1271_cmd_header header; | ||
33 | |||
34 | struct wl1271_cmd_test_header test; | ||
35 | |||
36 | struct wl1271_ini_general_params general_params; | ||
37 | |||
38 | u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
39 | u8 sr_sen_n_p; | ||
40 | u8 sr_sen_n_p_gain; | ||
41 | u8 sr_sen_nrn; | ||
42 | u8 sr_sen_prn; | ||
43 | u8 padding[3]; | ||
44 | } __packed; | ||
45 | |||
46 | struct wl128x_general_parms_cmd { | ||
47 | struct wl1271_cmd_header header; | ||
48 | |||
49 | struct wl1271_cmd_test_header test; | ||
50 | |||
51 | struct wl128x_ini_general_params general_params; | ||
52 | |||
53 | u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
54 | u8 sr_sen_n_p; | ||
55 | u8 sr_sen_n_p_gain; | ||
56 | u8 sr_sen_nrn; | ||
57 | u8 sr_sen_prn; | ||
58 | u8 padding[3]; | ||
59 | } __packed; | ||
60 | |||
61 | struct wl1271_radio_parms_cmd { | ||
62 | struct wl1271_cmd_header header; | ||
63 | |||
64 | struct wl1271_cmd_test_header test; | ||
65 | |||
66 | /* Static radio parameters */ | ||
67 | struct wl1271_ini_band_params_2 static_params_2; | ||
68 | struct wl1271_ini_band_params_5 static_params_5; | ||
69 | |||
70 | /* Dynamic radio parameters */ | ||
71 | struct wl1271_ini_fem_params_2 dyn_params_2; | ||
72 | u8 padding2; | ||
73 | struct wl1271_ini_fem_params_5 dyn_params_5; | ||
74 | u8 padding3[2]; | ||
75 | } __packed; | ||
76 | |||
77 | struct wl128x_radio_parms_cmd { | ||
78 | struct wl1271_cmd_header header; | ||
79 | |||
80 | struct wl1271_cmd_test_header test; | ||
81 | |||
82 | /* Static radio parameters */ | ||
83 | struct wl128x_ini_band_params_2 static_params_2; | ||
84 | struct wl128x_ini_band_params_5 static_params_5; | ||
85 | |||
86 | u8 fem_vendor_and_options; | ||
87 | |||
88 | /* Dynamic radio parameters */ | ||
89 | struct wl128x_ini_fem_params_2 dyn_params_2; | ||
90 | u8 padding2; | ||
91 | struct wl128x_ini_fem_params_5 dyn_params_5; | ||
92 | } __packed; | ||
93 | |||
94 | #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 | ||
95 | |||
96 | struct wl1271_ext_radio_parms_cmd { | ||
97 | struct wl1271_cmd_header header; | ||
98 | |||
99 | struct wl1271_cmd_test_header test; | ||
100 | |||
101 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
102 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
103 | u8 padding[3]; | ||
104 | } __packed; | ||
105 | |||
106 | int wl1271_cmd_general_parms(struct wl1271 *wl); | ||
107 | int wl128x_cmd_general_parms(struct wl1271 *wl); | ||
108 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | ||
109 | int wl128x_cmd_radio_parms(struct wl1271 *wl); | ||
110 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); | ||
111 | |||
112 | #endif /* __WL12XX_CMD_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl12xx/conf.h b/drivers/net/wireless/ti/wl12xx/conf.h new file mode 100644 index 000000000000..75e29897a0f5 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/conf.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
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 __WL12XX_CONF_H__ | ||
23 | #define __WL12XX_CONF_H__ | ||
24 | |||
25 | /* these are number of channels on the band divided by two, rounded up */ | ||
26 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | ||
27 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | ||
28 | |||
29 | struct wl12xx_conf_rf { | ||
30 | /* | ||
31 | * Per channel power compensation for 2.4GHz | ||
32 | * | ||
33 | * Range: s8 | ||
34 | */ | ||
35 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
36 | |||
37 | /* | ||
38 | * Per channel power compensation for 5GHz | ||
39 | * | ||
40 | * Range: s8 | ||
41 | */ | ||
42 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
43 | }; | ||
44 | |||
45 | struct wl12xx_priv_conf { | ||
46 | struct wl12xx_conf_rf rf; | ||
47 | struct conf_memory_settings mem_wl127x; | ||
48 | }; | ||
49 | |||
50 | #endif /* __WL12XX_CONF_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c new file mode 100644 index 000000000000..d7dd3def07b5 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -0,0 +1,1388 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
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 | |||
25 | #include <linux/err.h> | ||
26 | |||
27 | #include <linux/wl12xx.h> | ||
28 | |||
29 | #include "../wlcore/wlcore.h" | ||
30 | #include "../wlcore/debug.h" | ||
31 | #include "../wlcore/io.h" | ||
32 | #include "../wlcore/acx.h" | ||
33 | #include "../wlcore/tx.h" | ||
34 | #include "../wlcore/rx.h" | ||
35 | #include "../wlcore/io.h" | ||
36 | #include "../wlcore/boot.h" | ||
37 | |||
38 | #include "wl12xx.h" | ||
39 | #include "reg.h" | ||
40 | #include "cmd.h" | ||
41 | #include "acx.h" | ||
42 | |||
43 | static struct wlcore_conf wl12xx_conf = { | ||
44 | .sg = { | ||
45 | .params = { | ||
46 | [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, | ||
47 | [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, | ||
48 | [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, | ||
49 | [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, | ||
50 | [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, | ||
51 | [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, | ||
52 | [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, | ||
53 | [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, | ||
54 | [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, | ||
55 | [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, | ||
56 | [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, | ||
57 | [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, | ||
58 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, | ||
59 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, | ||
60 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, | ||
61 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, | ||
62 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, | ||
63 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, | ||
64 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, | ||
65 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, | ||
66 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, | ||
67 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, | ||
68 | [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, | ||
69 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, | ||
70 | [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, | ||
71 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, | ||
72 | /* active scan params */ | ||
73 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
74 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
75 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
76 | /* passive scan params */ | ||
77 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, | ||
78 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, | ||
79 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
80 | /* passive scan in dual antenna params */ | ||
81 | [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, | ||
82 | [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, | ||
83 | [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, | ||
84 | /* general params */ | ||
85 | [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, | ||
86 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
87 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
88 | [CONF_SG_DHCP_TIME] = 5000, | ||
89 | [CONF_SG_RXT] = 1200, | ||
90 | [CONF_SG_TXT] = 1000, | ||
91 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
92 | [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, | ||
93 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
94 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
95 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
96 | [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, | ||
97 | [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, | ||
98 | [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, | ||
99 | /* AP params */ | ||
100 | [CONF_AP_BEACON_MISS_TX] = 3, | ||
101 | [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, | ||
102 | [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, | ||
103 | [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, | ||
104 | [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, | ||
105 | [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, | ||
106 | /* CTS Diluting params */ | ||
107 | [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, | ||
108 | [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, | ||
109 | }, | ||
110 | .state = CONF_SG_PROTECTIVE, | ||
111 | }, | ||
112 | .rx = { | ||
113 | .rx_msdu_life_time = 512000, | ||
114 | .packet_detection_threshold = 0, | ||
115 | .ps_poll_timeout = 15, | ||
116 | .upsd_timeout = 15, | ||
117 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, | ||
118 | .rx_cca_threshold = 0, | ||
119 | .irq_blk_threshold = 0xFFFF, | ||
120 | .irq_pkt_threshold = 0, | ||
121 | .irq_timeout = 600, | ||
122 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | ||
123 | }, | ||
124 | .tx = { | ||
125 | .tx_energy_detection = 0, | ||
126 | .sta_rc_conf = { | ||
127 | .enabled_rates = 0, | ||
128 | .short_retry_limit = 10, | ||
129 | .long_retry_limit = 10, | ||
130 | .aflags = 0, | ||
131 | }, | ||
132 | .ac_conf_count = 4, | ||
133 | .ac_conf = { | ||
134 | [CONF_TX_AC_BE] = { | ||
135 | .ac = CONF_TX_AC_BE, | ||
136 | .cw_min = 15, | ||
137 | .cw_max = 63, | ||
138 | .aifsn = 3, | ||
139 | .tx_op_limit = 0, | ||
140 | }, | ||
141 | [CONF_TX_AC_BK] = { | ||
142 | .ac = CONF_TX_AC_BK, | ||
143 | .cw_min = 15, | ||
144 | .cw_max = 63, | ||
145 | .aifsn = 7, | ||
146 | .tx_op_limit = 0, | ||
147 | }, | ||
148 | [CONF_TX_AC_VI] = { | ||
149 | .ac = CONF_TX_AC_VI, | ||
150 | .cw_min = 15, | ||
151 | .cw_max = 63, | ||
152 | .aifsn = CONF_TX_AIFS_PIFS, | ||
153 | .tx_op_limit = 3008, | ||
154 | }, | ||
155 | [CONF_TX_AC_VO] = { | ||
156 | .ac = CONF_TX_AC_VO, | ||
157 | .cw_min = 15, | ||
158 | .cw_max = 63, | ||
159 | .aifsn = CONF_TX_AIFS_PIFS, | ||
160 | .tx_op_limit = 1504, | ||
161 | }, | ||
162 | }, | ||
163 | .max_tx_retries = 100, | ||
164 | .ap_aging_period = 300, | ||
165 | .tid_conf_count = 4, | ||
166 | .tid_conf = { | ||
167 | [CONF_TX_AC_BE] = { | ||
168 | .queue_id = CONF_TX_AC_BE, | ||
169 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
170 | .tsid = CONF_TX_AC_BE, | ||
171 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
172 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
173 | .apsd_conf = {0, 0}, | ||
174 | }, | ||
175 | [CONF_TX_AC_BK] = { | ||
176 | .queue_id = CONF_TX_AC_BK, | ||
177 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
178 | .tsid = CONF_TX_AC_BK, | ||
179 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
180 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
181 | .apsd_conf = {0, 0}, | ||
182 | }, | ||
183 | [CONF_TX_AC_VI] = { | ||
184 | .queue_id = CONF_TX_AC_VI, | ||
185 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
186 | .tsid = CONF_TX_AC_VI, | ||
187 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
188 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
189 | .apsd_conf = {0, 0}, | ||
190 | }, | ||
191 | [CONF_TX_AC_VO] = { | ||
192 | .queue_id = CONF_TX_AC_VO, | ||
193 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
194 | .tsid = CONF_TX_AC_VO, | ||
195 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
196 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
197 | .apsd_conf = {0, 0}, | ||
198 | }, | ||
199 | }, | ||
200 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | ||
201 | .tx_compl_timeout = 700, | ||
202 | .tx_compl_threshold = 4, | ||
203 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
204 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
205 | .tmpl_short_retry_limit = 10, | ||
206 | .tmpl_long_retry_limit = 10, | ||
207 | .tx_watchdog_timeout = 5000, | ||
208 | }, | ||
209 | .conn = { | ||
210 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | ||
211 | .listen_interval = 1, | ||
212 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, | ||
213 | .suspend_listen_interval = 3, | ||
214 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | ||
215 | .bcn_filt_ie_count = 2, | ||
216 | .bcn_filt_ie = { | ||
217 | [0] = { | ||
218 | .ie = WLAN_EID_CHANNEL_SWITCH, | ||
219 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | ||
220 | }, | ||
221 | [1] = { | ||
222 | .ie = WLAN_EID_HT_OPERATION, | ||
223 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
224 | }, | ||
225 | }, | ||
226 | .synch_fail_thold = 10, | ||
227 | .bss_lose_timeout = 100, | ||
228 | .beacon_rx_timeout = 10000, | ||
229 | .broadcast_timeout = 20000, | ||
230 | .rx_broadcast_in_ps = 1, | ||
231 | .ps_poll_threshold = 10, | ||
232 | .bet_enable = CONF_BET_MODE_ENABLE, | ||
233 | .bet_max_consecutive = 50, | ||
234 | .psm_entry_retries = 8, | ||
235 | .psm_exit_retries = 16, | ||
236 | .psm_entry_nullfunc_retries = 3, | ||
237 | .dynamic_ps_timeout = 40, | ||
238 | .forced_ps = false, | ||
239 | .keep_alive_interval = 55000, | ||
240 | .max_listen_interval = 20, | ||
241 | }, | ||
242 | .itrim = { | ||
243 | .enable = false, | ||
244 | .timeout = 50000, | ||
245 | }, | ||
246 | .pm_config = { | ||
247 | .host_clk_settling_time = 5000, | ||
248 | .host_fast_wakeup_support = false | ||
249 | }, | ||
250 | .roam_trigger = { | ||
251 | .trigger_pacing = 1, | ||
252 | .avg_weight_rssi_beacon = 20, | ||
253 | .avg_weight_rssi_data = 10, | ||
254 | .avg_weight_snr_beacon = 20, | ||
255 | .avg_weight_snr_data = 10, | ||
256 | }, | ||
257 | .scan = { | ||
258 | .min_dwell_time_active = 7500, | ||
259 | .max_dwell_time_active = 30000, | ||
260 | .min_dwell_time_passive = 100000, | ||
261 | .max_dwell_time_passive = 100000, | ||
262 | .num_probe_reqs = 2, | ||
263 | .split_scan_timeout = 50000, | ||
264 | }, | ||
265 | .sched_scan = { | ||
266 | /* | ||
267 | * Values are in TU/1000 but since sched scan FW command | ||
268 | * params are in TUs rounding up may occur. | ||
269 | */ | ||
270 | .base_dwell_time = 7500, | ||
271 | .max_dwell_time_delta = 22500, | ||
272 | /* based on 250bits per probe @1Mbps */ | ||
273 | .dwell_time_delta_per_probe = 2000, | ||
274 | /* based on 250bits per probe @6Mbps (plus a bit more) */ | ||
275 | .dwell_time_delta_per_probe_5 = 350, | ||
276 | .dwell_time_passive = 100000, | ||
277 | .dwell_time_dfs = 150000, | ||
278 | .num_probe_reqs = 2, | ||
279 | .rssi_threshold = -90, | ||
280 | .snr_threshold = 0, | ||
281 | }, | ||
282 | .ht = { | ||
283 | .rx_ba_win_size = 8, | ||
284 | .tx_ba_win_size = 64, | ||
285 | .inactivity_timeout = 10000, | ||
286 | .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, | ||
287 | }, | ||
288 | /* | ||
289 | * Memory config for wl127x chips is given in the | ||
290 | * wl12xx_default_priv_conf struct. The below configuration is | ||
291 | * for wl128x chips. | ||
292 | */ | ||
293 | .mem = { | ||
294 | .num_stations = 1, | ||
295 | .ssid_profiles = 1, | ||
296 | .rx_block_num = 40, | ||
297 | .tx_min_block_num = 40, | ||
298 | .dynamic_memory = 1, | ||
299 | .min_req_tx_blocks = 45, | ||
300 | .min_req_rx_blocks = 22, | ||
301 | .tx_min = 27, | ||
302 | }, | ||
303 | .fm_coex = { | ||
304 | .enable = true, | ||
305 | .swallow_period = 5, | ||
306 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
307 | .n_divider_fref_set_2 = 12, | ||
308 | .m_divider_fref_set_1 = 148, | ||
309 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
310 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
311 | .ldo_stabilization_time = 0xffff, /* default */ | ||
312 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
313 | .swallow_clk_diff = 0xff, /* default */ | ||
314 | }, | ||
315 | .rx_streaming = { | ||
316 | .duration = 150, | ||
317 | .queues = 0x1, | ||
318 | .interval = 20, | ||
319 | .always = 0, | ||
320 | }, | ||
321 | .fwlog = { | ||
322 | .mode = WL12XX_FWLOG_ON_DEMAND, | ||
323 | .mem_blocks = 2, | ||
324 | .severity = 0, | ||
325 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | ||
326 | .output = WL12XX_FWLOG_OUTPUT_HOST, | ||
327 | .threshold = 0, | ||
328 | }, | ||
329 | .rate = { | ||
330 | .rate_retry_score = 32000, | ||
331 | .per_add = 8192, | ||
332 | .per_th1 = 2048, | ||
333 | .per_th2 = 4096, | ||
334 | .max_per = 8100, | ||
335 | .inverse_curiosity_factor = 5, | ||
336 | .tx_fail_low_th = 4, | ||
337 | .tx_fail_high_th = 10, | ||
338 | .per_alpha_shift = 4, | ||
339 | .per_add_shift = 13, | ||
340 | .per_beta1_shift = 10, | ||
341 | .per_beta2_shift = 8, | ||
342 | .rate_check_up = 2, | ||
343 | .rate_check_down = 12, | ||
344 | .rate_retry_policy = { | ||
345 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
346 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
347 | 0x00, 0x00, 0x00, | ||
348 | }, | ||
349 | }, | ||
350 | .hangover = { | ||
351 | .recover_time = 0, | ||
352 | .hangover_period = 20, | ||
353 | .dynamic_mode = 1, | ||
354 | .early_termination_mode = 1, | ||
355 | .max_period = 20, | ||
356 | .min_period = 1, | ||
357 | .increase_delta = 1, | ||
358 | .decrease_delta = 2, | ||
359 | .quiet_time = 4, | ||
360 | .increase_time = 1, | ||
361 | .window_size = 16, | ||
362 | }, | ||
363 | }; | ||
364 | |||
365 | static struct wl12xx_priv_conf wl12xx_default_priv_conf = { | ||
366 | .rf = { | ||
367 | .tx_per_channel_power_compensation_2 = { | ||
368 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
369 | }, | ||
370 | .tx_per_channel_power_compensation_5 = { | ||
371 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
372 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
373 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
374 | }, | ||
375 | }, | ||
376 | .mem_wl127x = { | ||
377 | .num_stations = 1, | ||
378 | .ssid_profiles = 1, | ||
379 | .rx_block_num = 70, | ||
380 | .tx_min_block_num = 40, | ||
381 | .dynamic_memory = 1, | ||
382 | .min_req_tx_blocks = 100, | ||
383 | .min_req_rx_blocks = 22, | ||
384 | .tx_min = 27, | ||
385 | }, | ||
386 | |||
387 | }; | ||
388 | |||
389 | #define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1 | ||
390 | #define WL12XX_TX_HW_BLOCK_GEM_SPARE 2 | ||
391 | #define WL12XX_TX_HW_BLOCK_SIZE 252 | ||
392 | |||
393 | static const u8 wl12xx_rate_to_idx_2ghz[] = { | ||
394 | /* MCS rates are used only with 11n */ | ||
395 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
396 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */ | ||
397 | 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */ | ||
398 | 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */ | ||
399 | 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */ | ||
400 | 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */ | ||
401 | 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */ | ||
402 | 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */ | ||
403 | 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */ | ||
404 | |||
405 | 11, /* WL12XX_CONF_HW_RXTX_RATE_54 */ | ||
406 | 10, /* WL12XX_CONF_HW_RXTX_RATE_48 */ | ||
407 | 9, /* WL12XX_CONF_HW_RXTX_RATE_36 */ | ||
408 | 8, /* WL12XX_CONF_HW_RXTX_RATE_24 */ | ||
409 | |||
410 | /* TI-specific rate */ | ||
411 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */ | ||
412 | |||
413 | 7, /* WL12XX_CONF_HW_RXTX_RATE_18 */ | ||
414 | 6, /* WL12XX_CONF_HW_RXTX_RATE_12 */ | ||
415 | 3, /* WL12XX_CONF_HW_RXTX_RATE_11 */ | ||
416 | 5, /* WL12XX_CONF_HW_RXTX_RATE_9 */ | ||
417 | 4, /* WL12XX_CONF_HW_RXTX_RATE_6 */ | ||
418 | 2, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */ | ||
419 | 1, /* WL12XX_CONF_HW_RXTX_RATE_2 */ | ||
420 | 0 /* WL12XX_CONF_HW_RXTX_RATE_1 */ | ||
421 | }; | ||
422 | |||
423 | static const u8 wl12xx_rate_to_idx_5ghz[] = { | ||
424 | /* MCS rates are used only with 11n */ | ||
425 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
426 | 7, /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */ | ||
427 | 6, /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */ | ||
428 | 5, /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */ | ||
429 | 4, /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */ | ||
430 | 3, /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */ | ||
431 | 2, /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */ | ||
432 | 1, /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */ | ||
433 | 0, /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */ | ||
434 | |||
435 | 7, /* WL12XX_CONF_HW_RXTX_RATE_54 */ | ||
436 | 6, /* WL12XX_CONF_HW_RXTX_RATE_48 */ | ||
437 | 5, /* WL12XX_CONF_HW_RXTX_RATE_36 */ | ||
438 | 4, /* WL12XX_CONF_HW_RXTX_RATE_24 */ | ||
439 | |||
440 | /* TI-specific rate */ | ||
441 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22 */ | ||
442 | |||
443 | 3, /* WL12XX_CONF_HW_RXTX_RATE_18 */ | ||
444 | 2, /* WL12XX_CONF_HW_RXTX_RATE_12 */ | ||
445 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11 */ | ||
446 | 1, /* WL12XX_CONF_HW_RXTX_RATE_9 */ | ||
447 | 0, /* WL12XX_CONF_HW_RXTX_RATE_6 */ | ||
448 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5 */ | ||
449 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2 */ | ||
450 | CONF_HW_RXTX_RATE_UNSUPPORTED /* WL12XX_CONF_HW_RXTX_RATE_1 */ | ||
451 | }; | ||
452 | |||
453 | static const u8 *wl12xx_band_rate_to_idx[] = { | ||
454 | [IEEE80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz, | ||
455 | [IEEE80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz | ||
456 | }; | ||
457 | |||
458 | enum wl12xx_hw_rates { | ||
459 | WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0, | ||
460 | WL12XX_CONF_HW_RXTX_RATE_MCS7, | ||
461 | WL12XX_CONF_HW_RXTX_RATE_MCS6, | ||
462 | WL12XX_CONF_HW_RXTX_RATE_MCS5, | ||
463 | WL12XX_CONF_HW_RXTX_RATE_MCS4, | ||
464 | WL12XX_CONF_HW_RXTX_RATE_MCS3, | ||
465 | WL12XX_CONF_HW_RXTX_RATE_MCS2, | ||
466 | WL12XX_CONF_HW_RXTX_RATE_MCS1, | ||
467 | WL12XX_CONF_HW_RXTX_RATE_MCS0, | ||
468 | WL12XX_CONF_HW_RXTX_RATE_54, | ||
469 | WL12XX_CONF_HW_RXTX_RATE_48, | ||
470 | WL12XX_CONF_HW_RXTX_RATE_36, | ||
471 | WL12XX_CONF_HW_RXTX_RATE_24, | ||
472 | WL12XX_CONF_HW_RXTX_RATE_22, | ||
473 | WL12XX_CONF_HW_RXTX_RATE_18, | ||
474 | WL12XX_CONF_HW_RXTX_RATE_12, | ||
475 | WL12XX_CONF_HW_RXTX_RATE_11, | ||
476 | WL12XX_CONF_HW_RXTX_RATE_9, | ||
477 | WL12XX_CONF_HW_RXTX_RATE_6, | ||
478 | WL12XX_CONF_HW_RXTX_RATE_5_5, | ||
479 | WL12XX_CONF_HW_RXTX_RATE_2, | ||
480 | WL12XX_CONF_HW_RXTX_RATE_1, | ||
481 | WL12XX_CONF_HW_RXTX_RATE_MAX, | ||
482 | }; | ||
483 | |||
484 | static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = { | ||
485 | [PART_DOWN] = { | ||
486 | .mem = { | ||
487 | .start = 0x00000000, | ||
488 | .size = 0x000177c0 | ||
489 | }, | ||
490 | .reg = { | ||
491 | .start = REGISTERS_BASE, | ||
492 | .size = 0x00008800 | ||
493 | }, | ||
494 | .mem2 = { | ||
495 | .start = 0x00000000, | ||
496 | .size = 0x00000000 | ||
497 | }, | ||
498 | .mem3 = { | ||
499 | .start = 0x00000000, | ||
500 | .size = 0x00000000 | ||
501 | }, | ||
502 | }, | ||
503 | |||
504 | [PART_BOOT] = { /* in wl12xx we can use a mix of work and down | ||
505 | * partition here */ | ||
506 | .mem = { | ||
507 | .start = 0x00040000, | ||
508 | .size = 0x00014fc0 | ||
509 | }, | ||
510 | .reg = { | ||
511 | .start = REGISTERS_BASE, | ||
512 | .size = 0x00008800 | ||
513 | }, | ||
514 | .mem2 = { | ||
515 | .start = 0x00000000, | ||
516 | .size = 0x00000000 | ||
517 | }, | ||
518 | .mem3 = { | ||
519 | .start = 0x00000000, | ||
520 | .size = 0x00000000 | ||
521 | }, | ||
522 | }, | ||
523 | |||
524 | [PART_WORK] = { | ||
525 | .mem = { | ||
526 | .start = 0x00040000, | ||
527 | .size = 0x00014fc0 | ||
528 | }, | ||
529 | .reg = { | ||
530 | .start = REGISTERS_BASE, | ||
531 | .size = 0x0000a000 | ||
532 | }, | ||
533 | .mem2 = { | ||
534 | .start = 0x003004f8, | ||
535 | .size = 0x00000004 | ||
536 | }, | ||
537 | .mem3 = { | ||
538 | .start = 0x00040404, | ||
539 | .size = 0x00000000 | ||
540 | }, | ||
541 | }, | ||
542 | |||
543 | [PART_DRPW] = { | ||
544 | .mem = { | ||
545 | .start = 0x00040000, | ||
546 | .size = 0x00014fc0 | ||
547 | }, | ||
548 | .reg = { | ||
549 | .start = DRPW_BASE, | ||
550 | .size = 0x00006000 | ||
551 | }, | ||
552 | .mem2 = { | ||
553 | .start = 0x00000000, | ||
554 | .size = 0x00000000 | ||
555 | }, | ||
556 | .mem3 = { | ||
557 | .start = 0x00000000, | ||
558 | .size = 0x00000000 | ||
559 | } | ||
560 | } | ||
561 | }; | ||
562 | |||
563 | static const int wl12xx_rtable[REG_TABLE_LEN] = { | ||
564 | [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL, | ||
565 | [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR, | ||
566 | [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK, | ||
567 | [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR, | ||
568 | [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR, | ||
569 | [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG, | ||
570 | [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK, | ||
571 | [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4, | ||
572 | [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B, | ||
573 | [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS, | ||
574 | |||
575 | /* data access memory addresses, used with partition translation */ | ||
576 | [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA, | ||
577 | [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA, | ||
578 | |||
579 | /* raw data access memory addresses */ | ||
580 | [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR, | ||
581 | }; | ||
582 | |||
583 | /* TODO: maybe move to a new header file? */ | ||
584 | #define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" | ||
585 | #define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" | ||
586 | #define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" | ||
587 | |||
588 | #define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" | ||
589 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" | ||
590 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" | ||
591 | |||
592 | static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | ||
593 | { | ||
594 | if (wl->chip.id != CHIP_ID_1283_PG20) { | ||
595 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | ||
596 | struct wl1271_rx_mem_pool_addr rx_mem_addr; | ||
597 | |||
598 | /* | ||
599 | * Choose the block we want to read | ||
600 | * For aggregated packets, only the first memory block | ||
601 | * should be retrieved. The FW takes care of the rest. | ||
602 | */ | ||
603 | u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK; | ||
604 | |||
605 | rx_mem_addr.addr = (mem_block << 8) + | ||
606 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); | ||
607 | |||
608 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; | ||
609 | |||
610 | wl1271_write(wl, WL1271_SLV_REG_DATA, | ||
611 | &rx_mem_addr, sizeof(rx_mem_addr), false); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | static int wl12xx_identify_chip(struct wl1271 *wl) | ||
616 | { | ||
617 | int ret = 0; | ||
618 | |||
619 | switch (wl->chip.id) { | ||
620 | case CHIP_ID_1271_PG10: | ||
621 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", | ||
622 | wl->chip.id); | ||
623 | |||
624 | /* clear the alignment quirk, since we don't support it */ | ||
625 | wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
626 | |||
627 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; | ||
628 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | ||
629 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | ||
630 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, | ||
631 | sizeof(wl->conf.mem)); | ||
632 | |||
633 | /* read data preparation is only needed by wl127x */ | ||
634 | wl->ops->prepare_read = wl127x_prepare_read; | ||
635 | |||
636 | break; | ||
637 | |||
638 | case CHIP_ID_1271_PG20: | ||
639 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | ||
640 | wl->chip.id); | ||
641 | |||
642 | /* clear the alignment quirk, since we don't support it */ | ||
643 | wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
644 | |||
645 | wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; | ||
646 | wl->plt_fw_name = WL127X_PLT_FW_NAME; | ||
647 | wl->sr_fw_name = WL127X_FW_NAME_SINGLE; | ||
648 | wl->mr_fw_name = WL127X_FW_NAME_MULTI; | ||
649 | memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, | ||
650 | sizeof(wl->conf.mem)); | ||
651 | |||
652 | /* read data preparation is only needed by wl127x */ | ||
653 | wl->ops->prepare_read = wl127x_prepare_read; | ||
654 | |||
655 | break; | ||
656 | |||
657 | case CHIP_ID_1283_PG20: | ||
658 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | ||
659 | wl->chip.id); | ||
660 | wl->plt_fw_name = WL128X_PLT_FW_NAME; | ||
661 | wl->sr_fw_name = WL128X_FW_NAME_SINGLE; | ||
662 | wl->mr_fw_name = WL128X_FW_NAME_MULTI; | ||
663 | break; | ||
664 | case CHIP_ID_1283_PG10: | ||
665 | default: | ||
666 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | ||
667 | ret = -ENODEV; | ||
668 | goto out; | ||
669 | } | ||
670 | |||
671 | out: | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
676 | { | ||
677 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
678 | addr = (addr >> 1) + 0x30000; | ||
679 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | ||
680 | |||
681 | /* write value to OCP_POR_WDATA */ | ||
682 | wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val); | ||
683 | |||
684 | /* write 1 to OCP_CMD */ | ||
685 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); | ||
686 | } | ||
687 | |||
688 | static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr) | ||
689 | { | ||
690 | u32 val; | ||
691 | int timeout = OCP_CMD_LOOP; | ||
692 | |||
693 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
694 | addr = (addr >> 1) + 0x30000; | ||
695 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | ||
696 | |||
697 | /* write 2 to OCP_CMD */ | ||
698 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); | ||
699 | |||
700 | /* poll for data ready */ | ||
701 | do { | ||
702 | val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); | ||
703 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
704 | |||
705 | if (!timeout) { | ||
706 | wl1271_warning("Top register access timed out."); | ||
707 | return 0xffff; | ||
708 | } | ||
709 | |||
710 | /* check data status and return if OK */ | ||
711 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
712 | return val & 0xffff; | ||
713 | else { | ||
714 | wl1271_warning("Top register access returned error."); | ||
715 | return 0xffff; | ||
716 | } | ||
717 | } | ||
718 | |||
719 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | ||
720 | { | ||
721 | u16 spare_reg; | ||
722 | |||
723 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ | ||
724 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | ||
725 | if (spare_reg == 0xFFFF) | ||
726 | return -EFAULT; | ||
727 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); | ||
728 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | ||
729 | |||
730 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ | ||
731 | wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, | ||
732 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); | ||
733 | |||
734 | /* Delay execution for 15msec, to let the HW settle */ | ||
735 | mdelay(15); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | ||
741 | { | ||
742 | u16 tcxo_detection; | ||
743 | |||
744 | tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG); | ||
745 | if (tcxo_detection & TCXO_DET_FAILED) | ||
746 | return false; | ||
747 | |||
748 | return true; | ||
749 | } | ||
750 | |||
751 | static bool wl128x_is_fref_valid(struct wl1271 *wl) | ||
752 | { | ||
753 | u16 fref_detection; | ||
754 | |||
755 | fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG); | ||
756 | if (fref_detection & FREF_CLK_DETECT_FAIL) | ||
757 | return false; | ||
758 | |||
759 | return true; | ||
760 | } | ||
761 | |||
762 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) | ||
763 | { | ||
764 | wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); | ||
765 | wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
766 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | ||
772 | { | ||
773 | u16 spare_reg; | ||
774 | u16 pll_config; | ||
775 | u8 input_freq; | ||
776 | |||
777 | /* Mask bits [3:1] in the sys_clk_cfg register */ | ||
778 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | ||
779 | if (spare_reg == 0xFFFF) | ||
780 | return -EFAULT; | ||
781 | spare_reg |= BIT(2); | ||
782 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | ||
783 | |||
784 | /* Handle special cases of the TCXO clock */ | ||
785 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | ||
786 | wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) | ||
787 | return wl128x_manually_configure_mcs_pll(wl); | ||
788 | |||
789 | /* Set the input frequency according to the selected clock source */ | ||
790 | input_freq = (clk & 1) + 1; | ||
791 | |||
792 | pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG); | ||
793 | if (pll_config == 0xFFFF) | ||
794 | return -EFAULT; | ||
795 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); | ||
796 | pll_config |= MCS_PLL_ENABLE_HP; | ||
797 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * WL128x has two clocks input - TCXO and FREF. | ||
804 | * TCXO is the main clock of the device, while FREF is used to sync | ||
805 | * between the GPS and the cellular modem. | ||
806 | * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used | ||
807 | * as the WLAN/BT main clock. | ||
808 | */ | ||
809 | static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | ||
810 | { | ||
811 | u16 sys_clk_cfg; | ||
812 | |||
813 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | ||
814 | if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || | ||
815 | wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { | ||
816 | if (!wl128x_switch_tcxo_to_fref(wl)) | ||
817 | return -EINVAL; | ||
818 | goto fref_clk; | ||
819 | } | ||
820 | |||
821 | /* Query the HW, to determine which clock source we should use */ | ||
822 | sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG); | ||
823 | if (sys_clk_cfg == 0xFFFF) | ||
824 | return -EINVAL; | ||
825 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) | ||
826 | goto fref_clk; | ||
827 | |||
828 | /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ | ||
829 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || | ||
830 | wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { | ||
831 | if (!wl128x_switch_tcxo_to_fref(wl)) | ||
832 | return -EINVAL; | ||
833 | goto fref_clk; | ||
834 | } | ||
835 | |||
836 | /* TCXO clock is selected */ | ||
837 | if (!wl128x_is_tcxo_valid(wl)) | ||
838 | return -EINVAL; | ||
839 | *selected_clock = wl->tcxo_clock; | ||
840 | goto config_mcs_pll; | ||
841 | |||
842 | fref_clk: | ||
843 | /* FREF clock is selected */ | ||
844 | if (!wl128x_is_fref_valid(wl)) | ||
845 | return -EINVAL; | ||
846 | *selected_clock = wl->ref_clock; | ||
847 | |||
848 | config_mcs_pll: | ||
849 | return wl128x_configure_mcs_pll(wl, *selected_clock); | ||
850 | } | ||
851 | |||
852 | static int wl127x_boot_clk(struct wl1271 *wl) | ||
853 | { | ||
854 | u32 pause; | ||
855 | u32 clk; | ||
856 | |||
857 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | ||
858 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; | ||
859 | |||
860 | if (wl->ref_clock == CONF_REF_CLK_19_2_E || | ||
861 | wl->ref_clock == CONF_REF_CLK_38_4_E || | ||
862 | wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) | ||
863 | /* ref clk: 19.2/38.4/38.4-XTAL */ | ||
864 | clk = 0x3; | ||
865 | else if (wl->ref_clock == CONF_REF_CLK_26_E || | ||
866 | wl->ref_clock == CONF_REF_CLK_52_E) | ||
867 | /* ref clk: 26/52 */ | ||
868 | clk = 0x5; | ||
869 | else | ||
870 | return -EINVAL; | ||
871 | |||
872 | if (wl->ref_clock != CONF_REF_CLK_19_2_E) { | ||
873 | u16 val; | ||
874 | /* Set clock type (open drain) */ | ||
875 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); | ||
876 | val &= FREF_CLK_TYPE_BITS; | ||
877 | wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | ||
878 | |||
879 | /* Set clock pull mode (no pull) */ | ||
880 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
881 | val |= NO_PULL; | ||
882 | wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
883 | } else { | ||
884 | u16 val; | ||
885 | /* Set clock polarity */ | ||
886 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY); | ||
887 | val &= FREF_CLK_POLARITY_BITS; | ||
888 | val |= CLK_REQ_OUTN_SEL; | ||
889 | wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | ||
890 | } | ||
891 | |||
892 | wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); | ||
893 | |||
894 | pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); | ||
895 | |||
896 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | ||
897 | |||
898 | pause &= ~(WU_COUNTER_PAUSE_VAL); | ||
899 | pause |= WU_COUNTER_PAUSE_VAL; | ||
900 | wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | ||
906 | { | ||
907 | unsigned long timeout; | ||
908 | u32 boot_data; | ||
909 | |||
910 | /* perform soft reset */ | ||
911 | wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | ||
912 | |||
913 | /* SOFT_RESET is self clearing */ | ||
914 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | ||
915 | while (1) { | ||
916 | boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); | ||
917 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | ||
918 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | ||
919 | break; | ||
920 | |||
921 | if (time_after(jiffies, timeout)) { | ||
922 | /* 1.2 check pWhalBus->uSelfClearTime if the | ||
923 | * timeout was reached */ | ||
924 | wl1271_error("soft reset timeout"); | ||
925 | return -1; | ||
926 | } | ||
927 | |||
928 | udelay(SOFT_RESET_STALL_TIME); | ||
929 | } | ||
930 | |||
931 | /* disable Rx/Tx */ | ||
932 | wl1271_write32(wl, WL12XX_ENABLE, 0x0); | ||
933 | |||
934 | /* disable auto calibration on start*/ | ||
935 | wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); | ||
936 | |||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | static int wl12xx_pre_boot(struct wl1271 *wl) | ||
941 | { | ||
942 | int ret = 0; | ||
943 | u32 clk; | ||
944 | int selected_clock = -1; | ||
945 | |||
946 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
947 | ret = wl128x_boot_clk(wl, &selected_clock); | ||
948 | if (ret < 0) | ||
949 | goto out; | ||
950 | } else { | ||
951 | ret = wl127x_boot_clk(wl); | ||
952 | if (ret < 0) | ||
953 | goto out; | ||
954 | } | ||
955 | |||
956 | /* Continue the ELP wake up sequence */ | ||
957 | wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | ||
958 | udelay(500); | ||
959 | |||
960 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | ||
961 | |||
962 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | ||
963 | to be used by DRPw FW. The RTRIM value will be added by the FW | ||
964 | before taking DRPw out of reset */ | ||
965 | |||
966 | clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); | ||
967 | |||
968 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | ||
969 | |||
970 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
971 | clk |= ((selected_clock & 0x3) << 1) << 4; | ||
972 | else | ||
973 | clk |= (wl->ref_clock << 1) << 4; | ||
974 | |||
975 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); | ||
976 | |||
977 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
978 | |||
979 | /* Disable interrupts */ | ||
980 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | ||
981 | |||
982 | ret = wl1271_boot_soft_reset(wl); | ||
983 | if (ret < 0) | ||
984 | goto out; | ||
985 | |||
986 | out: | ||
987 | return ret; | ||
988 | } | ||
989 | |||
990 | static void wl12xx_pre_upload(struct wl1271 *wl) | ||
991 | { | ||
992 | u32 tmp; | ||
993 | |||
994 | /* write firmware's last address (ie. it's length) to | ||
995 | * ACX_EEPROMLESS_IND_REG */ | ||
996 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | ||
997 | |||
998 | wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); | ||
999 | |||
1000 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | ||
1001 | |||
1002 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | ||
1003 | |||
1004 | /* 6. read the EEPROM parameters */ | ||
1005 | tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); | ||
1006 | |||
1007 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | ||
1008 | * to upload_fw) */ | ||
1009 | |||
1010 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1011 | 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 | |||
1018 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); | ||
1019 | |||
1020 | /* We use HIGH polarity, so unset the LOW bit */ | ||
1021 | polarity &= ~POLARITY_LOW; | ||
1022 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); | ||
1023 | |||
1024 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR); | ||
1025 | |||
1026 | wlcore_enable_interrupts(wl); | ||
1027 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | ||
1028 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | ||
1029 | |||
1030 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); | ||
1031 | } | ||
1032 | |||
1033 | static int wl12xx_boot(struct wl1271 *wl) | ||
1034 | { | ||
1035 | int ret; | ||
1036 | |||
1037 | ret = wl12xx_pre_boot(wl); | ||
1038 | if (ret < 0) | ||
1039 | goto out; | ||
1040 | |||
1041 | ret = wlcore_boot_upload_nvs(wl); | ||
1042 | if (ret < 0) | ||
1043 | goto out; | ||
1044 | |||
1045 | wl12xx_pre_upload(wl); | ||
1046 | |||
1047 | ret = wlcore_boot_upload_firmware(wl); | ||
1048 | if (ret < 0) | ||
1049 | goto out; | ||
1050 | |||
1051 | ret = wlcore_boot_run_firmware(wl); | ||
1052 | if (ret < 0) | ||
1053 | goto out; | ||
1054 | |||
1055 | wl12xx_enable_interrupts(wl); | ||
1056 | |||
1057 | out: | ||
1058 | return ret; | ||
1059 | } | ||
1060 | |||
1061 | static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | ||
1062 | void *buf, size_t len) | ||
1063 | { | ||
1064 | wl1271_write(wl, cmd_box_addr, buf, len, false); | ||
1065 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | ||
1066 | } | ||
1067 | |||
1068 | static void wl12xx_ack_event(struct wl1271 *wl) | ||
1069 | { | ||
1070 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK); | ||
1071 | } | ||
1072 | |||
1073 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | ||
1074 | { | ||
1075 | u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE; | ||
1076 | u32 align_len = wlcore_calc_packet_alignment(wl, len); | ||
1077 | |||
1078 | return (align_len + blk_size - 1) / blk_size + spare_blks; | ||
1079 | } | ||
1080 | |||
1081 | static void | ||
1082 | wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | ||
1083 | u32 blks, u32 spare_blks) | ||
1084 | { | ||
1085 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
1086 | desc->wl128x_mem.total_mem_blocks = blks; | ||
1087 | } else { | ||
1088 | desc->wl127x_mem.extra_blocks = spare_blks; | ||
1089 | desc->wl127x_mem.total_mem_blocks = blks; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | static void | ||
1094 | wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | ||
1095 | struct sk_buff *skb) | ||
1096 | { | ||
1097 | u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len); | ||
1098 | |||
1099 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
1100 | desc->wl128x_mem.extra_bytes = aligned_len - skb->len; | ||
1101 | desc->length = cpu_to_le16(aligned_len >> 2); | ||
1102 | |||
1103 | wl1271_debug(DEBUG_TX, | ||
1104 | "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d", | ||
1105 | desc->hlid, | ||
1106 | le16_to_cpu(desc->length), | ||
1107 | le16_to_cpu(desc->life_time), | ||
1108 | desc->wl128x_mem.total_mem_blocks, | ||
1109 | desc->wl128x_mem.extra_bytes); | ||
1110 | } else { | ||
1111 | /* calculate number of padding bytes */ | ||
1112 | int pad = aligned_len - skb->len; | ||
1113 | desc->tx_attr |= | ||
1114 | cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD); | ||
1115 | |||
1116 | /* Store the aligned length in terms of words */ | ||
1117 | desc->length = cpu_to_le16(aligned_len >> 2); | ||
1118 | |||
1119 | wl1271_debug(DEBUG_TX, | ||
1120 | "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d", | ||
1121 | pad, desc->hlid, | ||
1122 | le16_to_cpu(desc->length), | ||
1123 | le16_to_cpu(desc->life_time), | ||
1124 | desc->wl127x_mem.total_mem_blocks); | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | static enum wl_rx_buf_align | ||
1129 | wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | ||
1130 | { | ||
1131 | if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD) | ||
1132 | return WLCORE_RX_BUF_UNALIGNED; | ||
1133 | |||
1134 | return WLCORE_RX_BUF_ALIGNED; | ||
1135 | } | ||
1136 | |||
1137 | static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | ||
1138 | u32 data_len) | ||
1139 | { | ||
1140 | struct wl1271_rx_descriptor *desc = rx_data; | ||
1141 | |||
1142 | /* invalid packet */ | ||
1143 | if (data_len < sizeof(*desc) || | ||
1144 | data_len < sizeof(*desc) + desc->pad_len) | ||
1145 | return 0; | ||
1146 | |||
1147 | return data_len - sizeof(*desc) - desc->pad_len; | ||
1148 | } | ||
1149 | |||
1150 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) | ||
1151 | { | ||
1152 | if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff)) | ||
1153 | return; | ||
1154 | |||
1155 | wl1271_tx_complete(wl); | ||
1156 | } | ||
1157 | |||
1158 | static int wl12xx_hw_init(struct wl1271 *wl) | ||
1159 | { | ||
1160 | int ret; | ||
1161 | |||
1162 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
1163 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; | ||
1164 | |||
1165 | ret = wl128x_cmd_general_parms(wl); | ||
1166 | if (ret < 0) | ||
1167 | goto out; | ||
1168 | ret = wl128x_cmd_radio_parms(wl); | ||
1169 | if (ret < 0) | ||
1170 | goto out; | ||
1171 | |||
1172 | if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) | ||
1173 | /* Enable SDIO padding */ | ||
1174 | host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; | ||
1175 | |||
1176 | /* Must be before wl1271_acx_init_mem_config() */ | ||
1177 | ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); | ||
1178 | if (ret < 0) | ||
1179 | goto out; | ||
1180 | } else { | ||
1181 | ret = wl1271_cmd_general_parms(wl); | ||
1182 | if (ret < 0) | ||
1183 | goto out; | ||
1184 | ret = wl1271_cmd_radio_parms(wl); | ||
1185 | if (ret < 0) | ||
1186 | goto out; | ||
1187 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
1188 | if (ret < 0) | ||
1189 | goto out; | ||
1190 | } | ||
1191 | out: | ||
1192 | return ret; | ||
1193 | } | ||
1194 | |||
1195 | static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl, | ||
1196 | struct wl12xx_vif *wlvif) | ||
1197 | { | ||
1198 | return wlvif->rate_set; | ||
1199 | } | ||
1200 | |||
1201 | static int wl12xx_identify_fw(struct wl1271 *wl) | ||
1202 | { | ||
1203 | unsigned int *fw_ver = wl->chip.fw_ver; | ||
1204 | |||
1205 | /* Only new station firmwares support routing fw logs to the host */ | ||
1206 | if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && | ||
1207 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) | ||
1208 | wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
1209 | |||
1210 | /* This feature is not yet supported for AP mode */ | ||
1211 | if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) | ||
1212 | wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static void wl12xx_conf_init(struct wl1271 *wl) | ||
1218 | { | ||
1219 | struct wl12xx_priv *priv = wl->priv; | ||
1220 | |||
1221 | /* apply driver default configuration */ | ||
1222 | memcpy(&wl->conf, &wl12xx_conf, sizeof(wl12xx_conf)); | ||
1223 | |||
1224 | /* apply default private configuration */ | ||
1225 | memcpy(&priv->conf, &wl12xx_default_priv_conf, sizeof(priv->conf)); | ||
1226 | } | ||
1227 | |||
1228 | static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | ||
1229 | { | ||
1230 | bool supported = false; | ||
1231 | u8 major, minor; | ||
1232 | |||
1233 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
1234 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
1235 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); | ||
1236 | |||
1237 | /* in wl128x we have the MAC address if the PG is >= (2, 1) */ | ||
1238 | if (major > 2 || (major == 2 && minor >= 1)) | ||
1239 | supported = true; | ||
1240 | } else { | ||
1241 | major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
1242 | minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver); | ||
1243 | |||
1244 | /* in wl127x we have the MAC address if the PG is >= (3, 1) */ | ||
1245 | if (major == 3 && minor >= 1) | ||
1246 | supported = true; | ||
1247 | } | ||
1248 | |||
1249 | wl1271_debug(DEBUG_PROBE, | ||
1250 | "PG Ver major = %d minor = %d, MAC %s present", | ||
1251 | major, minor, supported ? "is" : "is not"); | ||
1252 | |||
1253 | return supported; | ||
1254 | } | ||
1255 | |||
1256 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | ||
1257 | { | ||
1258 | u32 mac1, mac2; | ||
1259 | |||
1260 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | ||
1261 | |||
1262 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | ||
1263 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | ||
1264 | |||
1265 | /* these are the two parts of the BD_ADDR */ | ||
1266 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | ||
1267 | ((mac1 & 0xff000000) >> 24); | ||
1268 | wl->fuse_nic_addr = mac1 & 0xffffff; | ||
1269 | |||
1270 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | ||
1271 | } | ||
1272 | |||
1273 | static s8 wl12xx_get_pg_ver(struct wl1271 *wl) | ||
1274 | { | ||
1275 | u32 die_info; | ||
1276 | |||
1277 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1278 | die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | ||
1279 | else | ||
1280 | die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | ||
1281 | |||
1282 | return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | ||
1283 | } | ||
1284 | |||
1285 | static void wl12xx_get_mac(struct wl1271 *wl) | ||
1286 | { | ||
1287 | if (wl12xx_mac_in_fuse(wl)) | ||
1288 | wl12xx_get_fuse_mac(wl); | ||
1289 | } | ||
1290 | |||
1291 | static struct wlcore_ops wl12xx_ops = { | ||
1292 | .identify_chip = wl12xx_identify_chip, | ||
1293 | .identify_fw = wl12xx_identify_fw, | ||
1294 | .boot = wl12xx_boot, | ||
1295 | .trigger_cmd = wl12xx_trigger_cmd, | ||
1296 | .ack_event = wl12xx_ack_event, | ||
1297 | .calc_tx_blocks = wl12xx_calc_tx_blocks, | ||
1298 | .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, | ||
1299 | .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, | ||
1300 | .get_rx_buf_align = wl12xx_get_rx_buf_align, | ||
1301 | .get_rx_packet_len = wl12xx_get_rx_packet_len, | ||
1302 | .tx_immediate_compl = NULL, | ||
1303 | .tx_delayed_compl = wl12xx_tx_delayed_compl, | ||
1304 | .hw_init = wl12xx_hw_init, | ||
1305 | .init_vif = NULL, | ||
1306 | .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, | ||
1307 | .get_pg_ver = wl12xx_get_pg_ver, | ||
1308 | .get_mac = wl12xx_get_mac, | ||
1309 | }; | ||
1310 | |||
1311 | static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { | ||
1312 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | | ||
1313 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), | ||
1314 | .ht_supported = true, | ||
1315 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, | ||
1316 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, | ||
1317 | .mcs = { | ||
1318 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
1319 | .rx_highest = cpu_to_le16(72), | ||
1320 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
1321 | }, | ||
1322 | }; | ||
1323 | |||
1324 | static int __devinit wl12xx_probe(struct platform_device *pdev) | ||
1325 | { | ||
1326 | struct wl1271 *wl; | ||
1327 | struct ieee80211_hw *hw; | ||
1328 | struct wl12xx_priv *priv; | ||
1329 | |||
1330 | hw = wlcore_alloc_hw(sizeof(*priv)); | ||
1331 | if (IS_ERR(hw)) { | ||
1332 | wl1271_error("can't allocate hw"); | ||
1333 | return PTR_ERR(hw); | ||
1334 | } | ||
1335 | |||
1336 | wl = hw->priv; | ||
1337 | wl->ops = &wl12xx_ops; | ||
1338 | wl->ptable = wl12xx_ptable; | ||
1339 | wl->rtable = wl12xx_rtable; | ||
1340 | wl->num_tx_desc = 16; | ||
1341 | wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; | ||
1342 | wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE; | ||
1343 | wl->band_rate_to_idx = wl12xx_band_rate_to_idx; | ||
1344 | wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; | ||
1345 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; | ||
1346 | wl->fw_status_priv_len = 0; | ||
1347 | memcpy(&wl->ht_cap, &wl12xx_ht_cap, sizeof(wl12xx_ht_cap)); | ||
1348 | wl12xx_conf_init(wl); | ||
1349 | |||
1350 | return wlcore_probe(wl, pdev); | ||
1351 | } | ||
1352 | |||
1353 | static const struct platform_device_id wl12xx_id_table[] __devinitconst = { | ||
1354 | { "wl12xx", 0 }, | ||
1355 | { } /* Terminating Entry */ | ||
1356 | }; | ||
1357 | MODULE_DEVICE_TABLE(platform, wl12xx_id_table); | ||
1358 | |||
1359 | static struct platform_driver wl12xx_driver = { | ||
1360 | .probe = wl12xx_probe, | ||
1361 | .remove = __devexit_p(wlcore_remove), | ||
1362 | .id_table = wl12xx_id_table, | ||
1363 | .driver = { | ||
1364 | .name = "wl12xx_driver", | ||
1365 | .owner = THIS_MODULE, | ||
1366 | } | ||
1367 | }; | ||
1368 | |||
1369 | static int __init wl12xx_init(void) | ||
1370 | { | ||
1371 | return platform_driver_register(&wl12xx_driver); | ||
1372 | } | ||
1373 | module_init(wl12xx_init); | ||
1374 | |||
1375 | static void __exit wl12xx_exit(void) | ||
1376 | { | ||
1377 | platform_driver_unregister(&wl12xx_driver); | ||
1378 | } | ||
1379 | module_exit(wl12xx_exit); | ||
1380 | |||
1381 | MODULE_LICENSE("GPL v2"); | ||
1382 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | ||
1383 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); | ||
1384 | MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); | ||
1385 | MODULE_FIRMWARE(WL127X_PLT_FW_NAME); | ||
1386 | MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); | ||
1387 | MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); | ||
1388 | MODULE_FIRMWARE(WL128X_PLT_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/ti/wl12xx/reg.h index 340db324bc26..79ede02e2587 100644 --- a/drivers/net/wireless/wl12xx/reg.h +++ b/drivers/net/wireless/ti/wl12xx/reg.h | |||
@@ -33,16 +33,8 @@ | |||
33 | #define REGISTERS_DOWN_SIZE 0x00008800 | 33 | #define REGISTERS_DOWN_SIZE 0x00008800 |
34 | #define REGISTERS_WORK_SIZE 0x0000b000 | 34 | #define REGISTERS_WORK_SIZE 0x0000b000 |
35 | 35 | ||
36 | #define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC | ||
37 | #define FW_STATUS_ADDR (0x14FC0 + 0xA000) | 36 | #define FW_STATUS_ADDR (0x14FC0 + 0xA000) |
38 | 37 | ||
39 | /* ELP register commands */ | ||
40 | #define ELPCTRL_WAKE_UP 0x1 | ||
41 | #define ELPCTRL_WAKE_UP_WLAN_READY 0x5 | ||
42 | #define ELPCTRL_SLEEP 0x0 | ||
43 | /* ELP WLAN_READY bit */ | ||
44 | #define ELPCTRL_WLAN_READY 0x2 | ||
45 | |||
46 | /*=============================================== | 38 | /*=============================================== |
47 | Host Software Reset - 32bit RW | 39 | Host Software Reset - 32bit RW |
48 | ------------------------------------------ | 40 | ------------------------------------------ |
@@ -57,14 +49,14 @@ | |||
57 | (not self-clearing), the Wlan hardware | 49 | (not self-clearing), the Wlan hardware |
58 | exits the software reset state. | 50 | exits the software reset state. |
59 | ===============================================*/ | 51 | ===============================================*/ |
60 | #define ACX_REG_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000) | 52 | #define WL12XX_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000) |
61 | 53 | ||
62 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) | 54 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) |
63 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) | 55 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) |
64 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) | 56 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) |
65 | 57 | ||
66 | #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) | 58 | #define WL12XX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) |
67 | #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) | 59 | #define WL12XX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) |
68 | 60 | ||
69 | /*============================================= | 61 | /*============================================= |
70 | Host Interrupt Mask Register - 32bit (RW) | 62 | Host Interrupt Mask Register - 32bit (RW) |
@@ -94,7 +86,7 @@ | |||
94 | 21- - | 86 | 21- - |
95 | Default: 0x0001 | 87 | Default: 0x0001 |
96 | *==============================================*/ | 88 | *==============================================*/ |
97 | #define ACX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC) | 89 | #define WL12XX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC) |
98 | 90 | ||
99 | /*============================================= | 91 | /*============================================= |
100 | Host Interrupt Mask Set 16bit, (Write only) | 92 | Host Interrupt Mask Set 16bit, (Write only) |
@@ -125,7 +117,7 @@ | |||
125 | Reading this register doesn't | 117 | Reading this register doesn't |
126 | effect its content. | 118 | effect its content. |
127 | =============================================*/ | 119 | =============================================*/ |
128 | #define ACX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8) | 120 | #define WL12XX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8) |
129 | 121 | ||
130 | /*============================================= | 122 | /*============================================= |
131 | Host Interrupt Status Clear on Read Register | 123 | Host Interrupt Status Clear on Read Register |
@@ -148,9 +140,9 @@ | |||
148 | HINT_STS_ND registers, thus making the | 140 | HINT_STS_ND registers, thus making the |
149 | assotiated interrupt inactive. (0-no effect) | 141 | assotiated interrupt inactive. (0-no effect) |
150 | ==============================================*/ | 142 | ==============================================*/ |
151 | #define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) | 143 | #define WL12XX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) |
152 | 144 | ||
153 | #define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538) | 145 | #define WL12XX_REG_RX_DRIVER_COUNTER (REGISTERS_BASE + 0x0538) |
154 | 146 | ||
155 | /* Device Configuration registers*/ | 147 | /* Device Configuration registers*/ |
156 | #define SOR_CFG (REGISTERS_BASE + 0x0800) | 148 | #define SOR_CFG (REGISTERS_BASE + 0x0800) |
@@ -175,9 +167,9 @@ | |||
175 | 1 halt eCPU | 167 | 1 halt eCPU |
176 | 0 enable eCPU | 168 | 0 enable eCPU |
177 | ===============================================*/ | 169 | ===============================================*/ |
178 | #define ACX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804) | 170 | #define WL12XX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804) |
179 | 171 | ||
180 | #define HI_CFG (REGISTERS_BASE + 0x0808) | 172 | #define WL12XX_HI_CFG (REGISTERS_BASE + 0x0808) |
181 | 173 | ||
182 | /*=============================================== | 174 | /*=============================================== |
183 | EEPROM Burst Read Start - 32bit RW | 175 | EEPROM Burst Read Start - 32bit RW |
@@ -196,72 +188,67 @@ | |||
196 | *================================================*/ | 188 | *================================================*/ |
197 | #define ACX_REG_EE_START (REGISTERS_BASE + 0x080C) | 189 | #define ACX_REG_EE_START (REGISTERS_BASE + 0x080C) |
198 | 190 | ||
199 | #define OCP_POR_CTR (REGISTERS_BASE + 0x09B4) | 191 | #define WL12XX_OCP_POR_CTR (REGISTERS_BASE + 0x09B4) |
200 | #define OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8) | 192 | #define WL12XX_OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8) |
201 | #define OCP_DATA_READ (REGISTERS_BASE + 0x09BC) | 193 | #define WL12XX_OCP_DATA_READ (REGISTERS_BASE + 0x09BC) |
202 | #define OCP_CMD (REGISTERS_BASE + 0x09C0) | 194 | #define WL12XX_OCP_CMD (REGISTERS_BASE + 0x09C0) |
203 | |||
204 | #define WL1271_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8) | ||
205 | 195 | ||
206 | #define CHIP_ID_B (REGISTERS_BASE + 0x5674) | 196 | #define WL12XX_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8) |
207 | 197 | ||
208 | #define CHIP_ID_1271_PG10 (0x4030101) | 198 | #define WL12XX_CHIP_ID_B (REGISTERS_BASE + 0x5674) |
209 | #define CHIP_ID_1271_PG20 (0x4030111) | ||
210 | #define CHIP_ID_1283_PG10 (0x05030101) | ||
211 | #define CHIP_ID_1283_PG20 (0x05030111) | ||
212 | 199 | ||
213 | #define ENABLE (REGISTERS_BASE + 0x5450) | 200 | #define WL12XX_ENABLE (REGISTERS_BASE + 0x5450) |
214 | 201 | ||
215 | /* Power Management registers */ | 202 | /* Power Management registers */ |
216 | #define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) | 203 | #define WL12XX_ELP_CFG_MODE (REGISTERS_BASE + 0x5804) |
217 | #define ELP_CMD (REGISTERS_BASE + 0x5808) | 204 | #define WL12XX_ELP_CMD (REGISTERS_BASE + 0x5808) |
218 | #define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) | 205 | #define WL12XX_PLL_CAL_TIME (REGISTERS_BASE + 0x5810) |
219 | #define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) | 206 | #define WL12XX_CLK_REQ_TIME (REGISTERS_BASE + 0x5814) |
220 | #define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) | 207 | #define WL12XX_CLK_BUF_TIME (REGISTERS_BASE + 0x5818) |
221 | 208 | ||
222 | #define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) | 209 | #define WL12XX_CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) |
223 | 210 | ||
224 | /* Scratch Pad registers*/ | 211 | /* Scratch Pad registers*/ |
225 | #define SCR_PAD0 (REGISTERS_BASE + 0x5608) | 212 | #define WL12XX_SCR_PAD0 (REGISTERS_BASE + 0x5608) |
226 | #define SCR_PAD1 (REGISTERS_BASE + 0x560C) | 213 | #define WL12XX_SCR_PAD1 (REGISTERS_BASE + 0x560C) |
227 | #define SCR_PAD2 (REGISTERS_BASE + 0x5610) | 214 | #define WL12XX_SCR_PAD2 (REGISTERS_BASE + 0x5610) |
228 | #define SCR_PAD3 (REGISTERS_BASE + 0x5614) | 215 | #define WL12XX_SCR_PAD3 (REGISTERS_BASE + 0x5614) |
229 | #define SCR_PAD4 (REGISTERS_BASE + 0x5618) | 216 | #define WL12XX_SCR_PAD4 (REGISTERS_BASE + 0x5618) |
230 | #define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) | 217 | #define WL12XX_SCR_PAD4_SET (REGISTERS_BASE + 0x561C) |
231 | #define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) | 218 | #define WL12XX_SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) |
232 | #define SCR_PAD5 (REGISTERS_BASE + 0x5624) | 219 | #define WL12XX_SCR_PAD5 (REGISTERS_BASE + 0x5624) |
233 | #define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) | 220 | #define WL12XX_SCR_PAD5_SET (REGISTERS_BASE + 0x5628) |
234 | #define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) | 221 | #define WL12XX_SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) |
235 | #define SCR_PAD6 (REGISTERS_BASE + 0x5630) | 222 | #define WL12XX_SCR_PAD6 (REGISTERS_BASE + 0x5630) |
236 | #define SCR_PAD7 (REGISTERS_BASE + 0x5634) | 223 | #define WL12XX_SCR_PAD7 (REGISTERS_BASE + 0x5634) |
237 | #define SCR_PAD8 (REGISTERS_BASE + 0x5638) | 224 | #define WL12XX_SCR_PAD8 (REGISTERS_BASE + 0x5638) |
238 | #define SCR_PAD9 (REGISTERS_BASE + 0x563C) | 225 | #define WL12XX_SCR_PAD9 (REGISTERS_BASE + 0x563C) |
239 | 226 | ||
240 | /* Spare registers*/ | 227 | /* Spare registers*/ |
241 | #define SPARE_A1 (REGISTERS_BASE + 0x0994) | 228 | #define WL12XX_SPARE_A1 (REGISTERS_BASE + 0x0994) |
242 | #define SPARE_A2 (REGISTERS_BASE + 0x0998) | 229 | #define WL12XX_SPARE_A2 (REGISTERS_BASE + 0x0998) |
243 | #define SPARE_A3 (REGISTERS_BASE + 0x099C) | 230 | #define WL12XX_SPARE_A3 (REGISTERS_BASE + 0x099C) |
244 | #define SPARE_A4 (REGISTERS_BASE + 0x09A0) | 231 | #define WL12XX_SPARE_A4 (REGISTERS_BASE + 0x09A0) |
245 | #define SPARE_A5 (REGISTERS_BASE + 0x09A4) | 232 | #define WL12XX_SPARE_A5 (REGISTERS_BASE + 0x09A4) |
246 | #define SPARE_A6 (REGISTERS_BASE + 0x09A8) | 233 | #define WL12XX_SPARE_A6 (REGISTERS_BASE + 0x09A8) |
247 | #define SPARE_A7 (REGISTERS_BASE + 0x09AC) | 234 | #define WL12XX_SPARE_A7 (REGISTERS_BASE + 0x09AC) |
248 | #define SPARE_A8 (REGISTERS_BASE + 0x09B0) | 235 | #define WL12XX_SPARE_A8 (REGISTERS_BASE + 0x09B0) |
249 | #define SPARE_B1 (REGISTERS_BASE + 0x5420) | 236 | #define WL12XX_SPARE_B1 (REGISTERS_BASE + 0x5420) |
250 | #define SPARE_B2 (REGISTERS_BASE + 0x5424) | 237 | #define WL12XX_SPARE_B2 (REGISTERS_BASE + 0x5424) |
251 | #define SPARE_B3 (REGISTERS_BASE + 0x5428) | 238 | #define WL12XX_SPARE_B3 (REGISTERS_BASE + 0x5428) |
252 | #define SPARE_B4 (REGISTERS_BASE + 0x542C) | 239 | #define WL12XX_SPARE_B4 (REGISTERS_BASE + 0x542C) |
253 | #define SPARE_B5 (REGISTERS_BASE + 0x5430) | 240 | #define WL12XX_SPARE_B5 (REGISTERS_BASE + 0x5430) |
254 | #define SPARE_B6 (REGISTERS_BASE + 0x5434) | 241 | #define WL12XX_SPARE_B6 (REGISTERS_BASE + 0x5434) |
255 | #define SPARE_B7 (REGISTERS_BASE + 0x5438) | 242 | #define WL12XX_SPARE_B7 (REGISTERS_BASE + 0x5438) |
256 | #define SPARE_B8 (REGISTERS_BASE + 0x543C) | 243 | #define WL12XX_SPARE_B8 (REGISTERS_BASE + 0x543C) |
257 | 244 | ||
258 | #define PLL_PARAMETERS (REGISTERS_BASE + 0x6040) | 245 | #define WL12XX_PLL_PARAMETERS (REGISTERS_BASE + 0x6040) |
259 | #define WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008) | 246 | #define WL12XX_WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008) |
260 | #define WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100) | 247 | #define WL12XX_WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100) |
261 | #define DRPW_SCRATCH_START (DRPW_BASE + 0x002C) | 248 | #define WL12XX_DRPW_SCRATCH_START (DRPW_BASE + 0x002C) |
262 | 249 | ||
263 | 250 | #define WL12XX_CMD_MBOX_ADDRESS 0x407B4 | |
264 | #define ACX_SLV_SOFT_RESET_BIT BIT(1) | 251 | |
265 | #define ACX_REG_EEPROM_START_BIT BIT(1) | 252 | #define ACX_REG_EEPROM_START_BIT BIT(1) |
266 | 253 | ||
267 | /* Command/Information Mailbox Pointers */ | 254 | /* Command/Information Mailbox Pointers */ |
@@ -279,7 +266,7 @@ | |||
279 | the host receives the Init Complete interrupt from | 266 | the host receives the Init Complete interrupt from |
280 | the Wlan hardware. | 267 | the Wlan hardware. |
281 | ===============================================*/ | 268 | ===============================================*/ |
282 | #define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) | 269 | #define WL12XX_REG_COMMAND_MAILBOX_PTR (WL12XX_SCR_PAD0) |
283 | 270 | ||
284 | /*=============================================== | 271 | /*=============================================== |
285 | Information Mailbox Pointer - 32bit RW | 272 | Information Mailbox Pointer - 32bit RW |
@@ -294,7 +281,7 @@ | |||
294 | until after the host receives the Init Complete interrupt from | 281 | until after the host receives the Init Complete interrupt from |
295 | the Wlan hardware. | 282 | the Wlan hardware. |
296 | ===============================================*/ | 283 | ===============================================*/ |
297 | #define REG_EVENT_MAILBOX_PTR (SCR_PAD1) | 284 | #define WL12XX_REG_EVENT_MAILBOX_PTR (WL12XX_SCR_PAD1) |
298 | 285 | ||
299 | /*=============================================== | 286 | /*=============================================== |
300 | EEPROM Read/Write Request 32bit RW | 287 | EEPROM Read/Write Request 32bit RW |
@@ -365,26 +352,6 @@ | |||
365 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f | 352 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f |
366 | #define ACX_CONT_WIND_MAX 0x03ff0000 | 353 | #define ACX_CONT_WIND_MAX 0x03ff0000 |
367 | 354 | ||
368 | /*=============================================== | ||
369 | HI_CFG Interface Configuration Register Values | ||
370 | ------------------------------------------ | ||
371 | ===============================================*/ | ||
372 | #define HI_CFG_UART_ENABLE 0x00000004 | ||
373 | #define HI_CFG_RST232_ENABLE 0x00000008 | ||
374 | #define HI_CFG_CLOCK_REQ_SELECT 0x00000010 | ||
375 | #define HI_CFG_HOST_INT_ENABLE 0x00000020 | ||
376 | #define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 | ||
377 | #define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 | ||
378 | #define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 | ||
379 | #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 | ||
380 | #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 | ||
381 | |||
382 | #define HI_CFG_DEF_VAL \ | ||
383 | (HI_CFG_UART_ENABLE | \ | ||
384 | HI_CFG_RST232_ENABLE | \ | ||
385 | HI_CFG_CLOCK_REQ_SELECT | \ | ||
386 | HI_CFG_HOST_INT_ENABLE) | ||
387 | |||
388 | #define REF_FREQ_19_2 0 | 355 | #define REF_FREQ_19_2 0 |
389 | #define REF_FREQ_26_0 1 | 356 | #define REF_FREQ_26_0 1 |
390 | #define REF_FREQ_38_4 2 | 357 | #define REF_FREQ_38_4 2 |
@@ -400,38 +367,19 @@ | |||
400 | #define LUT_PARAM_BB_PLL_LOOP_FILTER 5 | 367 | #define LUT_PARAM_BB_PLL_LOOP_FILTER 5 |
401 | #define LUT_PARAM_NUM 6 | 368 | #define LUT_PARAM_NUM 6 |
402 | 369 | ||
403 | #define ACX_EEPROMLESS_IND_REG (SCR_PAD4) | 370 | #define WL12XX_EEPROMLESS_IND (WL12XX_SCR_PAD4) |
404 | #define USE_EEPROM 0 | 371 | #define USE_EEPROM 0 |
405 | #define SOFT_RESET_MAX_TIME 1000000 | ||
406 | #define SOFT_RESET_STALL_TIME 1000 | ||
407 | #define NVS_DATA_BUNDARY_ALIGNMENT 4 | 372 | #define NVS_DATA_BUNDARY_ALIGNMENT 4 |
408 | 373 | ||
409 | |||
410 | /* Firmware image load chunk size */ | ||
411 | #define CHUNK_SIZE 16384 | ||
412 | |||
413 | /* Firmware image header size */ | 374 | /* Firmware image header size */ |
414 | #define FW_HDR_SIZE 8 | 375 | #define FW_HDR_SIZE 8 |
415 | 376 | ||
416 | #define ECPU_CONTROL_HALT 0x00000101 | ||
417 | |||
418 | |||
419 | /****************************************************************************** | 377 | /****************************************************************************** |
420 | 378 | ||
421 | CHANNELS, BAND & REG DOMAINS definitions | 379 | CHANNELS, BAND & REG DOMAINS definitions |
422 | 380 | ||
423 | ******************************************************************************/ | 381 | ******************************************************************************/ |
424 | 382 | ||
425 | |||
426 | enum { | ||
427 | RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ | ||
428 | RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ | ||
429 | RADIO_BAND_JAPAN_4_9_GHZ = 2, | ||
430 | DEFAULT_BAND = RADIO_BAND_2_4GHZ, | ||
431 | INVALID_BAND = 0xFE, | ||
432 | MAX_RADIO_BANDS = 0xFF | ||
433 | }; | ||
434 | |||
435 | #define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ | 383 | #define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ |
436 | #define OFDM_RATE_BIT BIT(6) | 384 | #define OFDM_RATE_BIT BIT(6) |
437 | #define PBCC_RATE_BIT BIT(7) | 385 | #define PBCC_RATE_BIT BIT(7) |
@@ -465,14 +413,82 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
465 | 413 | ||
466 | ******************************************************************************/ | 414 | ******************************************************************************/ |
467 | 415 | ||
416 | #define OCP_CMD_LOOP 32 | ||
417 | #define OCP_CMD_WRITE 0x1 | ||
418 | #define OCP_CMD_READ 0x2 | ||
419 | #define OCP_READY_MASK BIT(18) | ||
420 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
421 | #define OCP_STATUS_NO_RESP 0x00000 | ||
422 | #define OCP_STATUS_OK 0x10000 | ||
423 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
424 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
425 | |||
426 | #define OCP_REG_POLARITY 0x0064 | ||
427 | #define OCP_REG_CLK_TYPE 0x0448 | ||
428 | #define OCP_REG_CLK_POLARITY 0x0cb2 | ||
429 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
430 | |||
431 | #define POLARITY_LOW BIT(1) | ||
432 | #define NO_PULL (BIT(14) | BIT(15)) | ||
433 | |||
434 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | ||
435 | #define CLK_REQ_PRCM 0x100 | ||
436 | #define FREF_CLK_POLARITY_BITS 0xfffff8ff | ||
437 | #define CLK_REQ_OUTN_SEL 0x700 | ||
438 | |||
439 | #define WU_COUNTER_PAUSE_VAL 0x3FF | ||
440 | |||
441 | /* PLL configuration algorithm for wl128x */ | ||
442 | #define SYS_CLK_CFG_REG 0x2200 | ||
443 | /* Bit[0] - 0-TCXO, 1-FREF */ | ||
444 | #define MCS_PLL_CLK_SEL_FREF BIT(0) | ||
445 | /* Bit[3:2] - 01-TCXO, 10-FREF */ | ||
446 | #define WL_CLK_REQ_TYPE_FREF BIT(3) | ||
447 | #define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) | ||
448 | /* Bit[4] - 0-TCXO, 1-FREF */ | ||
449 | #define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) | ||
450 | |||
451 | #define TCXO_ILOAD_INT_REG 0x2264 | ||
452 | #define TCXO_CLK_DETECT_REG 0x2266 | ||
453 | |||
454 | #define TCXO_DET_FAILED BIT(4) | ||
455 | |||
456 | #define FREF_ILOAD_INT_REG 0x2084 | ||
457 | #define FREF_CLK_DETECT_REG 0x2086 | ||
458 | #define FREF_CLK_DETECT_FAIL BIT(4) | ||
459 | |||
460 | /* Use this reg for masking during driver access */ | ||
461 | #define WL_SPARE_REG 0x2320 | ||
462 | #define WL_SPARE_VAL BIT(2) | ||
463 | /* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ | ||
464 | #define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) | ||
465 | |||
466 | #define PLL_LOCK_COUNTERS_REG 0xD8C | ||
467 | #define PLL_LOCK_COUNTERS_COEX 0x0F | ||
468 | #define PLL_LOCK_COUNTERS_MCS 0xF0 | ||
469 | #define MCS_PLL_OVERRIDE_REG 0xD90 | ||
470 | #define MCS_PLL_CONFIG_REG 0xD92 | ||
471 | #define MCS_SEL_IN_FREQ_MASK 0x0070 | ||
472 | #define MCS_SEL_IN_FREQ_SHIFT 4 | ||
473 | #define MCS_PLL_CONFIG_REG_VAL 0x73 | ||
474 | #define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) | ||
475 | |||
476 | #define MCS_PLL_M_REG 0xD94 | ||
477 | #define MCS_PLL_N_REG 0xD96 | ||
478 | #define MCS_PLL_M_REG_VAL 0xC8 | ||
479 | #define MCS_PLL_N_REG_VAL 0x07 | ||
480 | |||
481 | #define SDIO_IO_DS 0xd14 | ||
482 | |||
483 | /* SDIO/wSPI DS configuration values */ | ||
484 | enum { | ||
485 | HCI_IO_DS_8MA = 0, | ||
486 | HCI_IO_DS_4MA = 1, /* default */ | ||
487 | HCI_IO_DS_6MA = 2, | ||
488 | HCI_IO_DS_2MA = 3, | ||
489 | }; | ||
468 | 490 | ||
469 | /************************************************************************* | 491 | /* end PLL configuration algorithm for wl128x */ |
470 | |||
471 | Interrupt Trigger Register (Host -> WiLink) | ||
472 | |||
473 | **************************************************************************/ | ||
474 | |||
475 | /* Hardware to Embedded CPU Interrupts - first 32-bit register set */ | ||
476 | 492 | ||
477 | /* | 493 | /* |
478 | * Host Command Interrupt. Setting this bit masks | 494 | * Host Command Interrupt. Setting this bit masks |
@@ -480,7 +496,7 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
480 | * the FW that it has sent a command | 496 | * the FW that it has sent a command |
481 | * to the Wlan hardware Command Mailbox. | 497 | * to the Wlan hardware Command Mailbox. |
482 | */ | 498 | */ |
483 | #define INTR_TRIG_CMD BIT(0) | 499 | #define WL12XX_INTR_TRIG_CMD BIT(0) |
484 | 500 | ||
485 | /* | 501 | /* |
486 | * Host Event Acknowlegde Interrupt. The host | 502 | * Host Event Acknowlegde Interrupt. The host |
@@ -488,42 +504,27 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
488 | * the unsolicited information from the event | 504 | * the unsolicited information from the event |
489 | * mailbox. | 505 | * mailbox. |
490 | */ | 506 | */ |
491 | #define INTR_TRIG_EVENT_ACK BIT(1) | 507 | #define WL12XX_INTR_TRIG_EVENT_ACK BIT(1) |
492 | |||
493 | /* | ||
494 | * The host sets this bit to inform the Wlan | ||
495 | * FW that a TX packet is in the XFER | ||
496 | * Buffer #0. | ||
497 | */ | ||
498 | #define INTR_TRIG_TX_PROC0 BIT(2) | ||
499 | |||
500 | /* | ||
501 | * The host sets this bit to inform the FW | ||
502 | * that it read a packet from RX XFER | ||
503 | * Buffer #0. | ||
504 | */ | ||
505 | #define INTR_TRIG_RX_PROC0 BIT(3) | ||
506 | |||
507 | #define INTR_TRIG_DEBUG_ACK BIT(4) | ||
508 | 508 | ||
509 | #define INTR_TRIG_STATE_CHANGED BIT(5) | 509 | /*=============================================== |
510 | 510 | HI_CFG Interface Configuration Register Values | |
511 | 511 | ------------------------------------------ | |
512 | /* Hardware to Embedded CPU Interrupts - second 32-bit register set */ | 512 | ===============================================*/ |
513 | 513 | #define HI_CFG_UART_ENABLE 0x00000004 | |
514 | /* | 514 | #define HI_CFG_RST232_ENABLE 0x00000008 |
515 | * The host sets this bit to inform the FW | 515 | #define HI_CFG_CLOCK_REQ_SELECT 0x00000010 |
516 | * that it read a packet from RX XFER | 516 | #define HI_CFG_HOST_INT_ENABLE 0x00000020 |
517 | * Buffer #1. | 517 | #define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 |
518 | */ | 518 | #define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 |
519 | #define INTR_TRIG_RX_PROC1 BIT(17) | 519 | #define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 |
520 | #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 | ||
521 | #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 | ||
520 | 522 | ||
521 | /* | 523 | #define HI_CFG_DEF_VAL \ |
522 | * The host sets this bit to inform the Wlan | 524 | (HI_CFG_UART_ENABLE | \ |
523 | * hardware that a TX packet is in the XFER | 525 | HI_CFG_RST232_ENABLE | \ |
524 | * Buffer #1. | 526 | HI_CFG_CLOCK_REQ_SELECT | \ |
525 | */ | 527 | HI_CFG_HOST_INT_ENABLE) |
526 | #define INTR_TRIG_TX_PROC1 BIT(18) | ||
527 | 528 | ||
528 | #define WL127X_REG_FUSE_DATA_2_1 0x050a | 529 | #define WL127X_REG_FUSE_DATA_2_1 0x050a |
529 | #define WL128X_REG_FUSE_DATA_2_1 0x2152 | 530 | #define WL128X_REG_FUSE_DATA_2_1 0x2152 |
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h new file mode 100644 index 000000000000..74cd332e23ef --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
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 __WL12XX_PRIV_H__ | ||
23 | #define __WL12XX_PRIV_H__ | ||
24 | |||
25 | #include "conf.h" | ||
26 | |||
27 | struct wl12xx_priv { | ||
28 | struct wl12xx_priv_conf conf; | ||
29 | }; | ||
30 | |||
31 | #endif /* __WL12XX_PRIV_H__ */ | ||
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig new file mode 100644 index 000000000000..9d04c38938bc --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/Kconfig | |||
@@ -0,0 +1,41 @@ | |||
1 | config WLCORE | ||
2 | tristate "TI wlcore support" | ||
3 | depends on WL_TI && GENERIC_HARDIRQS | ||
4 | depends on INET | ||
5 | select FW_LOADER | ||
6 | ---help--- | ||
7 | This module contains the main code for TI WLAN chips. It abstracts | ||
8 | hardware-specific differences among different chipset families. | ||
9 | Each chipset family needs to implement its own lower-level module | ||
10 | that will depend on this module for the common code. | ||
11 | |||
12 | If you choose to build a module, it will be called wlcore. Say N if | ||
13 | unsure. | ||
14 | |||
15 | config WLCORE_SPI | ||
16 | tristate "TI wlcore SPI support" | ||
17 | depends on WLCORE && SPI_MASTER | ||
18 | select CRC7 | ||
19 | ---help--- | ||
20 | This module adds support for the SPI interface of adapters using | ||
21 | TI WLAN chipsets. Select this if your platform is using | ||
22 | the SPI bus. | ||
23 | |||
24 | If you choose to build a module, it'll be called wlcore_spi. | ||
25 | Say N if unsure. | ||
26 | |||
27 | config WLCORE_SDIO | ||
28 | tristate "TI wlcore SDIO support" | ||
29 | depends on WLCORE && MMC | ||
30 | ---help--- | ||
31 | This module adds support for the SDIO interface of adapters using | ||
32 | TI WLAN chipsets. Select this if your platform is using | ||
33 | the SDIO bus. | ||
34 | |||
35 | If you choose to build a module, it'll be called wlcore_sdio. | ||
36 | Say N if unsure. | ||
37 | |||
38 | config WL12XX_PLATFORM_DATA | ||
39 | bool | ||
40 | depends on WLCORE_SDIO != n || WL1251_SDIO != n | ||
41 | default y | ||
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile new file mode 100644 index 000000000000..d9fba9e32130 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ | ||
2 | boot.o init.o debugfs.o scan.o | ||
3 | |||
4 | wlcore_spi-objs = spi.o | ||
5 | wlcore_sdio-objs = sdio.o | ||
6 | |||
7 | wlcore-$(CONFIG_NL80211_TESTMODE) += testmode.o | ||
8 | obj-$(CONFIG_WLCORE) += wlcore.o | ||
9 | obj-$(CONFIG_WLCORE_SPI) += wlcore_spi.o | ||
10 | obj-$(CONFIG_WLCORE_SDIO) += wlcore_sdio.o | ||
11 | |||
12 | # small builtin driver bit | ||
13 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | ||
14 | |||
15 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index bc96db0683a5..5912541a925e 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -28,11 +28,11 @@ | |||
28 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | #include "wl12xx.h" | 31 | #include "wlcore.h" |
32 | #include "debug.h" | 32 | #include "debug.h" |
33 | #include "wl12xx_80211.h" | 33 | #include "wl12xx_80211.h" |
34 | #include "reg.h" | ||
35 | #include "ps.h" | 34 | #include "ps.h" |
35 | #include "hw_ops.h" | ||
36 | 36 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
38 | u8 wake_up_event, u8 listen_interval) | 38 | u8 wake_up_event, u8 listen_interval) |
@@ -757,7 +757,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
757 | 757 | ||
758 | /* configure one AP supported rate class */ | 758 | /* configure one AP supported rate class */ |
759 | acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx); | 759 | acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx); |
760 | acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set); | 760 | |
761 | /* the AP policy is HW specific */ | ||
762 | acx->rate_policy.enabled_rates = | ||
763 | cpu_to_le32(wlcore_hw_sta_get_ap_rate_mask(wl, wlvif)); | ||
761 | acx->rate_policy.short_retry_limit = c->short_retry_limit; | 764 | acx->rate_policy.short_retry_limit = c->short_retry_limit; |
762 | acx->rate_policy.long_retry_limit = c->long_retry_limit; | 765 | acx->rate_policy.long_retry_limit = c->long_retry_limit; |
763 | acx->rate_policy.aflags = c->aflags; | 766 | acx->rate_policy.aflags = c->aflags; |
@@ -969,17 +972,14 @@ int wl12xx_acx_mem_cfg(struct wl1271 *wl) | |||
969 | goto out; | 972 | goto out; |
970 | } | 973 | } |
971 | 974 | ||
972 | if (wl->chip.id == CHIP_ID_1283_PG20) | 975 | mem = &wl->conf.mem; |
973 | mem = &wl->conf.mem_wl128x; | ||
974 | else | ||
975 | mem = &wl->conf.mem_wl127x; | ||
976 | 976 | ||
977 | /* memory config */ | 977 | /* memory config */ |
978 | mem_conf->num_stations = mem->num_stations; | 978 | mem_conf->num_stations = mem->num_stations; |
979 | mem_conf->rx_mem_block_num = mem->rx_block_num; | 979 | mem_conf->rx_mem_block_num = mem->rx_block_num; |
980 | mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; | 980 | mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; |
981 | mem_conf->num_ssid_profiles = mem->ssid_profiles; | 981 | mem_conf->num_ssid_profiles = mem->ssid_profiles; |
982 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); | 982 | mem_conf->total_tx_descriptors = cpu_to_le32(wl->num_tx_desc); |
983 | mem_conf->dyn_mem_enable = mem->dynamic_memory; | 983 | mem_conf->dyn_mem_enable = mem->dynamic_memory; |
984 | mem_conf->tx_free_req = mem->min_req_tx_blocks; | 984 | mem_conf->tx_free_req = mem->min_req_tx_blocks; |
985 | mem_conf->rx_free_req = mem->min_req_rx_blocks; | 985 | mem_conf->rx_free_req = mem->min_req_rx_blocks; |
@@ -998,32 +998,6 @@ out: | |||
998 | return ret; | 998 | return ret; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) | ||
1002 | { | ||
1003 | struct wl1271_acx_host_config_bitmap *bitmap_conf; | ||
1004 | int ret; | ||
1005 | |||
1006 | bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); | ||
1007 | if (!bitmap_conf) { | ||
1008 | ret = -ENOMEM; | ||
1009 | goto out; | ||
1010 | } | ||
1011 | |||
1012 | bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); | ||
1013 | |||
1014 | ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, | ||
1015 | bitmap_conf, sizeof(*bitmap_conf)); | ||
1016 | if (ret < 0) { | ||
1017 | wl1271_warning("wl1271 bitmap config opt failed: %d", ret); | ||
1018 | goto out; | ||
1019 | } | ||
1020 | |||
1021 | out: | ||
1022 | kfree(bitmap_conf); | ||
1023 | |||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
1027 | int wl1271_acx_init_mem_config(struct wl1271 *wl) | 1001 | int wl1271_acx_init_mem_config(struct wl1271 *wl) |
1028 | { | 1002 | { |
1029 | int ret; | 1003 | int ret; |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index a28fc044034c..b2f88831b7a9 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #ifndef __ACX_H__ | 25 | #ifndef __ACX_H__ |
26 | #define __ACX_H__ | 26 | #define __ACX_H__ |
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wlcore.h" |
29 | #include "cmd.h" | 29 | #include "cmd.h" |
30 | 30 | ||
31 | /************************************************************************* | 31 | /************************************************************************* |
@@ -824,16 +824,11 @@ struct wl1271_acx_keep_alive_config { | |||
824 | __le32 period; | 824 | __le32 period; |
825 | } __packed; | 825 | } __packed; |
826 | 826 | ||
827 | /* TODO: maybe this needs to be moved somewhere else? */ | ||
827 | #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) | 828 | #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) |
828 | #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) | 829 | #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) |
829 | #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) | 830 | #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) |
830 | 831 | ||
831 | struct wl1271_acx_host_config_bitmap { | ||
832 | struct acx_header header; | ||
833 | |||
834 | __le32 host_cfg_bitmap; | ||
835 | } __packed; | ||
836 | |||
837 | enum { | 832 | enum { |
838 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, | 833 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, |
839 | WL1271_ACX_TRIG_TYPE_EDGE, | 834 | WL1271_ACX_TRIG_TYPE_EDGE, |
@@ -1274,7 +1269,6 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); | |||
1274 | int wl1271_acx_tx_config_options(struct wl1271 *wl); | 1269 | int wl1271_acx_tx_config_options(struct wl1271 *wl); |
1275 | int wl12xx_acx_mem_cfg(struct wl1271 *wl); | 1270 | int wl12xx_acx_mem_cfg(struct wl1271 *wl); |
1276 | int wl1271_acx_init_mem_config(struct wl1271 *wl); | 1271 | int wl1271_acx_init_mem_config(struct wl1271 *wl); |
1277 | int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); | ||
1278 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1272 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1279 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | 1273 | int wl1271_acx_smart_reflex(struct wl1271 *wl); |
1280 | int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 1274 | int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c new file mode 100644 index 000000000000..3a2207db5405 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -0,0 +1,443 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/slab.h> | ||
25 | #include <linux/wl12xx.h> | ||
26 | #include <linux/export.h> | ||
27 | |||
28 | #include "debug.h" | ||
29 | #include "acx.h" | ||
30 | #include "boot.h" | ||
31 | #include "io.h" | ||
32 | #include "event.h" | ||
33 | #include "rx.h" | ||
34 | #include "hw_ops.h" | ||
35 | |||
36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | ||
37 | { | ||
38 | u32 cpu_ctrl; | ||
39 | |||
40 | /* 10.5.0 run the firmware (I) */ | ||
41 | cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); | ||
42 | |||
43 | /* 10.5.1 run the firmware (II) */ | ||
44 | cpu_ctrl |= flag; | ||
45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); | ||
46 | } | ||
47 | |||
48 | static int wlcore_parse_fw_ver(struct wl1271 *wl) | ||
49 | { | ||
50 | int ret; | ||
51 | |||
52 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", | ||
53 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], | ||
54 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], | ||
55 | &wl->chip.fw_ver[4]); | ||
56 | |||
57 | if (ret != 5) { | ||
58 | wl1271_warning("fw version incorrect value"); | ||
59 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | ret = wlcore_identify_fw(wl); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int wlcore_boot_fw_version(struct wl1271 *wl) | ||
71 | { | ||
72 | struct wl1271_static_data *static_data; | ||
73 | int ret; | ||
74 | |||
75 | static_data = kmalloc(sizeof(*static_data), GFP_DMA); | ||
76 | if (!static_data) { | ||
77 | wl1271_error("Couldn't allocate memory for static data!"); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
81 | wl1271_read(wl, wl->cmd_box_addr, static_data, sizeof(*static_data), | ||
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 | |||
89 | /* make sure the string is NULL-terminated */ | ||
90 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; | ||
91 | |||
92 | ret = wlcore_parse_fw_ver(wl); | ||
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | ||
100 | size_t fw_data_len, u32 dest) | ||
101 | { | ||
102 | struct wlcore_partition_set partition; | ||
103 | int addr, chunk_num, partition_limit; | ||
104 | u8 *p, *chunk; | ||
105 | |||
106 | /* whal_FwCtrl_LoadFwImageSm() */ | ||
107 | |||
108 | wl1271_debug(DEBUG_BOOT, "starting firmware upload"); | ||
109 | |||
110 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", | ||
111 | fw_data_len, CHUNK_SIZE); | ||
112 | |||
113 | if ((fw_data_len % 4) != 0) { | ||
114 | wl1271_error("firmware length not multiple of four"); | ||
115 | return -EIO; | ||
116 | } | ||
117 | |||
118 | chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
119 | if (!chunk) { | ||
120 | wl1271_error("allocation for firmware upload chunk failed"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); | ||
125 | partition.mem.start = dest; | ||
126 | wlcore_set_partition(wl, &partition); | ||
127 | |||
128 | /* 10.1 set partition limit and chunk num */ | ||
129 | chunk_num = 0; | ||
130 | partition_limit = wl->ptable[PART_DOWN].mem.size; | ||
131 | |||
132 | while (chunk_num < fw_data_len / CHUNK_SIZE) { | ||
133 | /* 10.2 update partition, if needed */ | ||
134 | addr = dest + (chunk_num + 2) * CHUNK_SIZE; | ||
135 | if (addr > partition_limit) { | ||
136 | addr = dest + chunk_num * CHUNK_SIZE; | ||
137 | partition_limit = chunk_num * CHUNK_SIZE + | ||
138 | wl->ptable[PART_DOWN].mem.size; | ||
139 | partition.mem.start = addr; | ||
140 | wlcore_set_partition(wl, &partition); | ||
141 | } | ||
142 | |||
143 | /* 10.3 upload the chunk */ | ||
144 | addr = dest + chunk_num * CHUNK_SIZE; | ||
145 | p = buf + chunk_num * CHUNK_SIZE; | ||
146 | memcpy(chunk, p, CHUNK_SIZE); | ||
147 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | ||
148 | p, addr); | ||
149 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); | ||
150 | |||
151 | chunk_num++; | ||
152 | } | ||
153 | |||
154 | /* 10.4 upload the last chunk */ | ||
155 | addr = dest + chunk_num * CHUNK_SIZE; | ||
156 | p = buf + chunk_num * CHUNK_SIZE; | ||
157 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | ||
158 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | ||
159 | fw_data_len % CHUNK_SIZE, p, addr); | ||
160 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | ||
161 | |||
162 | kfree(chunk); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | int wlcore_boot_upload_firmware(struct wl1271 *wl) | ||
167 | { | ||
168 | u32 chunks, addr, len; | ||
169 | int ret = 0; | ||
170 | u8 *fw; | ||
171 | |||
172 | fw = wl->fw; | ||
173 | chunks = be32_to_cpup((__be32 *) fw); | ||
174 | fw += sizeof(u32); | ||
175 | |||
176 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); | ||
177 | |||
178 | while (chunks--) { | ||
179 | addr = be32_to_cpup((__be32 *) fw); | ||
180 | fw += sizeof(u32); | ||
181 | len = be32_to_cpup((__be32 *) fw); | ||
182 | fw += sizeof(u32); | ||
183 | |||
184 | if (len > 300000) { | ||
185 | wl1271_info("firmware chunk too long: %u", len); | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", | ||
189 | chunks, addr, len); | ||
190 | ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); | ||
191 | if (ret != 0) | ||
192 | break; | ||
193 | fw += len; | ||
194 | } | ||
195 | |||
196 | return ret; | ||
197 | } | ||
198 | EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware); | ||
199 | |||
200 | int wlcore_boot_upload_nvs(struct wl1271 *wl) | ||
201 | { | ||
202 | size_t nvs_len, burst_len; | ||
203 | int i; | ||
204 | u32 dest_addr, val; | ||
205 | u8 *nvs_ptr, *nvs_aligned; | ||
206 | |||
207 | if (wl->nvs == NULL) | ||
208 | return -ENODEV; | ||
209 | |||
210 | if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) { | ||
211 | struct wl1271_nvs_file *nvs = | ||
212 | (struct wl1271_nvs_file *)wl->nvs; | ||
213 | /* | ||
214 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz | ||
215 | * band configurations) can be removed when those NVS files stop | ||
216 | * floating around. | ||
217 | */ | ||
218 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || | ||
219 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { | ||
220 | if (nvs->general_params.dual_mode_select) | ||
221 | wl->enable_11a = true; | ||
222 | } | ||
223 | |||
224 | if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && | ||
225 | (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
226 | wl->enable_11a)) { | ||
227 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
228 | wl->nvs_len, sizeof(struct wl1271_nvs_file)); | ||
229 | kfree(wl->nvs); | ||
230 | wl->nvs = NULL; | ||
231 | wl->nvs_len = 0; | ||
232 | return -EILSEQ; | ||
233 | } | ||
234 | |||
235 | /* only the first part of the NVS needs to be uploaded */ | ||
236 | nvs_len = sizeof(nvs->nvs); | ||
237 | nvs_ptr = (u8 *) nvs->nvs; | ||
238 | } else { | ||
239 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | ||
240 | |||
241 | if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { | ||
242 | if (nvs->general_params.dual_mode_select) | ||
243 | wl->enable_11a = true; | ||
244 | } else { | ||
245 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
246 | wl->nvs_len, | ||
247 | sizeof(struct wl128x_nvs_file)); | ||
248 | kfree(wl->nvs); | ||
249 | wl->nvs = NULL; | ||
250 | wl->nvs_len = 0; | ||
251 | return -EILSEQ; | ||
252 | } | ||
253 | |||
254 | /* only the first part of the NVS needs to be uploaded */ | ||
255 | nvs_len = sizeof(nvs->nvs); | ||
256 | nvs_ptr = (u8 *)nvs->nvs; | ||
257 | } | ||
258 | |||
259 | /* update current MAC address to NVS */ | ||
260 | nvs_ptr[11] = wl->addresses[0].addr[0]; | ||
261 | nvs_ptr[10] = wl->addresses[0].addr[1]; | ||
262 | nvs_ptr[6] = wl->addresses[0].addr[2]; | ||
263 | nvs_ptr[5] = wl->addresses[0].addr[3]; | ||
264 | nvs_ptr[4] = wl->addresses[0].addr[4]; | ||
265 | nvs_ptr[3] = wl->addresses[0].addr[5]; | ||
266 | |||
267 | /* | ||
268 | * Layout before the actual NVS tables: | ||
269 | * 1 byte : burst length. | ||
270 | * 2 bytes: destination address. | ||
271 | * n bytes: data to burst copy. | ||
272 | * | ||
273 | * This is ended by a 0 length, then the NVS tables. | ||
274 | */ | ||
275 | |||
276 | /* FIXME: Do we need to check here whether the LSB is 1? */ | ||
277 | while (nvs_ptr[0]) { | ||
278 | burst_len = nvs_ptr[0]; | ||
279 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); | ||
280 | |||
281 | /* | ||
282 | * Due to our new wl1271_translate_reg_addr function, | ||
283 | * we need to add the register partition start address | ||
284 | * to the destination | ||
285 | */ | ||
286 | dest_addr += wl->curr_part.reg.start; | ||
287 | |||
288 | /* We move our pointer to the data */ | ||
289 | nvs_ptr += 3; | ||
290 | |||
291 | for (i = 0; i < burst_len; i++) { | ||
292 | if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) | ||
293 | goto out_badnvs; | ||
294 | |||
295 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | ||
296 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | ||
297 | |||
298 | wl1271_debug(DEBUG_BOOT, | ||
299 | "nvs burst write 0x%x: 0x%x", | ||
300 | dest_addr, val); | ||
301 | wl1271_write32(wl, dest_addr, val); | ||
302 | |||
303 | nvs_ptr += 4; | ||
304 | dest_addr += 4; | ||
305 | } | ||
306 | |||
307 | if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) | ||
308 | goto out_badnvs; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * We've reached the first zero length, the first NVS table | ||
313 | * is located at an aligned offset which is at least 7 bytes further. | ||
314 | * NOTE: The wl->nvs->nvs element must be first, in order to | ||
315 | * simplify the casting, we assume it is at the beginning of | ||
316 | * the wl->nvs structure. | ||
317 | */ | ||
318 | nvs_ptr = (u8 *)wl->nvs + | ||
319 | ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); | ||
320 | |||
321 | if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) | ||
322 | goto out_badnvs; | ||
323 | |||
324 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | ||
325 | |||
326 | /* Now we must set the partition correctly */ | ||
327 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
328 | |||
329 | /* Copy the NVS tables to a new block to ensure alignment */ | ||
330 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | ||
331 | if (!nvs_aligned) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | /* And finally we upload the NVS tables */ | ||
335 | wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, | ||
336 | nvs_aligned, nvs_len, false); | ||
337 | |||
338 | kfree(nvs_aligned); | ||
339 | return 0; | ||
340 | |||
341 | out_badnvs: | ||
342 | wl1271_error("nvs data is malformed"); | ||
343 | return -EILSEQ; | ||
344 | } | ||
345 | EXPORT_SYMBOL_GPL(wlcore_boot_upload_nvs); | ||
346 | |||
347 | int wlcore_boot_run_firmware(struct wl1271 *wl) | ||
348 | { | ||
349 | int loop, ret; | ||
350 | u32 chip_id, intr; | ||
351 | |||
352 | /* Make sure we have the boot partition */ | ||
353 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
354 | |||
355 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | ||
356 | |||
357 | chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); | ||
358 | |||
359 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | ||
360 | |||
361 | if (chip_id != wl->chip.id) { | ||
362 | wl1271_error("chip id doesn't match after firmware boot"); | ||
363 | return -EIO; | ||
364 | } | ||
365 | |||
366 | /* wait for init to complete */ | ||
367 | loop = 0; | ||
368 | while (loop++ < INIT_LOOP) { | ||
369 | udelay(INIT_LOOP_DELAY); | ||
370 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | ||
371 | |||
372 | if (intr == 0xffffffff) { | ||
373 | wl1271_error("error reading hardware complete " | ||
374 | "init indication"); | ||
375 | return -EIO; | ||
376 | } | ||
377 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | ||
378 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { | ||
379 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, | ||
380 | WL1271_ACX_INTR_INIT_COMPLETE); | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | if (loop > INIT_LOOP) { | ||
386 | wl1271_error("timeout waiting for the hardware to " | ||
387 | "complete initialization"); | ||
388 | return -EIO; | ||
389 | } | ||
390 | |||
391 | /* get hardware config command mail box */ | ||
392 | wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); | ||
393 | |||
394 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); | ||
395 | |||
396 | /* get hardware config event mail box */ | ||
397 | wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); | ||
398 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | ||
399 | |||
400 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | ||
401 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | ||
402 | |||
403 | ret = wlcore_boot_fw_version(wl); | ||
404 | if (ret < 0) { | ||
405 | wl1271_error("couldn't boot firmware"); | ||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * in case of full asynchronous mode the firmware event must be | ||
411 | * ready to receive event from the command mailbox | ||
412 | */ | ||
413 | |||
414 | /* unmask required mbox events */ | ||
415 | wl->event_mask = BSS_LOSE_EVENT_ID | | ||
416 | SCAN_COMPLETE_EVENT_ID | | ||
417 | ROLE_STOP_COMPLETE_EVENT_ID | | ||
418 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
419 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | ||
420 | SOFT_GEMINI_SENSE_EVENT_ID | | ||
421 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
422 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
423 | DUMMY_PACKET_EVENT_ID | | ||
424 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
425 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
426 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
427 | INACTIVE_STA_EVENT_ID | | ||
428 | MAX_TX_RETRY_EVENT_ID | | ||
429 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | ||
430 | |||
431 | ret = wl1271_event_unmask(wl); | ||
432 | if (ret < 0) { | ||
433 | wl1271_error("EVENT mask setting failed"); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | /* set the working partition to its "running" mode offset */ | ||
438 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
439 | |||
440 | /* firmware startup completed */ | ||
441 | return 0; | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); | ||
diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h new file mode 100644 index 000000000000..094981dd2227 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/boot.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __BOOT_H__ | ||
25 | #define __BOOT_H__ | ||
26 | |||
27 | #include "wlcore.h" | ||
28 | |||
29 | int wlcore_boot_upload_firmware(struct wl1271 *wl); | ||
30 | int wlcore_boot_upload_nvs(struct wl1271 *wl); | ||
31 | int wlcore_boot_run_firmware(struct wl1271 *wl); | ||
32 | |||
33 | #define WL1271_NO_SUBBANDS 8 | ||
34 | #define WL1271_NO_POWER_LEVELS 4 | ||
35 | #define WL1271_FW_VERSION_MAX_LEN 20 | ||
36 | |||
37 | struct wl1271_static_data { | ||
38 | u8 mac_address[ETH_ALEN]; | ||
39 | u8 padding[2]; | ||
40 | u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; | ||
41 | u32 hw_version; | ||
42 | u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; | ||
43 | }; | ||
44 | |||
45 | /* number of times we try to read the INIT interrupt */ | ||
46 | #define INIT_LOOP 20000 | ||
47 | |||
48 | /* delay between retries */ | ||
49 | #define INIT_LOOP_DELAY 50 | ||
50 | |||
51 | #define WU_COUNTER_PAUSE_VAL 0x3FF | ||
52 | #define WELP_ARM_COMMAND_VAL 0x4 | ||
53 | |||
54 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 3414fc11e9ba..5c4716c6f040 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -28,9 +28,8 @@ | |||
28 | #include <linux/ieee80211.h> | 28 | #include <linux/ieee80211.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | #include "wl12xx.h" | 31 | #include "wlcore.h" |
32 | #include "debug.h" | 32 | #include "debug.h" |
33 | #include "reg.h" | ||
34 | #include "io.h" | 33 | #include "io.h" |
35 | #include "acx.h" | 34 | #include "acx.h" |
36 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
@@ -67,11 +66,15 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
67 | 66 | ||
68 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); | 67 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); |
69 | 68 | ||
70 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | 69 | /* |
70 | * TODO: we just need this because one bit is in a different | ||
71 | * place. Is there any better way? | ||
72 | */ | ||
73 | wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); | ||
71 | 74 | ||
72 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 75 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
73 | 76 | ||
74 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 77 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); |
75 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 78 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
76 | if (time_after(jiffies, timeout)) { | 79 | if (time_after(jiffies, timeout)) { |
77 | wl1271_error("command complete timeout"); | 80 | wl1271_error("command complete timeout"); |
@@ -85,7 +88,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
85 | else | 88 | else |
86 | msleep(1); | 89 | msleep(1); |
87 | 90 | ||
88 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 91 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); |
89 | } | 92 | } |
90 | 93 | ||
91 | /* read back the status code of the command */ | 94 | /* read back the status code of the command */ |
@@ -100,8 +103,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
100 | goto fail; | 103 | goto fail; |
101 | } | 104 | } |
102 | 105 | ||
103 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, | 106 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); |
104 | WL1271_ACX_INTR_CMD_COMPLETE); | ||
105 | return 0; | 107 | return 0; |
106 | 108 | ||
107 | fail: | 109 | fail: |
@@ -110,240 +112,18 @@ fail: | |||
110 | return ret; | 112 | return ret; |
111 | } | 113 | } |
112 | 114 | ||
113 | int wl1271_cmd_general_parms(struct wl1271 *wl) | ||
114 | { | ||
115 | struct wl1271_general_parms_cmd *gen_parms; | ||
116 | struct wl1271_ini_general_params *gp = | ||
117 | &((struct wl1271_nvs_file *)wl->nvs)->general_params; | ||
118 | bool answer = false; | ||
119 | int ret; | ||
120 | |||
121 | if (!wl->nvs) | ||
122 | return -ENODEV; | ||
123 | |||
124 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
125 | wl1271_warning("FEM index from INI out of bounds"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | ||
130 | if (!gen_parms) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | ||
134 | |||
135 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); | ||
136 | |||
137 | if (gp->tx_bip_fem_auto_detect) | ||
138 | answer = true; | ||
139 | |||
140 | /* Override the REF CLK from the NVS with the one from platform data */ | ||
141 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
142 | |||
143 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
144 | if (ret < 0) { | ||
145 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | gp->tx_bip_fem_manufacturer = | ||
150 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
151 | |||
152 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
153 | wl1271_warning("FEM index from FW out of bounds"); | ||
154 | ret = -EINVAL; | ||
155 | goto out; | ||
156 | } | ||
157 | |||
158 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
159 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
160 | |||
161 | out: | ||
162 | kfree(gen_parms); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | int wl128x_cmd_general_parms(struct wl1271 *wl) | ||
167 | { | ||
168 | struct wl128x_general_parms_cmd *gen_parms; | ||
169 | struct wl128x_ini_general_params *gp = | ||
170 | &((struct wl128x_nvs_file *)wl->nvs)->general_params; | ||
171 | bool answer = false; | ||
172 | int ret; | ||
173 | |||
174 | if (!wl->nvs) | ||
175 | return -ENODEV; | ||
176 | |||
177 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
178 | wl1271_warning("FEM index from ini out of bounds"); | ||
179 | return -EINVAL; | ||
180 | } | ||
181 | |||
182 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | ||
183 | if (!gen_parms) | ||
184 | return -ENOMEM; | ||
185 | |||
186 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | ||
187 | |||
188 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); | ||
189 | |||
190 | if (gp->tx_bip_fem_auto_detect) | ||
191 | answer = true; | ||
192 | |||
193 | /* Replace REF and TCXO CLKs with the ones from platform data */ | ||
194 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
195 | gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; | ||
196 | |||
197 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
198 | if (ret < 0) { | ||
199 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | gp->tx_bip_fem_manufacturer = | ||
204 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
205 | |||
206 | if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { | ||
207 | wl1271_warning("FEM index from FW out of bounds"); | ||
208 | ret = -EINVAL; | ||
209 | goto out; | ||
210 | } | ||
211 | |||
212 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
213 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
214 | |||
215 | out: | ||
216 | kfree(gen_parms); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | int wl1271_cmd_radio_parms(struct wl1271 *wl) | ||
221 | { | ||
222 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; | ||
223 | struct wl1271_radio_parms_cmd *radio_parms; | ||
224 | struct wl1271_ini_general_params *gp = &nvs->general_params; | ||
225 | int ret; | ||
226 | |||
227 | if (!wl->nvs) | ||
228 | return -ENODEV; | ||
229 | |||
230 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | ||
231 | if (!radio_parms) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | ||
235 | |||
236 | /* 2.4GHz parameters */ | ||
237 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | ||
238 | sizeof(struct wl1271_ini_band_params_2)); | ||
239 | memcpy(&radio_parms->dyn_params_2, | ||
240 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | ||
241 | sizeof(struct wl1271_ini_fem_params_2)); | ||
242 | |||
243 | /* 5GHz parameters */ | ||
244 | memcpy(&radio_parms->static_params_5, | ||
245 | &nvs->stat_radio_params_5, | ||
246 | sizeof(struct wl1271_ini_band_params_5)); | ||
247 | memcpy(&radio_parms->dyn_params_5, | ||
248 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | ||
249 | sizeof(struct wl1271_ini_fem_params_5)); | ||
250 | |||
251 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | ||
252 | radio_parms, sizeof(*radio_parms)); | ||
253 | |||
254 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); | ||
255 | if (ret < 0) | ||
256 | wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); | ||
257 | |||
258 | kfree(radio_parms); | ||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | int wl128x_cmd_radio_parms(struct wl1271 *wl) | ||
263 | { | ||
264 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | ||
265 | struct wl128x_radio_parms_cmd *radio_parms; | ||
266 | struct wl128x_ini_general_params *gp = &nvs->general_params; | ||
267 | int ret; | ||
268 | |||
269 | if (!wl->nvs) | ||
270 | return -ENODEV; | ||
271 | |||
272 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | ||
273 | if (!radio_parms) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | ||
277 | |||
278 | /* 2.4GHz parameters */ | ||
279 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | ||
280 | sizeof(struct wl128x_ini_band_params_2)); | ||
281 | memcpy(&radio_parms->dyn_params_2, | ||
282 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | ||
283 | sizeof(struct wl128x_ini_fem_params_2)); | ||
284 | |||
285 | /* 5GHz parameters */ | ||
286 | memcpy(&radio_parms->static_params_5, | ||
287 | &nvs->stat_radio_params_5, | ||
288 | sizeof(struct wl128x_ini_band_params_5)); | ||
289 | memcpy(&radio_parms->dyn_params_5, | ||
290 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | ||
291 | sizeof(struct wl128x_ini_fem_params_5)); | ||
292 | |||
293 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; | ||
294 | |||
295 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | ||
296 | radio_parms, sizeof(*radio_parms)); | ||
297 | |||
298 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); | ||
299 | if (ret < 0) | ||
300 | wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); | ||
301 | |||
302 | kfree(radio_parms); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) | ||
307 | { | ||
308 | struct wl1271_ext_radio_parms_cmd *ext_radio_parms; | ||
309 | struct conf_rf_settings *rf = &wl->conf.rf; | ||
310 | int ret; | ||
311 | |||
312 | if (!wl->nvs) | ||
313 | return -ENODEV; | ||
314 | |||
315 | ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); | ||
316 | if (!ext_radio_parms) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; | ||
320 | |||
321 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, | ||
322 | rf->tx_per_channel_power_compensation_2, | ||
323 | CONF_TX_PWR_COMPENSATION_LEN_2); | ||
324 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, | ||
325 | rf->tx_per_channel_power_compensation_5, | ||
326 | CONF_TX_PWR_COMPENSATION_LEN_5); | ||
327 | |||
328 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", | ||
329 | ext_radio_parms, sizeof(*ext_radio_parms)); | ||
330 | |||
331 | ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); | ||
332 | if (ret < 0) | ||
333 | wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); | ||
334 | |||
335 | kfree(ext_radio_parms); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | /* | 115 | /* |
340 | * Poll the mailbox event field until any of the bits in the mask is set or a | 116 | * Poll the mailbox event field until any of the bits in the mask is set or a |
341 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 117 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
342 | */ | 118 | */ |
343 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | 119 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) |
344 | { | 120 | { |
345 | u32 events_vector, event; | 121 | u32 *events_vector; |
122 | u32 event; | ||
346 | unsigned long timeout; | 123 | unsigned long timeout; |
124 | int ret = 0; | ||
125 | |||
126 | events_vector = kmalloc(sizeof(*events_vector), GFP_DMA); | ||
347 | 127 | ||
348 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 128 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
349 | 129 | ||
@@ -351,21 +131,24 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | |||
351 | if (time_after(jiffies, timeout)) { | 131 | if (time_after(jiffies, timeout)) { |
352 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", | 132 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", |
353 | (int)mask); | 133 | (int)mask); |
354 | return -ETIMEDOUT; | 134 | ret = -ETIMEDOUT; |
135 | goto out; | ||
355 | } | 136 | } |
356 | 137 | ||
357 | msleep(1); | 138 | msleep(1); |
358 | 139 | ||
359 | /* read from both event fields */ | 140 | /* read from both event fields */ |
360 | wl1271_read(wl, wl->mbox_ptr[0], &events_vector, | 141 | wl1271_read(wl, wl->mbox_ptr[0], events_vector, |
361 | sizeof(events_vector), false); | 142 | sizeof(*events_vector), false); |
362 | event = events_vector & mask; | 143 | event = *events_vector & mask; |
363 | wl1271_read(wl, wl->mbox_ptr[1], &events_vector, | 144 | wl1271_read(wl, wl->mbox_ptr[1], events_vector, |
364 | sizeof(events_vector), false); | 145 | sizeof(*events_vector), false); |
365 | event |= events_vector & mask; | 146 | event |= *events_vector & mask; |
366 | } while (!event); | 147 | } while (!event); |
367 | 148 | ||
368 | return 0; | 149 | out: |
150 | kfree(events_vector); | ||
151 | return ret; | ||
369 | } | 152 | } |
370 | 153 | ||
371 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | 154 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) |
@@ -522,7 +305,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, | |||
522 | 305 | ||
523 | cmd->role_id = wlvif->dev_role_id; | 306 | cmd->role_id = wlvif->dev_role_id; |
524 | if (wlvif->band == IEEE80211_BAND_5GHZ) | 307 | if (wlvif->band == IEEE80211_BAND_5GHZ) |
525 | cmd->band = WL12XX_BAND_5GHZ; | 308 | cmd->band = WLCORE_BAND_5GHZ; |
526 | cmd->channel = wlvif->channel; | 309 | cmd->channel = wlvif->channel; |
527 | 310 | ||
528 | if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { | 311 | if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { |
@@ -613,7 +396,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
613 | 396 | ||
614 | cmd->role_id = wlvif->role_id; | 397 | cmd->role_id = wlvif->role_id; |
615 | if (wlvif->band == IEEE80211_BAND_5GHZ) | 398 | if (wlvif->band == IEEE80211_BAND_5GHZ) |
616 | cmd->band = WL12XX_BAND_5GHZ; | 399 | cmd->band = WLCORE_BAND_5GHZ; |
617 | cmd->channel = wlvif->channel; | 400 | cmd->channel = wlvif->channel; |
618 | cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); | 401 | cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); |
619 | cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); | 402 | cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); |
@@ -750,14 +533,14 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
750 | 533 | ||
751 | switch (wlvif->band) { | 534 | switch (wlvif->band) { |
752 | case IEEE80211_BAND_2GHZ: | 535 | case IEEE80211_BAND_2GHZ: |
753 | cmd->band = RADIO_BAND_2_4GHZ; | 536 | cmd->band = WLCORE_BAND_2_4GHZ; |
754 | break; | 537 | break; |
755 | case IEEE80211_BAND_5GHZ: | 538 | case IEEE80211_BAND_5GHZ: |
756 | cmd->band = RADIO_BAND_5GHZ; | 539 | cmd->band = WLCORE_BAND_5GHZ; |
757 | break; | 540 | break; |
758 | default: | 541 | default: |
759 | wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); | 542 | wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); |
760 | cmd->band = RADIO_BAND_2_4GHZ; | 543 | cmd->band = WLCORE_BAND_2_4GHZ; |
761 | break; | 544 | break; |
762 | } | 545 | } |
763 | 546 | ||
@@ -830,7 +613,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
830 | 613 | ||
831 | cmd->role_id = wlvif->role_id; | 614 | cmd->role_id = wlvif->role_id; |
832 | if (wlvif->band == IEEE80211_BAND_5GHZ) | 615 | if (wlvif->band == IEEE80211_BAND_5GHZ) |
833 | cmd->band = WL12XX_BAND_5GHZ; | 616 | cmd->band = WLCORE_BAND_5GHZ; |
834 | cmd->channel = wlvif->channel; | 617 | cmd->channel = wlvif->channel; |
835 | cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); | 618 | cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); |
836 | cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); | 619 | cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); |
@@ -904,6 +687,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) | |||
904 | 687 | ||
905 | return ret; | 688 | return ret; |
906 | } | 689 | } |
690 | EXPORT_SYMBOL_GPL(wl1271_cmd_test); | ||
907 | 691 | ||
908 | /** | 692 | /** |
909 | * read acx from firmware | 693 | * read acx from firmware |
@@ -960,6 +744,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
960 | 744 | ||
961 | return 0; | 745 | return 0; |
962 | } | 746 | } |
747 | EXPORT_SYMBOL_GPL(wl1271_cmd_configure); | ||
963 | 748 | ||
964 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) | 749 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) |
965 | { | 750 | { |
@@ -1730,10 +1515,10 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1730 | cmd->channel = wlvif->channel; | 1515 | cmd->channel = wlvif->channel; |
1731 | switch (wlvif->band) { | 1516 | switch (wlvif->band) { |
1732 | case IEEE80211_BAND_2GHZ: | 1517 | case IEEE80211_BAND_2GHZ: |
1733 | cmd->band = RADIO_BAND_2_4GHZ; | 1518 | cmd->band = WLCORE_BAND_2_4GHZ; |
1734 | break; | 1519 | break; |
1735 | case IEEE80211_BAND_5GHZ: | 1520 | case IEEE80211_BAND_5GHZ: |
1736 | cmd->band = RADIO_BAND_5GHZ; | 1521 | cmd->band = WLCORE_BAND_5GHZ; |
1737 | break; | 1522 | break; |
1738 | default: | 1523 | default: |
1739 | wl1271_error("roc - unknown band: %d", (int)wlvif->band); | 1524 | wl1271_error("roc - unknown band: %d", (int)wlvif->band); |
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index de217d92516b..a46ae07cb77e 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -25,17 +25,12 @@ | |||
25 | #ifndef __CMD_H__ | 25 | #ifndef __CMD_H__ |
26 | #define __CMD_H__ | 26 | #define __CMD_H__ |
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wlcore.h" |
29 | 29 | ||
30 | struct acx_header; | 30 | struct acx_header; |
31 | 31 | ||
32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | 32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, |
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wl1271_cmd_general_parms(struct wl1271 *wl); | ||
35 | int wl128x_cmd_general_parms(struct wl1271 *wl); | ||
36 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | ||
37 | int wl128x_cmd_radio_parms(struct wl1271 *wl); | ||
38 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); | ||
39 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, | 34 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, |
40 | u8 *role_id); | 35 | u8 *role_id); |
41 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); | 36 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); |
@@ -262,13 +257,13 @@ struct wl12xx_cmd_role_disable { | |||
262 | u8 padding[3]; | 257 | u8 padding[3]; |
263 | } __packed; | 258 | } __packed; |
264 | 259 | ||
265 | enum wl12xx_band { | 260 | enum wlcore_band { |
266 | WL12XX_BAND_2_4GHZ = 0, | 261 | WLCORE_BAND_2_4GHZ = 0, |
267 | WL12XX_BAND_5GHZ = 1, | 262 | WLCORE_BAND_5GHZ = 1, |
268 | WL12XX_BAND_JAPAN_4_9_GHZ = 2, | 263 | WLCORE_BAND_JAPAN_4_9_GHZ = 2, |
269 | WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ, | 264 | WLCORE_BAND_DEFAULT = WLCORE_BAND_2_4GHZ, |
270 | WL12XX_BAND_INVALID = 0x7E, | 265 | WLCORE_BAND_INVALID = 0x7E, |
271 | WL12XX_BAND_MAX_RADIO = 0x7F, | 266 | WLCORE_BAND_MAX_RADIO = 0x7F, |
272 | }; | 267 | }; |
273 | 268 | ||
274 | struct wl12xx_cmd_role_start { | 269 | struct wl12xx_cmd_role_start { |
@@ -494,83 +489,6 @@ enum wl1271_channel_tune_bands { | |||
494 | 489 | ||
495 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 | 490 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 |
496 | 491 | ||
497 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 | ||
498 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E | ||
499 | #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 | ||
500 | |||
501 | struct wl1271_general_parms_cmd { | ||
502 | struct wl1271_cmd_header header; | ||
503 | |||
504 | struct wl1271_cmd_test_header test; | ||
505 | |||
506 | struct wl1271_ini_general_params general_params; | ||
507 | |||
508 | u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
509 | u8 sr_sen_n_p; | ||
510 | u8 sr_sen_n_p_gain; | ||
511 | u8 sr_sen_nrn; | ||
512 | u8 sr_sen_prn; | ||
513 | u8 padding[3]; | ||
514 | } __packed; | ||
515 | |||
516 | struct wl128x_general_parms_cmd { | ||
517 | struct wl1271_cmd_header header; | ||
518 | |||
519 | struct wl1271_cmd_test_header test; | ||
520 | |||
521 | struct wl128x_ini_general_params general_params; | ||
522 | |||
523 | u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
524 | u8 sr_sen_n_p; | ||
525 | u8 sr_sen_n_p_gain; | ||
526 | u8 sr_sen_nrn; | ||
527 | u8 sr_sen_prn; | ||
528 | u8 padding[3]; | ||
529 | } __packed; | ||
530 | |||
531 | struct wl1271_radio_parms_cmd { | ||
532 | struct wl1271_cmd_header header; | ||
533 | |||
534 | struct wl1271_cmd_test_header test; | ||
535 | |||
536 | /* Static radio parameters */ | ||
537 | struct wl1271_ini_band_params_2 static_params_2; | ||
538 | struct wl1271_ini_band_params_5 static_params_5; | ||
539 | |||
540 | /* Dynamic radio parameters */ | ||
541 | struct wl1271_ini_fem_params_2 dyn_params_2; | ||
542 | u8 padding2; | ||
543 | struct wl1271_ini_fem_params_5 dyn_params_5; | ||
544 | u8 padding3[2]; | ||
545 | } __packed; | ||
546 | |||
547 | struct wl128x_radio_parms_cmd { | ||
548 | struct wl1271_cmd_header header; | ||
549 | |||
550 | struct wl1271_cmd_test_header test; | ||
551 | |||
552 | /* Static radio parameters */ | ||
553 | struct wl128x_ini_band_params_2 static_params_2; | ||
554 | struct wl128x_ini_band_params_5 static_params_5; | ||
555 | |||
556 | u8 fem_vendor_and_options; | ||
557 | |||
558 | /* Dynamic radio parameters */ | ||
559 | struct wl128x_ini_fem_params_2 dyn_params_2; | ||
560 | u8 padding2; | ||
561 | struct wl128x_ini_fem_params_5 dyn_params_5; | ||
562 | } __packed; | ||
563 | |||
564 | struct wl1271_ext_radio_parms_cmd { | ||
565 | struct wl1271_cmd_header header; | ||
566 | |||
567 | struct wl1271_cmd_test_header test; | ||
568 | |||
569 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
570 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
571 | u8 padding[3]; | ||
572 | } __packed; | ||
573 | |||
574 | /* | 492 | /* |
575 | * There are three types of disconnections: | 493 | * There are three types of disconnections: |
576 | * | 494 | * |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 3e581e19424c..fef0db4213bc 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -65,36 +65,7 @@ enum { | |||
65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, | 65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | enum { | 68 | #define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff |
69 | CONF_HW_RXTX_RATE_MCS7_SGI = 0, | ||
70 | CONF_HW_RXTX_RATE_MCS7, | ||
71 | CONF_HW_RXTX_RATE_MCS6, | ||
72 | CONF_HW_RXTX_RATE_MCS5, | ||
73 | CONF_HW_RXTX_RATE_MCS4, | ||
74 | CONF_HW_RXTX_RATE_MCS3, | ||
75 | CONF_HW_RXTX_RATE_MCS2, | ||
76 | CONF_HW_RXTX_RATE_MCS1, | ||
77 | CONF_HW_RXTX_RATE_MCS0, | ||
78 | CONF_HW_RXTX_RATE_54, | ||
79 | CONF_HW_RXTX_RATE_48, | ||
80 | CONF_HW_RXTX_RATE_36, | ||
81 | CONF_HW_RXTX_RATE_24, | ||
82 | CONF_HW_RXTX_RATE_22, | ||
83 | CONF_HW_RXTX_RATE_18, | ||
84 | CONF_HW_RXTX_RATE_12, | ||
85 | CONF_HW_RXTX_RATE_11, | ||
86 | CONF_HW_RXTX_RATE_9, | ||
87 | CONF_HW_RXTX_RATE_6, | ||
88 | CONF_HW_RXTX_RATE_5_5, | ||
89 | CONF_HW_RXTX_RATE_2, | ||
90 | CONF_HW_RXTX_RATE_1, | ||
91 | CONF_HW_RXTX_RATE_MAX, | ||
92 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | ||
93 | }; | ||
94 | |||
95 | /* Rates between and including these are MCS rates */ | ||
96 | #define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI | ||
97 | #define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0 | ||
98 | 69 | ||
99 | enum { | 70 | enum { |
100 | CONF_SG_DISABLE = 0, | 71 | CONF_SG_DISABLE = 0, |
@@ -1096,16 +1067,31 @@ struct conf_scan_settings { | |||
1096 | }; | 1067 | }; |
1097 | 1068 | ||
1098 | struct conf_sched_scan_settings { | 1069 | struct conf_sched_scan_settings { |
1099 | /* minimum time to wait on the channel for active scans (in TUs) */ | 1070 | /* |
1100 | u16 min_dwell_time_active; | 1071 | * The base time to wait on the channel for active scans (in TU/1000). |
1072 | * The minimum dwell time is calculated according to this: | ||
1073 | * min_dwell_time = base + num_of_probes_to_be_sent * delta_per_probe | ||
1074 | * The maximum dwell time is calculated according to this: | ||
1075 | * max_dwell_time = min_dwell_time + max_dwell_time_delta | ||
1076 | */ | ||
1077 | u32 base_dwell_time; | ||
1101 | 1078 | ||
1102 | /* maximum time to wait on the channel for active scans (in TUs) */ | 1079 | /* The delta between the min dwell time and max dwell time for |
1103 | u16 max_dwell_time_active; | 1080 | * active scans (in TU/1000s). The max dwell time is used by the FW once |
1081 | * traffic is detected on the channel. | ||
1082 | */ | ||
1083 | u32 max_dwell_time_delta; | ||
1084 | |||
1085 | /* Delta added to min dwell time per each probe in 2.4 GHz (TU/1000) */ | ||
1086 | u32 dwell_time_delta_per_probe; | ||
1104 | 1087 | ||
1105 | /* time to wait on the channel for passive scans (in TUs) */ | 1088 | /* Delta added to min dwell time per each probe in 5 GHz (TU/1000) */ |
1089 | u32 dwell_time_delta_per_probe_5; | ||
1090 | |||
1091 | /* time to wait on the channel for passive scans (in TU/1000) */ | ||
1106 | u32 dwell_time_passive; | 1092 | u32 dwell_time_passive; |
1107 | 1093 | ||
1108 | /* time to wait on the channel for DFS scans (in TUs) */ | 1094 | /* time to wait on the channel for DFS scans (in TU/1000) */ |
1109 | u32 dwell_time_dfs; | 1095 | u32 dwell_time_dfs; |
1110 | 1096 | ||
1111 | /* number of probe requests to send on each channel in active scans */ | 1097 | /* number of probe requests to send on each channel in active scans */ |
@@ -1118,26 +1104,6 @@ struct conf_sched_scan_settings { | |||
1118 | s8 snr_threshold; | 1104 | s8 snr_threshold; |
1119 | }; | 1105 | }; |
1120 | 1106 | ||
1121 | /* these are number of channels on the band divided by two, rounded up */ | ||
1122 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | ||
1123 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | ||
1124 | |||
1125 | struct conf_rf_settings { | ||
1126 | /* | ||
1127 | * Per channel power compensation for 2.4GHz | ||
1128 | * | ||
1129 | * Range: s8 | ||
1130 | */ | ||
1131 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
1132 | |||
1133 | /* | ||
1134 | * Per channel power compensation for 5GHz | ||
1135 | * | ||
1136 | * Range: s8 | ||
1137 | */ | ||
1138 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
1139 | }; | ||
1140 | |||
1141 | struct conf_ht_setting { | 1107 | struct conf_ht_setting { |
1142 | u8 rx_ba_win_size; | 1108 | u8 rx_ba_win_size; |
1143 | u8 tx_ba_win_size; | 1109 | u8 tx_ba_win_size; |
@@ -1286,7 +1252,7 @@ struct conf_hangover_settings { | |||
1286 | u8 window_size; | 1252 | u8 window_size; |
1287 | }; | 1253 | }; |
1288 | 1254 | ||
1289 | struct conf_drv_settings { | 1255 | struct wlcore_conf { |
1290 | struct conf_sg_settings sg; | 1256 | struct conf_sg_settings sg; |
1291 | struct conf_rx_settings rx; | 1257 | struct conf_rx_settings rx; |
1292 | struct conf_tx_settings tx; | 1258 | struct conf_tx_settings tx; |
@@ -1296,16 +1262,13 @@ struct conf_drv_settings { | |||
1296 | struct conf_roam_trigger_settings roam_trigger; | 1262 | struct conf_roam_trigger_settings roam_trigger; |
1297 | struct conf_scan_settings scan; | 1263 | struct conf_scan_settings scan; |
1298 | struct conf_sched_scan_settings sched_scan; | 1264 | struct conf_sched_scan_settings sched_scan; |
1299 | struct conf_rf_settings rf; | ||
1300 | struct conf_ht_setting ht; | 1265 | struct conf_ht_setting ht; |
1301 | struct conf_memory_settings mem_wl127x; | 1266 | struct conf_memory_settings mem; |
1302 | struct conf_memory_settings mem_wl128x; | ||
1303 | struct conf_fm_coex fm_coex; | 1267 | struct conf_fm_coex fm_coex; |
1304 | struct conf_rx_streaming_settings rx_streaming; | 1268 | struct conf_rx_streaming_settings rx_streaming; |
1305 | struct conf_fwlog fwlog; | 1269 | struct conf_fwlog fwlog; |
1306 | struct conf_rate_policy_settings rate; | 1270 | struct conf_rate_policy_settings rate; |
1307 | struct conf_hangover_settings hangover; | 1271 | struct conf_hangover_settings hangover; |
1308 | u8 hci_io_ds; | ||
1309 | }; | 1272 | }; |
1310 | 1273 | ||
1311 | #endif | 1274 | #endif |
diff --git a/drivers/net/wireless/wl12xx/debug.h b/drivers/net/wireless/ti/wlcore/debug.h index ec0fdc25b280..6b800b3cbea5 100644 --- a/drivers/net/wireless/wl12xx/debug.h +++ b/drivers/net/wireless/ti/wlcore/debug.h | |||
@@ -52,6 +52,7 @@ enum { | |||
52 | DEBUG_ADHOC = BIT(16), | 52 | DEBUG_ADHOC = BIT(16), |
53 | DEBUG_AP = BIT(17), | 53 | DEBUG_AP = BIT(17), |
54 | DEBUG_PROBE = BIT(18), | 54 | DEBUG_PROBE = BIT(18), |
55 | DEBUG_IO = BIT(19), | ||
55 | DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), | 56 | DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), |
56 | DEBUG_ALL = ~0, | 57 | DEBUG_ALL = ~0, |
57 | }; | 58 | }; |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 564d49575c94..d5aea1ff5ad1 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | 28 | ||
29 | #include "wl12xx.h" | 29 | #include "wlcore.h" |
30 | #include "debug.h" | 30 | #include "debug.h" |
31 | #include "acx.h" | 31 | #include "acx.h" |
32 | #include "ps.h" | 32 | #include "ps.h" |
@@ -647,6 +647,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
647 | VIF_STATE_PRINT_INT(last_rssi_event); | 647 | VIF_STATE_PRINT_INT(last_rssi_event); |
648 | VIF_STATE_PRINT_INT(ba_support); | 648 | VIF_STATE_PRINT_INT(ba_support); |
649 | VIF_STATE_PRINT_INT(ba_allowed); | 649 | VIF_STATE_PRINT_INT(ba_allowed); |
650 | VIF_STATE_PRINT_INT(is_gem); | ||
650 | VIF_STATE_PRINT_LLHEX(tx_security_seq); | 651 | VIF_STATE_PRINT_LLHEX(tx_security_seq); |
651 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); | 652 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); |
652 | } | 653 | } |
diff --git a/drivers/net/wireless/wl12xx/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index 254c5b292cf6..a8d3aef011ff 100644 --- a/drivers/net/wireless/wl12xx/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef __DEBUGFS_H__ | 24 | #ifndef __DEBUGFS_H__ |
25 | #define __DEBUGFS_H__ | 25 | #define __DEBUGFS_H__ |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_debugfs_init(struct wl1271 *wl); | 29 | int wl1271_debugfs_init(struct wl1271 *wl); |
30 | void wl1271_debugfs_exit(struct wl1271 *wl); | 30 | void wl1271_debugfs_exit(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/ti/wlcore/event.c index c953717f38eb..292632ddf890 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -21,9 +21,8 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "wl12xx.h" | 24 | #include "wlcore.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "reg.h" | ||
27 | #include "io.h" | 26 | #include "io.h" |
28 | #include "event.h" | 27 | #include "event.h" |
29 | #include "ps.h" | 28 | #include "ps.h" |
@@ -98,8 +97,9 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox) | |||
98 | wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); | 97 | wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); |
99 | } | 98 | } |
100 | 99 | ||
101 | static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | 100 | static int wl1271_event_process(struct wl1271 *wl) |
102 | { | 101 | { |
102 | struct event_mailbox *mbox = wl->mbox; | ||
103 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
104 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
105 | u32 vector; | 105 | u32 vector; |
@@ -196,7 +196,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
196 | bool success; | 196 | bool success; |
197 | 197 | ||
198 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, | 198 | if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, |
199 | &wl->flags)) | 199 | &wlvif->flags)) |
200 | continue; | 200 | continue; |
201 | 201 | ||
202 | success = mbox->channel_switch_status ? false : true; | 202 | success = mbox->channel_switch_status ? false : true; |
@@ -278,18 +278,8 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
278 | return 0; | 278 | return 0; |
279 | } | 279 | } |
280 | 280 | ||
281 | void wl1271_event_mbox_config(struct wl1271 *wl) | ||
282 | { | ||
283 | wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); | ||
284 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | ||
285 | |||
286 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", | ||
287 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | ||
288 | } | ||
289 | |||
290 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | 281 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) |
291 | { | 282 | { |
292 | struct event_mailbox mbox; | ||
293 | int ret; | 283 | int ret; |
294 | 284 | ||
295 | wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); | 285 | wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); |
@@ -298,16 +288,19 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
298 | return -EINVAL; | 288 | return -EINVAL; |
299 | 289 | ||
300 | /* first we read the mbox descriptor */ | 290 | /* first we read the mbox descriptor */ |
301 | wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox, | 291 | wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, |
302 | sizeof(struct event_mailbox), false); | 292 | sizeof(*wl->mbox), false); |
303 | 293 | ||
304 | /* process the descriptor */ | 294 | /* process the descriptor */ |
305 | ret = wl1271_event_process(wl, &mbox); | 295 | ret = wl1271_event_process(wl); |
306 | if (ret < 0) | 296 | if (ret < 0) |
307 | return ret; | 297 | return ret; |
308 | 298 | ||
309 | /* then we let the firmware know it can go on...*/ | 299 | /* |
310 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); | 300 | * TODO: we just need this because one bit is in a different |
301 | * place. Is there any better way? | ||
302 | */ | ||
303 | wl->ops->ack_event(wl); | ||
311 | 304 | ||
312 | return 0; | 305 | return 0; |
313 | } | 306 | } |
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/ti/wlcore/event.h index 057d193d3525..8adf18d6c58f 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/ti/wlcore/event.h | |||
@@ -132,8 +132,9 @@ struct event_mailbox { | |||
132 | u8 reserved_8[9]; | 132 | u8 reserved_8[9]; |
133 | } __packed; | 133 | } __packed; |
134 | 134 | ||
135 | struct wl1271; | ||
136 | |||
135 | int wl1271_event_unmask(struct wl1271 *wl); | 137 | int wl1271_event_unmask(struct wl1271 *wl); |
136 | void wl1271_event_mbox_config(struct wl1271 *wl); | ||
137 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 138 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
138 | 139 | ||
139 | #endif | 140 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h new file mode 100644 index 000000000000..9384b4d56c24 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -0,0 +1,122 @@ | |||
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 __WLCORE_HW_OPS_H__ | ||
23 | #define __WLCORE_HW_OPS_H__ | ||
24 | |||
25 | #include "wlcore.h" | ||
26 | #include "rx.h" | ||
27 | |||
28 | static inline u32 | ||
29 | wlcore_hw_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | ||
30 | { | ||
31 | if (!wl->ops->calc_tx_blocks) | ||
32 | BUG_ON(1); | ||
33 | |||
34 | return wl->ops->calc_tx_blocks(wl, len, spare_blks); | ||
35 | } | ||
36 | |||
37 | static inline void | ||
38 | wlcore_hw_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, | ||
39 | u32 blks, u32 spare_blks) | ||
40 | { | ||
41 | if (!wl->ops->set_tx_desc_blocks) | ||
42 | BUG_ON(1); | ||
43 | |||
44 | return wl->ops->set_tx_desc_blocks(wl, desc, blks, spare_blks); | ||
45 | } | ||
46 | |||
47 | static inline void | ||
48 | wlcore_hw_set_tx_desc_data_len(struct wl1271 *wl, | ||
49 | struct wl1271_tx_hw_descr *desc, | ||
50 | struct sk_buff *skb) | ||
51 | { | ||
52 | if (!wl->ops->set_tx_desc_data_len) | ||
53 | BUG_ON(1); | ||
54 | |||
55 | wl->ops->set_tx_desc_data_len(wl, desc, skb); | ||
56 | } | ||
57 | |||
58 | static inline enum wl_rx_buf_align | ||
59 | wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | ||
60 | { | ||
61 | |||
62 | if (!wl->ops->get_rx_buf_align) | ||
63 | BUG_ON(1); | ||
64 | |||
65 | return wl->ops->get_rx_buf_align(wl, rx_desc); | ||
66 | } | ||
67 | |||
68 | static inline void | ||
69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | ||
70 | { | ||
71 | if (wl->ops->prepare_read) | ||
72 | wl->ops->prepare_read(wl, rx_desc, len); | ||
73 | } | ||
74 | |||
75 | static inline u32 | ||
76 | wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len) | ||
77 | { | ||
78 | if (!wl->ops->get_rx_packet_len) | ||
79 | BUG_ON(1); | ||
80 | |||
81 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); | ||
82 | } | ||
83 | |||
84 | static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl) | ||
85 | { | ||
86 | if (wl->ops->tx_delayed_compl) | ||
87 | wl->ops->tx_delayed_compl(wl); | ||
88 | } | ||
89 | |||
90 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) | ||
91 | { | ||
92 | if (wl->ops->tx_immediate_compl) | ||
93 | wl->ops->tx_immediate_compl(wl); | ||
94 | } | ||
95 | |||
96 | static inline int | ||
97 | wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
98 | { | ||
99 | if (wl->ops->init_vif) | ||
100 | return wl->ops->init_vif(wl, wlvif); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static inline u32 | ||
106 | wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif) | ||
107 | { | ||
108 | if (!wl->ops->sta_get_ap_rate_mask) | ||
109 | BUG_ON(1); | ||
110 | |||
111 | return wl->ops->sta_get_ap_rate_mask(wl, wlvif); | ||
112 | } | ||
113 | |||
114 | static inline int wlcore_identify_fw(struct wl1271 *wl) | ||
115 | { | ||
116 | if (wl->ops->identify_fw) | ||
117 | return wl->ops->identify_fw(wl); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/ti/wlcore/ini.h index 4cf9ecc56212..4cf9ecc56212 100644 --- a/drivers/net/wireless/wl12xx/ini.h +++ b/drivers/net/wireless/ti/wlcore/ini.h | |||
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/ti/wlcore/init.c index 203fbebf09eb..9f89255eb6e6 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "acx.h" | 31 | #include "acx.h" |
32 | #include "cmd.h" | 32 | #include "cmd.h" |
33 | #include "reg.h" | ||
34 | #include "tx.h" | 33 | #include "tx.h" |
35 | #include "io.h" | 34 | #include "io.h" |
35 | #include "hw_ops.h" | ||
36 | 36 | ||
37 | int wl1271_init_templates_config(struct wl1271 *wl) | 37 | int wl1271_init_templates_config(struct wl1271 *wl) |
38 | { | 38 | { |
@@ -319,7 +319,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl) | |||
319 | { | 319 | { |
320 | int ret; | 320 | int ret; |
321 | 321 | ||
322 | if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) | 322 | if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) |
323 | return 0; | 323 | return 0; |
324 | 324 | ||
325 | ret = wl12xx_cmd_config_fwlog(wl); | 325 | ret = wl12xx_cmd_config_fwlog(wl); |
@@ -494,26 +494,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
494 | return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); | 494 | return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); |
495 | } | 495 | } |
496 | 496 | ||
497 | int wl1271_chip_specific_init(struct wl1271 *wl) | ||
498 | { | ||
499 | int ret = 0; | ||
500 | |||
501 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
502 | u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; | ||
503 | |||
504 | if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT)) | ||
505 | /* Enable SDIO padding */ | ||
506 | host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; | ||
507 | |||
508 | /* Must be before wl1271_acx_init_mem_config() */ | ||
509 | ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); | ||
510 | if (ret < 0) | ||
511 | goto out; | ||
512 | } | ||
513 | out: | ||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | /* vif-specifc initialization */ | 497 | /* vif-specifc initialization */ |
518 | static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) | 498 | static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
519 | { | 499 | { |
@@ -582,10 +562,17 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
582 | if (ret < 0) | 562 | if (ret < 0) |
583 | return ret; | 563 | return ret; |
584 | } else if (!wl->sta_count) { | 564 | } else if (!wl->sta_count) { |
585 | /* Configure for ELP power saving */ | 565 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) { |
586 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | 566 | /* Configure for power always on */ |
587 | if (ret < 0) | 567 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
588 | return ret; | 568 | if (ret < 0) |
569 | return ret; | ||
570 | } else { | ||
571 | /* Configure for ELP power saving */ | ||
572 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
573 | if (ret < 0) | ||
574 | return ret; | ||
575 | } | ||
589 | } | 576 | } |
590 | } | 577 | } |
591 | 578 | ||
@@ -652,6 +639,10 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
652 | if (ret < 0) | 639 | if (ret < 0) |
653 | return ret; | 640 | return ret; |
654 | 641 | ||
642 | ret = wlcore_hw_init_vif(wl, wlvif); | ||
643 | if (ret < 0) | ||
644 | return ret; | ||
645 | |||
655 | return 0; | 646 | return 0; |
656 | } | 647 | } |
657 | 648 | ||
@@ -659,27 +650,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
659 | { | 650 | { |
660 | int ret; | 651 | int ret; |
661 | 652 | ||
662 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 653 | /* Chip-specific hw init */ |
663 | ret = wl128x_cmd_general_parms(wl); | 654 | ret = wl->ops->hw_init(wl); |
664 | if (ret < 0) | ||
665 | return ret; | ||
666 | ret = wl128x_cmd_radio_parms(wl); | ||
667 | if (ret < 0) | ||
668 | return ret; | ||
669 | } else { | ||
670 | ret = wl1271_cmd_general_parms(wl); | ||
671 | if (ret < 0) | ||
672 | return ret; | ||
673 | ret = wl1271_cmd_radio_parms(wl); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
677 | if (ret < 0) | ||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | /* Chip-specific init */ | ||
682 | ret = wl1271_chip_specific_init(wl); | ||
683 | if (ret < 0) | 655 | if (ret < 0) |
684 | return ret; | 656 | return ret; |
685 | 657 | ||
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/ti/wlcore/init.h index 2da0f404ef6e..a45fbfddec19 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/ti/wlcore/init.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef __INIT_H__ | 24 | #ifndef __INIT_H__ |
25 | #define __INIT_H__ | 25 | #define __INIT_H__ |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | 30 | int wl1271_init_templates_config(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/ti/wlcore/io.c index c574a3b31e31..7cd0081aede5 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c | |||
@@ -26,84 +26,12 @@ | |||
26 | #include <linux/spi/spi.h> | 26 | #include <linux/spi/spi.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | 28 | ||
29 | #include "wl12xx.h" | 29 | #include "wlcore.h" |
30 | #include "debug.h" | 30 | #include "debug.h" |
31 | #include "wl12xx_80211.h" | 31 | #include "wl12xx_80211.h" |
32 | #include "io.h" | 32 | #include "io.h" |
33 | #include "tx.h" | 33 | #include "tx.h" |
34 | 34 | ||
35 | #define OCP_CMD_LOOP 32 | ||
36 | |||
37 | #define OCP_CMD_WRITE 0x1 | ||
38 | #define OCP_CMD_READ 0x2 | ||
39 | |||
40 | #define OCP_READY_MASK BIT(18) | ||
41 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
42 | |||
43 | #define OCP_STATUS_NO_RESP 0x00000 | ||
44 | #define OCP_STATUS_OK 0x10000 | ||
45 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
46 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
47 | |||
48 | struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = { | ||
49 | [PART_DOWN] = { | ||
50 | .mem = { | ||
51 | .start = 0x00000000, | ||
52 | .size = 0x000177c0 | ||
53 | }, | ||
54 | .reg = { | ||
55 | .start = REGISTERS_BASE, | ||
56 | .size = 0x00008800 | ||
57 | }, | ||
58 | .mem2 = { | ||
59 | .start = 0x00000000, | ||
60 | .size = 0x00000000 | ||
61 | }, | ||
62 | .mem3 = { | ||
63 | .start = 0x00000000, | ||
64 | .size = 0x00000000 | ||
65 | }, | ||
66 | }, | ||
67 | |||
68 | [PART_WORK] = { | ||
69 | .mem = { | ||
70 | .start = 0x00040000, | ||
71 | .size = 0x00014fc0 | ||
72 | }, | ||
73 | .reg = { | ||
74 | .start = REGISTERS_BASE, | ||
75 | .size = 0x0000a000 | ||
76 | }, | ||
77 | .mem2 = { | ||
78 | .start = 0x003004f8, | ||
79 | .size = 0x00000004 | ||
80 | }, | ||
81 | .mem3 = { | ||
82 | .start = 0x00040404, | ||
83 | .size = 0x00000000 | ||
84 | }, | ||
85 | }, | ||
86 | |||
87 | [PART_DRPW] = { | ||
88 | .mem = { | ||
89 | .start = 0x00040000, | ||
90 | .size = 0x00014fc0 | ||
91 | }, | ||
92 | .reg = { | ||
93 | .start = DRPW_BASE, | ||
94 | .size = 0x00006000 | ||
95 | }, | ||
96 | .mem2 = { | ||
97 | .start = 0x00000000, | ||
98 | .size = 0x00000000 | ||
99 | }, | ||
100 | .mem3 = { | ||
101 | .start = 0x00000000, | ||
102 | .size = 0x00000000 | ||
103 | } | ||
104 | } | ||
105 | }; | ||
106 | |||
107 | bool wl1271_set_block_size(struct wl1271 *wl) | 35 | bool wl1271_set_block_size(struct wl1271 *wl) |
108 | { | 36 | { |
109 | if (wl->if_ops->set_block_size) { | 37 | if (wl->if_ops->set_block_size) { |
@@ -114,17 +42,53 @@ bool wl1271_set_block_size(struct wl1271 *wl) | |||
114 | return false; | 42 | return false; |
115 | } | 43 | } |
116 | 44 | ||
117 | void wl1271_disable_interrupts(struct wl1271 *wl) | 45 | void wlcore_disable_interrupts(struct wl1271 *wl) |
118 | { | 46 | { |
119 | disable_irq(wl->irq); | 47 | disable_irq(wl->irq); |
120 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); | ||
121 | 50 | ||
122 | void wl1271_enable_interrupts(struct wl1271 *wl) | 51 | void wlcore_enable_interrupts(struct wl1271 *wl) |
123 | { | 52 | { |
124 | enable_irq(wl->irq); | 53 | enable_irq(wl->irq); |
125 | } | 54 | } |
55 | EXPORT_SYMBOL_GPL(wlcore_enable_interrupts); | ||
126 | 56 | ||
127 | /* Set the SPI partitions to access the chip addresses | 57 | int wlcore_translate_addr(struct wl1271 *wl, int addr) |
58 | { | ||
59 | struct wlcore_partition_set *part = &wl->curr_part; | ||
60 | |||
61 | /* | ||
62 | * To translate, first check to which window of addresses the | ||
63 | * particular address belongs. Then subtract the starting address | ||
64 | * of that window from the address. Then, add offset of the | ||
65 | * translated region. | ||
66 | * | ||
67 | * The translated regions occur next to each other in physical device | ||
68 | * memory, so just add the sizes of the preceding address regions to | ||
69 | * get the offset to the new region. | ||
70 | */ | ||
71 | if ((addr >= part->mem.start) && | ||
72 | (addr < part->mem.start + part->mem.size)) | ||
73 | return addr - part->mem.start; | ||
74 | else if ((addr >= part->reg.start) && | ||
75 | (addr < part->reg.start + part->reg.size)) | ||
76 | return addr - part->reg.start + part->mem.size; | ||
77 | else if ((addr >= part->mem2.start) && | ||
78 | (addr < part->mem2.start + part->mem2.size)) | ||
79 | return addr - part->mem2.start + part->mem.size + | ||
80 | part->reg.size; | ||
81 | else if ((addr >= part->mem3.start) && | ||
82 | (addr < part->mem3.start + part->mem3.size)) | ||
83 | return addr - part->mem3.start + part->mem.size + | ||
84 | part->reg.size + part->mem2.size; | ||
85 | |||
86 | WARN(1, "HW address 0x%x out of range", addr); | ||
87 | return 0; | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(wlcore_translate_addr); | ||
90 | |||
91 | /* Set the partitions to access the chip addresses | ||
128 | * | 92 | * |
129 | * To simplify driver code, a fixed (virtual) memory map is defined for | 93 | * To simplify driver code, a fixed (virtual) memory map is defined for |
130 | * register and memory addresses. Because in the chipset, in different stages | 94 | * register and memory addresses. Because in the chipset, in different stages |
@@ -158,33 +122,43 @@ void wl1271_enable_interrupts(struct wl1271 *wl) | |||
158 | * | | | 122 | * | | |
159 | * | 123 | * |
160 | */ | 124 | */ |
161 | int wl1271_set_partition(struct wl1271 *wl, | 125 | void wlcore_set_partition(struct wl1271 *wl, |
162 | struct wl1271_partition_set *p) | 126 | const struct wlcore_partition_set *p) |
163 | { | 127 | { |
164 | /* copy partition info */ | 128 | /* copy partition info */ |
165 | memcpy(&wl->part, p, sizeof(*p)); | 129 | memcpy(&wl->curr_part, p, sizeof(*p)); |
166 | 130 | ||
167 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | 131 | wl1271_debug(DEBUG_IO, "mem_start %08X mem_size %08X", |
168 | p->mem.start, p->mem.size); | 132 | p->mem.start, p->mem.size); |
169 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | 133 | wl1271_debug(DEBUG_IO, "reg_start %08X reg_size %08X", |
170 | p->reg.start, p->reg.size); | 134 | p->reg.start, p->reg.size); |
171 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | 135 | wl1271_debug(DEBUG_IO, "mem2_start %08X mem2_size %08X", |
172 | p->mem2.start, p->mem2.size); | 136 | p->mem2.start, p->mem2.size); |
173 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | 137 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", |
174 | p->mem3.start, p->mem3.size); | 138 | p->mem3.start, p->mem3.size); |
175 | 139 | ||
176 | /* write partition info to the chipset */ | ||
177 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | 140 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); |
178 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | 141 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); |
179 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | 142 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); |
180 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | 143 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); |
181 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | 144 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); |
182 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | 145 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); |
146 | /* | ||
147 | * We don't need the size of the last partition, as it is | ||
148 | * automatically calculated based on the total memory size and | ||
149 | * the sizes of the previous partitions. | ||
150 | */ | ||
183 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | 151 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); |
152 | } | ||
153 | EXPORT_SYMBOL_GPL(wlcore_set_partition); | ||
184 | 154 | ||
185 | return 0; | 155 | void wlcore_select_partition(struct wl1271 *wl, u8 part) |
156 | { | ||
157 | wl1271_debug(DEBUG_IO, "setting partition %d", part); | ||
158 | |||
159 | wlcore_set_partition(wl, &wl->ptable[part]); | ||
186 | } | 160 | } |
187 | EXPORT_SYMBOL_GPL(wl1271_set_partition); | 161 | EXPORT_SYMBOL_GPL(wlcore_select_partition); |
188 | 162 | ||
189 | void wl1271_io_reset(struct wl1271 *wl) | 163 | void wl1271_io_reset(struct wl1271 *wl) |
190 | { | 164 | { |
@@ -197,48 +171,3 @@ void wl1271_io_init(struct wl1271 *wl) | |||
197 | if (wl->if_ops->init) | 171 | if (wl->if_ops->init) |
198 | wl->if_ops->init(wl->dev); | 172 | wl->if_ops->init(wl->dev); |
199 | } | 173 | } |
200 | |||
201 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
202 | { | ||
203 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
204 | addr = (addr >> 1) + 0x30000; | ||
205 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
206 | |||
207 | /* write value to OCP_POR_WDATA */ | ||
208 | wl1271_write32(wl, OCP_DATA_WRITE, val); | ||
209 | |||
210 | /* write 1 to OCP_CMD */ | ||
211 | wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
212 | } | ||
213 | |||
214 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
215 | { | ||
216 | u32 val; | ||
217 | int timeout = OCP_CMD_LOOP; | ||
218 | |||
219 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
220 | addr = (addr >> 1) + 0x30000; | ||
221 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
222 | |||
223 | /* write 2 to OCP_CMD */ | ||
224 | wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
225 | |||
226 | /* poll for data ready */ | ||
227 | do { | ||
228 | val = wl1271_read32(wl, OCP_DATA_READ); | ||
229 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
230 | |||
231 | if (!timeout) { | ||
232 | wl1271_warning("Top register access timed out."); | ||
233 | return 0xffff; | ||
234 | } | ||
235 | |||
236 | /* check data status and return if OK */ | ||
237 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
238 | return val & 0xffff; | ||
239 | else { | ||
240 | wl1271_warning("Top register access returned error."); | ||
241 | return 0xffff; | ||
242 | } | ||
243 | } | ||
244 | |||
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/ti/wlcore/io.h index 4fb3dab8c3b2..8942954b56a0 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
@@ -26,7 +26,6 @@ | |||
26 | #define __IO_H__ | 26 | #define __IO_H__ |
27 | 27 | ||
28 | #include <linux/irqreturn.h> | 28 | #include <linux/irqreturn.h> |
29 | #include "reg.h" | ||
30 | 29 | ||
31 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | 30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 |
32 | 31 | ||
@@ -43,15 +42,14 @@ | |||
43 | 42 | ||
44 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | 43 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 |
45 | 44 | ||
46 | extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN]; | ||
47 | |||
48 | struct wl1271; | 45 | struct wl1271; |
49 | 46 | ||
50 | void wl1271_disable_interrupts(struct wl1271 *wl); | 47 | void wlcore_disable_interrupts(struct wl1271 *wl); |
51 | void wl1271_enable_interrupts(struct wl1271 *wl); | 48 | void wlcore_enable_interrupts(struct wl1271 *wl); |
52 | 49 | ||
53 | void wl1271_io_reset(struct wl1271 *wl); | 50 | void wl1271_io_reset(struct wl1271 *wl); |
54 | void wl1271_io_init(struct wl1271 *wl); | 51 | void wl1271_io_init(struct wl1271 *wl); |
52 | int wlcore_translate_addr(struct wl1271 *wl, int addr); | ||
55 | 53 | ||
56 | /* Raw target IO, address is not translated */ | 54 | /* Raw target IO, address is not translated */ |
57 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 55 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, |
@@ -66,6 +64,18 @@ static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
66 | wl->if_ops->read(wl->dev, addr, buf, len, fixed); | 64 | wl->if_ops->read(wl->dev, addr, buf, len, fixed); |
67 | } | 65 | } |
68 | 66 | ||
67 | static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf, | ||
68 | size_t len, bool fixed) | ||
69 | { | ||
70 | wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed); | ||
71 | } | ||
72 | |||
73 | static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf, | ||
74 | size_t len, bool fixed) | ||
75 | { | ||
76 | wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed); | ||
77 | } | ||
78 | |||
69 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 79 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) |
70 | { | 80 | { |
71 | wl1271_raw_read(wl, addr, &wl->buffer_32, | 81 | wl1271_raw_read(wl, addr, &wl->buffer_32, |
@@ -81,36 +91,12 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | |||
81 | sizeof(wl->buffer_32), false); | 91 | sizeof(wl->buffer_32), false); |
82 | } | 92 | } |
83 | 93 | ||
84 | /* Translated target IO */ | ||
85 | static inline int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
86 | { | ||
87 | /* | ||
88 | * To translate, first check to which window of addresses the | ||
89 | * particular address belongs. Then subtract the starting address | ||
90 | * of that window from the address. Then, add offset of the | ||
91 | * translated region. | ||
92 | * | ||
93 | * The translated regions occur next to each other in physical device | ||
94 | * memory, so just add the sizes of the preceding address regions to | ||
95 | * get the offset to the new region. | ||
96 | * | ||
97 | * Currently, only the two first regions are addressed, and the | ||
98 | * assumption is that all addresses will fall into either of those | ||
99 | * two. | ||
100 | */ | ||
101 | if ((addr >= wl->part.reg.start) && | ||
102 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
103 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
104 | else | ||
105 | return addr - wl->part.mem.start; | ||
106 | } | ||
107 | |||
108 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | 94 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, |
109 | size_t len, bool fixed) | 95 | size_t len, bool fixed) |
110 | { | 96 | { |
111 | int physical; | 97 | int physical; |
112 | 98 | ||
113 | physical = wl1271_translate_addr(wl, addr); | 99 | physical = wlcore_translate_addr(wl, addr); |
114 | 100 | ||
115 | wl1271_raw_read(wl, physical, buf, len, fixed); | 101 | wl1271_raw_read(wl, physical, buf, len, fixed); |
116 | } | 102 | } |
@@ -120,11 +106,23 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | |||
120 | { | 106 | { |
121 | int physical; | 107 | int physical; |
122 | 108 | ||
123 | physical = wl1271_translate_addr(wl, addr); | 109 | physical = wlcore_translate_addr(wl, addr); |
124 | 110 | ||
125 | wl1271_raw_write(wl, physical, buf, len, fixed); | 111 | wl1271_raw_write(wl, physical, buf, len, fixed); |
126 | } | 112 | } |
127 | 113 | ||
114 | static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf, | ||
115 | size_t len, bool fixed) | ||
116 | { | ||
117 | wl1271_write(wl, wl->rtable[reg], buf, len, fixed); | ||
118 | } | ||
119 | |||
120 | static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf, | ||
121 | size_t len, bool fixed) | ||
122 | { | ||
123 | wl1271_read(wl, wl->rtable[reg], buf, len, fixed); | ||
124 | } | ||
125 | |||
128 | static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | 126 | static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, |
129 | void *buf, size_t len, bool fixed) | 127 | void *buf, size_t len, bool fixed) |
130 | { | 128 | { |
@@ -134,19 +132,30 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
134 | /* Addresses are stored internally as addresses to 32 bytes blocks */ | 132 | /* Addresses are stored internally as addresses to 32 bytes blocks */ |
135 | addr = hwaddr << 5; | 133 | addr = hwaddr << 5; |
136 | 134 | ||
137 | physical = wl1271_translate_addr(wl, addr); | 135 | physical = wlcore_translate_addr(wl, addr); |
138 | 136 | ||
139 | wl1271_raw_read(wl, physical, buf, len, fixed); | 137 | wl1271_raw_read(wl, physical, buf, len, fixed); |
140 | } | 138 | } |
141 | 139 | ||
142 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | 140 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) |
143 | { | 141 | { |
144 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | 142 | return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr)); |
145 | } | 143 | } |
146 | 144 | ||
147 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | 145 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) |
148 | { | 146 | { |
149 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | 147 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); |
148 | } | ||
149 | |||
150 | static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) | ||
151 | { | ||
152 | return wl1271_raw_read32(wl, | ||
153 | wlcore_translate_addr(wl, wl->rtable[reg])); | ||
154 | } | ||
155 | |||
156 | static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) | ||
157 | { | ||
158 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val); | ||
150 | } | 159 | } |
151 | 160 | ||
152 | static inline void wl1271_power_off(struct wl1271 *wl) | 161 | static inline void wl1271_power_off(struct wl1271 *wl) |
@@ -164,13 +173,8 @@ static inline int wl1271_power_on(struct wl1271 *wl) | |||
164 | return ret; | 173 | return ret; |
165 | } | 174 | } |
166 | 175 | ||
167 | 176 | void wlcore_set_partition(struct wl1271 *wl, | |
168 | /* Top Register IO */ | 177 | const struct wlcore_partition_set *p); |
169 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
170 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
171 | |||
172 | int wl1271_set_partition(struct wl1271 *wl, | ||
173 | struct wl1271_partition_set *p); | ||
174 | 178 | ||
175 | bool wl1271_set_block_size(struct wl1271 *wl); | 179 | bool wl1271_set_block_size(struct wl1271 *wl); |
176 | 180 | ||
@@ -178,4 +182,6 @@ bool wl1271_set_block_size(struct wl1271 *wl); | |||
178 | 182 | ||
179 | int wl1271_tx_dummy_packet(struct wl1271 *wl); | 183 | int wl1271_tx_dummy_packet(struct wl1271 *wl); |
180 | 184 | ||
185 | void wlcore_select_partition(struct wl1271 *wl, u8 part); | ||
186 | |||
181 | #endif | 187 | #endif |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/ti/wlcore/main.c index 362ff1a7067e..2b0f987660c6 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -35,10 +35,9 @@ | |||
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | 37 | ||
38 | #include "wl12xx.h" | 38 | #include "wlcore.h" |
39 | #include "debug.h" | 39 | #include "debug.h" |
40 | #include "wl12xx_80211.h" | 40 | #include "wl12xx_80211.h" |
41 | #include "reg.h" | ||
42 | #include "io.h" | 41 | #include "io.h" |
43 | #include "event.h" | 42 | #include "event.h" |
44 | #include "tx.h" | 43 | #include "tx.h" |
@@ -50,342 +49,15 @@ | |||
50 | #include "boot.h" | 49 | #include "boot.h" |
51 | #include "testmode.h" | 50 | #include "testmode.h" |
52 | #include "scan.h" | 51 | #include "scan.h" |
52 | #include "hw_ops.h" | ||
53 | 53 | ||
54 | #define WL1271_BOOT_RETRIES 3 | 54 | #define WL1271_BOOT_RETRIES 3 |
55 | 55 | ||
56 | static struct conf_drv_settings default_conf = { | 56 | #define WL1271_BOOT_RETRIES 3 |
57 | .sg = { | ||
58 | .params = { | ||
59 | [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, | ||
60 | [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, | ||
61 | [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, | ||
62 | [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, | ||
63 | [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, | ||
64 | [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, | ||
65 | [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, | ||
66 | [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, | ||
67 | [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, | ||
68 | [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, | ||
69 | [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, | ||
70 | [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, | ||
71 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, | ||
72 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, | ||
73 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, | ||
74 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, | ||
75 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, | ||
76 | [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, | ||
77 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, | ||
78 | [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, | ||
79 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, | ||
80 | [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, | ||
81 | [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, | ||
82 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, | ||
83 | [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, | ||
84 | [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, | ||
85 | /* active scan params */ | ||
86 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
87 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
88 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
89 | /* passive scan params */ | ||
90 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, | ||
91 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, | ||
92 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
93 | /* passive scan in dual antenna params */ | ||
94 | [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, | ||
95 | [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, | ||
96 | [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, | ||
97 | /* general params */ | ||
98 | [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, | ||
99 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
100 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
101 | [CONF_SG_DHCP_TIME] = 5000, | ||
102 | [CONF_SG_RXT] = 1200, | ||
103 | [CONF_SG_TXT] = 1000, | ||
104 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
105 | [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, | ||
106 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
107 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
108 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
109 | [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, | ||
110 | [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, | ||
111 | [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, | ||
112 | /* AP params */ | ||
113 | [CONF_AP_BEACON_MISS_TX] = 3, | ||
114 | [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, | ||
115 | [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, | ||
116 | [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, | ||
117 | [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, | ||
118 | [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, | ||
119 | /* CTS Diluting params */ | ||
120 | [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, | ||
121 | [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, | ||
122 | }, | ||
123 | .state = CONF_SG_PROTECTIVE, | ||
124 | }, | ||
125 | .rx = { | ||
126 | .rx_msdu_life_time = 512000, | ||
127 | .packet_detection_threshold = 0, | ||
128 | .ps_poll_timeout = 15, | ||
129 | .upsd_timeout = 15, | ||
130 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, | ||
131 | .rx_cca_threshold = 0, | ||
132 | .irq_blk_threshold = 0xFFFF, | ||
133 | .irq_pkt_threshold = 0, | ||
134 | .irq_timeout = 600, | ||
135 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | ||
136 | }, | ||
137 | .tx = { | ||
138 | .tx_energy_detection = 0, | ||
139 | .sta_rc_conf = { | ||
140 | .enabled_rates = 0, | ||
141 | .short_retry_limit = 10, | ||
142 | .long_retry_limit = 10, | ||
143 | .aflags = 0, | ||
144 | }, | ||
145 | .ac_conf_count = 4, | ||
146 | .ac_conf = { | ||
147 | [CONF_TX_AC_BE] = { | ||
148 | .ac = CONF_TX_AC_BE, | ||
149 | .cw_min = 15, | ||
150 | .cw_max = 63, | ||
151 | .aifsn = 3, | ||
152 | .tx_op_limit = 0, | ||
153 | }, | ||
154 | [CONF_TX_AC_BK] = { | ||
155 | .ac = CONF_TX_AC_BK, | ||
156 | .cw_min = 15, | ||
157 | .cw_max = 63, | ||
158 | .aifsn = 7, | ||
159 | .tx_op_limit = 0, | ||
160 | }, | ||
161 | [CONF_TX_AC_VI] = { | ||
162 | .ac = CONF_TX_AC_VI, | ||
163 | .cw_min = 15, | ||
164 | .cw_max = 63, | ||
165 | .aifsn = CONF_TX_AIFS_PIFS, | ||
166 | .tx_op_limit = 3008, | ||
167 | }, | ||
168 | [CONF_TX_AC_VO] = { | ||
169 | .ac = CONF_TX_AC_VO, | ||
170 | .cw_min = 15, | ||
171 | .cw_max = 63, | ||
172 | .aifsn = CONF_TX_AIFS_PIFS, | ||
173 | .tx_op_limit = 1504, | ||
174 | }, | ||
175 | }, | ||
176 | .max_tx_retries = 100, | ||
177 | .ap_aging_period = 300, | ||
178 | .tid_conf_count = 4, | ||
179 | .tid_conf = { | ||
180 | [CONF_TX_AC_BE] = { | ||
181 | .queue_id = CONF_TX_AC_BE, | ||
182 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
183 | .tsid = CONF_TX_AC_BE, | ||
184 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
185 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
186 | .apsd_conf = {0, 0}, | ||
187 | }, | ||
188 | [CONF_TX_AC_BK] = { | ||
189 | .queue_id = CONF_TX_AC_BK, | ||
190 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
191 | .tsid = CONF_TX_AC_BK, | ||
192 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
193 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
194 | .apsd_conf = {0, 0}, | ||
195 | }, | ||
196 | [CONF_TX_AC_VI] = { | ||
197 | .queue_id = CONF_TX_AC_VI, | ||
198 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
199 | .tsid = CONF_TX_AC_VI, | ||
200 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
201 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
202 | .apsd_conf = {0, 0}, | ||
203 | }, | ||
204 | [CONF_TX_AC_VO] = { | ||
205 | .queue_id = CONF_TX_AC_VO, | ||
206 | .channel_type = CONF_CHANNEL_TYPE_EDCF, | ||
207 | .tsid = CONF_TX_AC_VO, | ||
208 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
209 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
210 | .apsd_conf = {0, 0}, | ||
211 | }, | ||
212 | }, | ||
213 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | ||
214 | .tx_compl_timeout = 700, | ||
215 | .tx_compl_threshold = 4, | ||
216 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
217 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
218 | .tmpl_short_retry_limit = 10, | ||
219 | .tmpl_long_retry_limit = 10, | ||
220 | .tx_watchdog_timeout = 5000, | ||
221 | }, | ||
222 | .conn = { | ||
223 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | ||
224 | .listen_interval = 1, | ||
225 | .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, | ||
226 | .suspend_listen_interval = 3, | ||
227 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | ||
228 | .bcn_filt_ie_count = 2, | ||
229 | .bcn_filt_ie = { | ||
230 | [0] = { | ||
231 | .ie = WLAN_EID_CHANNEL_SWITCH, | ||
232 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | ||
233 | }, | ||
234 | [1] = { | ||
235 | .ie = WLAN_EID_HT_OPERATION, | ||
236 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
237 | }, | ||
238 | }, | ||
239 | .synch_fail_thold = 10, | ||
240 | .bss_lose_timeout = 100, | ||
241 | .beacon_rx_timeout = 10000, | ||
242 | .broadcast_timeout = 20000, | ||
243 | .rx_broadcast_in_ps = 1, | ||
244 | .ps_poll_threshold = 10, | ||
245 | .bet_enable = CONF_BET_MODE_ENABLE, | ||
246 | .bet_max_consecutive = 50, | ||
247 | .psm_entry_retries = 8, | ||
248 | .psm_exit_retries = 16, | ||
249 | .psm_entry_nullfunc_retries = 3, | ||
250 | .dynamic_ps_timeout = 200, | ||
251 | .forced_ps = false, | ||
252 | .keep_alive_interval = 55000, | ||
253 | .max_listen_interval = 20, | ||
254 | }, | ||
255 | .itrim = { | ||
256 | .enable = false, | ||
257 | .timeout = 50000, | ||
258 | }, | ||
259 | .pm_config = { | ||
260 | .host_clk_settling_time = 5000, | ||
261 | .host_fast_wakeup_support = false | ||
262 | }, | ||
263 | .roam_trigger = { | ||
264 | .trigger_pacing = 1, | ||
265 | .avg_weight_rssi_beacon = 20, | ||
266 | .avg_weight_rssi_data = 10, | ||
267 | .avg_weight_snr_beacon = 20, | ||
268 | .avg_weight_snr_data = 10, | ||
269 | }, | ||
270 | .scan = { | ||
271 | .min_dwell_time_active = 7500, | ||
272 | .max_dwell_time_active = 30000, | ||
273 | .min_dwell_time_passive = 100000, | ||
274 | .max_dwell_time_passive = 100000, | ||
275 | .num_probe_reqs = 2, | ||
276 | .split_scan_timeout = 50000, | ||
277 | }, | ||
278 | .sched_scan = { | ||
279 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | ||
280 | .min_dwell_time_active = 30, | ||
281 | .max_dwell_time_active = 60, | ||
282 | .dwell_time_passive = 100, | ||
283 | .dwell_time_dfs = 150, | ||
284 | .num_probe_reqs = 2, | ||
285 | .rssi_threshold = -90, | ||
286 | .snr_threshold = 0, | ||
287 | }, | ||
288 | .rf = { | ||
289 | .tx_per_channel_power_compensation_2 = { | ||
290 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
291 | }, | ||
292 | .tx_per_channel_power_compensation_5 = { | ||
293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
294 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
295 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
296 | }, | ||
297 | }, | ||
298 | .ht = { | ||
299 | .rx_ba_win_size = 8, | ||
300 | .tx_ba_win_size = 64, | ||
301 | .inactivity_timeout = 10000, | ||
302 | .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, | ||
303 | }, | ||
304 | .mem_wl127x = { | ||
305 | .num_stations = 1, | ||
306 | .ssid_profiles = 1, | ||
307 | .rx_block_num = 70, | ||
308 | .tx_min_block_num = 40, | ||
309 | .dynamic_memory = 1, | ||
310 | .min_req_tx_blocks = 100, | ||
311 | .min_req_rx_blocks = 22, | ||
312 | .tx_min = 27, | ||
313 | }, | ||
314 | .mem_wl128x = { | ||
315 | .num_stations = 1, | ||
316 | .ssid_profiles = 1, | ||
317 | .rx_block_num = 40, | ||
318 | .tx_min_block_num = 40, | ||
319 | .dynamic_memory = 1, | ||
320 | .min_req_tx_blocks = 45, | ||
321 | .min_req_rx_blocks = 22, | ||
322 | .tx_min = 27, | ||
323 | }, | ||
324 | .fm_coex = { | ||
325 | .enable = true, | ||
326 | .swallow_period = 5, | ||
327 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
328 | .n_divider_fref_set_2 = 12, | ||
329 | .m_divider_fref_set_1 = 148, | ||
330 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
331 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
332 | .ldo_stabilization_time = 0xffff, /* default */ | ||
333 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
334 | .swallow_clk_diff = 0xff, /* default */ | ||
335 | }, | ||
336 | .rx_streaming = { | ||
337 | .duration = 150, | ||
338 | .queues = 0x1, | ||
339 | .interval = 20, | ||
340 | .always = 0, | ||
341 | }, | ||
342 | .fwlog = { | ||
343 | .mode = WL12XX_FWLOG_ON_DEMAND, | ||
344 | .mem_blocks = 2, | ||
345 | .severity = 0, | ||
346 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | ||
347 | .output = WL12XX_FWLOG_OUTPUT_HOST, | ||
348 | .threshold = 0, | ||
349 | }, | ||
350 | .hci_io_ds = HCI_IO_DS_6MA, | ||
351 | .rate = { | ||
352 | .rate_retry_score = 32000, | ||
353 | .per_add = 8192, | ||
354 | .per_th1 = 2048, | ||
355 | .per_th2 = 4096, | ||
356 | .max_per = 8100, | ||
357 | .inverse_curiosity_factor = 5, | ||
358 | .tx_fail_low_th = 4, | ||
359 | .tx_fail_high_th = 10, | ||
360 | .per_alpha_shift = 4, | ||
361 | .per_add_shift = 13, | ||
362 | .per_beta1_shift = 10, | ||
363 | .per_beta2_shift = 8, | ||
364 | .rate_check_up = 2, | ||
365 | .rate_check_down = 12, | ||
366 | .rate_retry_policy = { | ||
367 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
368 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
369 | 0x00, 0x00, 0x00, | ||
370 | }, | ||
371 | }, | ||
372 | .hangover = { | ||
373 | .recover_time = 0, | ||
374 | .hangover_period = 20, | ||
375 | .dynamic_mode = 1, | ||
376 | .early_termination_mode = 1, | ||
377 | .max_period = 20, | ||
378 | .min_period = 1, | ||
379 | .increase_delta = 1, | ||
380 | .decrease_delta = 2, | ||
381 | .quiet_time = 4, | ||
382 | .increase_time = 1, | ||
383 | .window_size = 16, | ||
384 | }, | ||
385 | }; | ||
386 | 57 | ||
387 | static char *fwlog_param; | 58 | static char *fwlog_param; |
388 | static bool bug_on_recovery; | 59 | static bool bug_on_recovery; |
60 | static bool no_recovery; | ||
389 | 61 | ||
390 | static void __wl1271_op_remove_interface(struct wl1271 *wl, | 62 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
391 | struct ieee80211_vif *vif, | 63 | struct ieee80211_vif *vif, |
@@ -628,22 +300,8 @@ out: | |||
628 | mutex_unlock(&wl->mutex); | 300 | mutex_unlock(&wl->mutex); |
629 | } | 301 | } |
630 | 302 | ||
631 | static void wl1271_conf_init(struct wl1271 *wl) | 303 | static void wlcore_adjust_conf(struct wl1271 *wl) |
632 | { | 304 | { |
633 | |||
634 | /* | ||
635 | * This function applies the default configuration to the driver. This | ||
636 | * function is invoked upon driver load (spi probe.) | ||
637 | * | ||
638 | * The configuration is stored in a run-time structure in order to | ||
639 | * facilitate for run-time adjustment of any of the parameters. Making | ||
640 | * changes to the configuration structure will apply the new values on | ||
641 | * the next interface up (wl1271_op_start.) | ||
642 | */ | ||
643 | |||
644 | /* apply driver default configuration */ | ||
645 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); | ||
646 | |||
647 | /* Adjust settings according to optional module parameters */ | 305 | /* Adjust settings according to optional module parameters */ |
648 | if (fwlog_param) { | 306 | if (fwlog_param) { |
649 | if (!strcmp(fwlog_param, "continuous")) { | 307 | if (!strcmp(fwlog_param, "continuous")) { |
@@ -666,28 +324,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
666 | { | 324 | { |
667 | int ret; | 325 | int ret; |
668 | 326 | ||
669 | if (wl->chip.id == CHIP_ID_1283_PG20) | 327 | ret = wl->ops->hw_init(wl); |
670 | ret = wl128x_cmd_general_parms(wl); | ||
671 | else | ||
672 | ret = wl1271_cmd_general_parms(wl); | ||
673 | if (ret < 0) | ||
674 | return ret; | ||
675 | |||
676 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
677 | ret = wl128x_cmd_radio_parms(wl); | ||
678 | else | ||
679 | ret = wl1271_cmd_radio_parms(wl); | ||
680 | if (ret < 0) | ||
681 | return ret; | ||
682 | |||
683 | if (wl->chip.id != CHIP_ID_1283_PG20) { | ||
684 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
685 | if (ret < 0) | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | /* Chip-specific initializations */ | ||
690 | ret = wl1271_chip_specific_init(wl); | ||
691 | if (ret < 0) | 328 | if (ret < 0) |
692 | return ret; | 329 | return ret; |
693 | 330 | ||
@@ -750,7 +387,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
750 | 387 | ||
751 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, | 388 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, |
752 | struct wl12xx_vif *wlvif, | 389 | struct wl12xx_vif *wlvif, |
753 | struct wl12xx_fw_status *status) | 390 | struct wl_fw_status *status) |
754 | { | 391 | { |
755 | struct wl1271_link *lnk; | 392 | struct wl1271_link *lnk; |
756 | u32 cur_fw_ps_map; | 393 | u32 cur_fw_ps_map; |
@@ -770,9 +407,10 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
770 | 407 | ||
771 | for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { | 408 | for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { |
772 | lnk = &wl->links[hlid]; | 409 | lnk = &wl->links[hlid]; |
773 | cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts; | 410 | cnt = status->counters.tx_lnk_free_pkts[hlid] - |
411 | lnk->prev_freed_pkts; | ||
774 | 412 | ||
775 | lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; | 413 | lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[hlid]; |
776 | lnk->allocated_pkts -= cnt; | 414 | lnk->allocated_pkts -= cnt; |
777 | 415 | ||
778 | wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, | 416 | wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, |
@@ -781,15 +419,19 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
781 | } | 419 | } |
782 | 420 | ||
783 | static void wl12xx_fw_status(struct wl1271 *wl, | 421 | static void wl12xx_fw_status(struct wl1271 *wl, |
784 | struct wl12xx_fw_status *status) | 422 | struct wl_fw_status *status) |
785 | { | 423 | { |
786 | struct wl12xx_vif *wlvif; | 424 | struct wl12xx_vif *wlvif; |
787 | struct timespec ts; | 425 | struct timespec ts; |
788 | u32 old_tx_blk_count = wl->tx_blocks_available; | 426 | u32 old_tx_blk_count = wl->tx_blocks_available; |
789 | int avail, freed_blocks; | 427 | int avail, freed_blocks; |
790 | int i; | 428 | int i; |
429 | size_t status_len; | ||
430 | |||
431 | status_len = sizeof(*status) + wl->fw_status_priv_len; | ||
791 | 432 | ||
792 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 433 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status, |
434 | status_len, false); | ||
793 | 435 | ||
794 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 436 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
795 | "drv_rx_counter = %d, tx_results_counter = %d)", | 437 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -801,10 +443,10 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
801 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 443 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
802 | /* prevent wrap-around in freed-packets counter */ | 444 | /* prevent wrap-around in freed-packets counter */ |
803 | wl->tx_allocated_pkts[i] -= | 445 | wl->tx_allocated_pkts[i] -= |
804 | (status->tx_released_pkts[i] - | 446 | (status->counters.tx_released_pkts[i] - |
805 | wl->tx_pkts_freed[i]) & 0xff; | 447 | wl->tx_pkts_freed[i]) & 0xff; |
806 | 448 | ||
807 | wl->tx_pkts_freed[i] = status->tx_released_pkts[i]; | 449 | wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i]; |
808 | } | 450 | } |
809 | 451 | ||
810 | /* prevent wrap-around in total blocks counter */ | 452 | /* prevent wrap-around in total blocks counter */ |
@@ -927,6 +569,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
927 | smp_mb__after_clear_bit(); | 569 | smp_mb__after_clear_bit(); |
928 | 570 | ||
929 | wl12xx_fw_status(wl, wl->fw_status); | 571 | wl12xx_fw_status(wl, wl->fw_status); |
572 | |||
573 | wlcore_hw_tx_immediate_compl(wl); | ||
574 | |||
930 | intr = le32_to_cpu(wl->fw_status->intr); | 575 | intr = le32_to_cpu(wl->fw_status->intr); |
931 | intr &= WL1271_INTR_MASK; | 576 | intr &= WL1271_INTR_MASK; |
932 | if (!intr) { | 577 | if (!intr) { |
@@ -963,9 +608,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
963 | } | 608 | } |
964 | 609 | ||
965 | /* check for tx results */ | 610 | /* check for tx results */ |
966 | if (wl->fw_status->tx_results_counter != | 611 | wlcore_hw_tx_delayed_compl(wl); |
967 | (wl->tx_results_count & 0xff)) | ||
968 | wl1271_tx_complete(wl); | ||
969 | 612 | ||
970 | /* Make sure the deferred queues don't get too long */ | 613 | /* Make sure the deferred queues don't get too long */ |
971 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + | 614 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + |
@@ -1046,10 +689,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) | |||
1046 | 689 | ||
1047 | if (plt) { | 690 | if (plt) { |
1048 | fw_type = WL12XX_FW_TYPE_PLT; | 691 | fw_type = WL12XX_FW_TYPE_PLT; |
1049 | if (wl->chip.id == CHIP_ID_1283_PG20) | 692 | fw_name = wl->plt_fw_name; |
1050 | fw_name = WL128X_PLT_FW_NAME; | ||
1051 | else | ||
1052 | fw_name = WL127X_PLT_FW_NAME; | ||
1053 | } else { | 693 | } else { |
1054 | /* | 694 | /* |
1055 | * we can't call wl12xx_get_vif_count() here because | 695 | * we can't call wl12xx_get_vif_count() here because |
@@ -1057,16 +697,10 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) | |||
1057 | */ | 697 | */ |
1058 | if (wl->last_vif_count > 1) { | 698 | if (wl->last_vif_count > 1) { |
1059 | fw_type = WL12XX_FW_TYPE_MULTI; | 699 | fw_type = WL12XX_FW_TYPE_MULTI; |
1060 | if (wl->chip.id == CHIP_ID_1283_PG20) | 700 | fw_name = wl->mr_fw_name; |
1061 | fw_name = WL128X_FW_NAME_MULTI; | ||
1062 | else | ||
1063 | fw_name = WL127X_FW_NAME_MULTI; | ||
1064 | } else { | 701 | } else { |
1065 | fw_type = WL12XX_FW_TYPE_NORMAL; | 702 | fw_type = WL12XX_FW_TYPE_NORMAL; |
1066 | if (wl->chip.id == CHIP_ID_1283_PG20) | 703 | fw_name = wl->sr_fw_name; |
1067 | fw_name = WL128X_FW_NAME_SINGLE; | ||
1068 | else | ||
1069 | fw_name = WL127X_FW_NAME_SINGLE; | ||
1070 | } | 704 | } |
1071 | } | 705 | } |
1072 | 706 | ||
@@ -1173,7 +807,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
1173 | u32 first_addr; | 807 | u32 first_addr; |
1174 | u8 *block; | 808 | u8 *block; |
1175 | 809 | ||
1176 | if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) || | 810 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || |
1177 | (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) || | 811 | (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) || |
1178 | (wl->conf.fwlog.mem_blocks == 0)) | 812 | (wl->conf.fwlog.mem_blocks == 0)) |
1179 | return; | 813 | return; |
@@ -1239,11 +873,20 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1239 | wl12xx_read_fwlog_panic(wl); | 873 | wl12xx_read_fwlog_panic(wl); |
1240 | 874 | ||
1241 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", | 875 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
1242 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | 876 | wl->chip.fw_ver_str, |
877 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY)); | ||
1243 | 878 | ||
1244 | BUG_ON(bug_on_recovery && | 879 | BUG_ON(bug_on_recovery && |
1245 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 880 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
1246 | 881 | ||
882 | if (no_recovery) { | ||
883 | wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); | ||
884 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
885 | goto out_unlock; | ||
886 | } | ||
887 | |||
888 | BUG_ON(bug_on_recovery); | ||
889 | |||
1247 | /* | 890 | /* |
1248 | * Advance security sequence number to overcome potential progress | 891 | * Advance security sequence number to overcome potential progress |
1249 | * in the firmware during recovery. This doens't hurt if the network is | 892 | * in the firmware during recovery. This doens't hurt if the network is |
@@ -1290,10 +933,7 @@ out_unlock: | |||
1290 | 933 | ||
1291 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 934 | static void wl1271_fw_wakeup(struct wl1271 *wl) |
1292 | { | 935 | { |
1293 | u32 elp_reg; | 936 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
1294 | |||
1295 | elp_reg = ELPCTRL_WAKE_UP; | ||
1296 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | ||
1297 | } | 937 | } |
1298 | 938 | ||
1299 | static int wl1271_setup(struct wl1271 *wl) | 939 | static int wl1271_setup(struct wl1271 *wl) |
@@ -1323,7 +963,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl) | |||
1323 | wl1271_io_reset(wl); | 963 | wl1271_io_reset(wl); |
1324 | wl1271_io_init(wl); | 964 | wl1271_io_init(wl); |
1325 | 965 | ||
1326 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); | 966 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1327 | 967 | ||
1328 | /* ELP module wake up */ | 968 | /* ELP module wake up */ |
1329 | wl1271_fw_wakeup(wl); | 969 | wl1271_fw_wakeup(wl); |
@@ -1348,44 +988,18 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | |||
1348 | * negligible, we use the same block size for all different | 988 | * negligible, we use the same block size for all different |
1349 | * chip types. | 989 | * chip types. |
1350 | */ | 990 | */ |
1351 | if (!wl1271_set_block_size(wl)) | 991 | if (wl1271_set_block_size(wl)) |
1352 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | 992 | wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; |
1353 | |||
1354 | switch (wl->chip.id) { | ||
1355 | case CHIP_ID_1271_PG10: | ||
1356 | wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", | ||
1357 | wl->chip.id); | ||
1358 | 993 | ||
1359 | ret = wl1271_setup(wl); | 994 | ret = wl->ops->identify_chip(wl); |
1360 | if (ret < 0) | 995 | if (ret < 0) |
1361 | goto out; | 996 | goto out; |
1362 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | ||
1363 | break; | ||
1364 | |||
1365 | case CHIP_ID_1271_PG20: | ||
1366 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | ||
1367 | wl->chip.id); | ||
1368 | |||
1369 | ret = wl1271_setup(wl); | ||
1370 | if (ret < 0) | ||
1371 | goto out; | ||
1372 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | ||
1373 | break; | ||
1374 | 997 | ||
1375 | case CHIP_ID_1283_PG20: | 998 | /* TODO: make sure the lower driver has set things up correctly */ |
1376 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | ||
1377 | wl->chip.id); | ||
1378 | 999 | ||
1379 | ret = wl1271_setup(wl); | 1000 | ret = wl1271_setup(wl); |
1380 | if (ret < 0) | 1001 | if (ret < 0) |
1381 | goto out; | ||
1382 | break; | ||
1383 | case CHIP_ID_1283_PG10: | ||
1384 | default: | ||
1385 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | ||
1386 | ret = -ENODEV; | ||
1387 | goto out; | 1002 | goto out; |
1388 | } | ||
1389 | 1003 | ||
1390 | ret = wl12xx_fetch_firmware(wl, plt); | 1004 | ret = wl12xx_fetch_firmware(wl, plt); |
1391 | if (ret < 0) | 1005 | if (ret < 0) |
@@ -1425,7 +1039,7 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1425 | if (ret < 0) | 1039 | if (ret < 0) |
1426 | goto power_off; | 1040 | goto power_off; |
1427 | 1041 | ||
1428 | ret = wl1271_boot(wl); | 1042 | ret = wl->ops->boot(wl); |
1429 | if (ret < 0) | 1043 | if (ret < 0) |
1430 | goto power_off; | 1044 | goto power_off; |
1431 | 1045 | ||
@@ -1454,7 +1068,7 @@ irq_disable: | |||
1454 | work function will not do anything.) Also, any other | 1068 | work function will not do anything.) Also, any other |
1455 | possible concurrent operations will fail due to the | 1069 | possible concurrent operations will fail due to the |
1456 | current state, hence the wl1271 struct should be safe. */ | 1070 | current state, hence the wl1271 struct should be safe. */ |
1457 | wl1271_disable_interrupts(wl); | 1071 | wlcore_disable_interrupts(wl); |
1458 | wl1271_flush_deferred_work(wl); | 1072 | wl1271_flush_deferred_work(wl); |
1459 | cancel_work_sync(&wl->netstack_work); | 1073 | cancel_work_sync(&wl->netstack_work); |
1460 | mutex_lock(&wl->mutex); | 1074 | mutex_lock(&wl->mutex); |
@@ -1481,7 +1095,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1481 | * Otherwise, the interrupt handler might be called and exit without | 1095 | * Otherwise, the interrupt handler might be called and exit without |
1482 | * reading the interrupt status. | 1096 | * reading the interrupt status. |
1483 | */ | 1097 | */ |
1484 | wl1271_disable_interrupts(wl); | 1098 | wlcore_disable_interrupts(wl); |
1485 | mutex_lock(&wl->mutex); | 1099 | mutex_lock(&wl->mutex); |
1486 | if (!wl->plt) { | 1100 | if (!wl->plt) { |
1487 | mutex_unlock(&wl->mutex); | 1101 | mutex_unlock(&wl->mutex); |
@@ -1491,7 +1105,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1491 | * may have been disabled when op_stop was called. It will, | 1105 | * may have been disabled when op_stop was called. It will, |
1492 | * however, balance the above call to disable_interrupts(). | 1106 | * however, balance the above call to disable_interrupts(). |
1493 | */ | 1107 | */ |
1494 | wl1271_enable_interrupts(wl); | 1108 | wlcore_enable_interrupts(wl); |
1495 | 1109 | ||
1496 | wl1271_error("cannot power down because not in PLT " | 1110 | wl1271_error("cannot power down because not in PLT " |
1497 | "state: %d", wl->state); | 1111 | "state: %d", wl->state); |
@@ -1652,14 +1266,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1652 | { | 1266 | { |
1653 | int ret = 0; | 1267 | int ret = 0; |
1654 | 1268 | ||
1655 | mutex_lock(&wl->mutex); | ||
1656 | |||
1657 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | 1269 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
1658 | goto out_unlock; | 1270 | goto out; |
1659 | 1271 | ||
1660 | ret = wl1271_ps_elp_wakeup(wl); | 1272 | ret = wl1271_ps_elp_wakeup(wl); |
1661 | if (ret < 0) | 1273 | if (ret < 0) |
1662 | goto out_unlock; | 1274 | goto out; |
1663 | 1275 | ||
1664 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1276 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1665 | wl->conf.conn.suspend_wake_up_event, | 1277 | wl->conf.conn.suspend_wake_up_event, |
@@ -1668,11 +1280,9 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1668 | if (ret < 0) | 1280 | if (ret < 0) |
1669 | wl1271_error("suspend: set wake up conditions failed: %d", ret); | 1281 | wl1271_error("suspend: set wake up conditions failed: %d", ret); |
1670 | 1282 | ||
1671 | |||
1672 | wl1271_ps_elp_sleep(wl); | 1283 | wl1271_ps_elp_sleep(wl); |
1673 | 1284 | ||
1674 | out_unlock: | 1285 | out: |
1675 | mutex_unlock(&wl->mutex); | ||
1676 | return ret; | 1286 | return ret; |
1677 | 1287 | ||
1678 | } | 1288 | } |
@@ -1682,20 +1292,17 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl, | |||
1682 | { | 1292 | { |
1683 | int ret = 0; | 1293 | int ret = 0; |
1684 | 1294 | ||
1685 | mutex_lock(&wl->mutex); | ||
1686 | |||
1687 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) | 1295 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) |
1688 | goto out_unlock; | 1296 | goto out; |
1689 | 1297 | ||
1690 | ret = wl1271_ps_elp_wakeup(wl); | 1298 | ret = wl1271_ps_elp_wakeup(wl); |
1691 | if (ret < 0) | 1299 | if (ret < 0) |
1692 | goto out_unlock; | 1300 | goto out; |
1693 | 1301 | ||
1694 | ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); | 1302 | ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); |
1695 | 1303 | ||
1696 | wl1271_ps_elp_sleep(wl); | 1304 | wl1271_ps_elp_sleep(wl); |
1697 | out_unlock: | 1305 | out: |
1698 | mutex_unlock(&wl->mutex); | ||
1699 | return ret; | 1306 | return ret; |
1700 | 1307 | ||
1701 | } | 1308 | } |
@@ -1720,10 +1327,9 @@ static void wl1271_configure_resume(struct wl1271 *wl, | |||
1720 | if ((!is_ap) && (!is_sta)) | 1327 | if ((!is_ap) && (!is_sta)) |
1721 | return; | 1328 | return; |
1722 | 1329 | ||
1723 | mutex_lock(&wl->mutex); | ||
1724 | ret = wl1271_ps_elp_wakeup(wl); | 1330 | ret = wl1271_ps_elp_wakeup(wl); |
1725 | if (ret < 0) | 1331 | if (ret < 0) |
1726 | goto out; | 1332 | return; |
1727 | 1333 | ||
1728 | if (is_sta) { | 1334 | if (is_sta) { |
1729 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1335 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
@@ -1739,8 +1345,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, | |||
1739 | } | 1345 | } |
1740 | 1346 | ||
1741 | wl1271_ps_elp_sleep(wl); | 1347 | wl1271_ps_elp_sleep(wl); |
1742 | out: | ||
1743 | mutex_unlock(&wl->mutex); | ||
1744 | } | 1348 | } |
1745 | 1349 | ||
1746 | static int wl1271_op_suspend(struct ieee80211_hw *hw, | 1350 | static int wl1271_op_suspend(struct ieee80211_hw *hw, |
@@ -1755,6 +1359,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1755 | 1359 | ||
1756 | wl1271_tx_flush(wl); | 1360 | wl1271_tx_flush(wl); |
1757 | 1361 | ||
1362 | mutex_lock(&wl->mutex); | ||
1758 | wl->wow_enabled = true; | 1363 | wl->wow_enabled = true; |
1759 | wl12xx_for_each_wlvif(wl, wlvif) { | 1364 | wl12xx_for_each_wlvif(wl, wlvif) { |
1760 | ret = wl1271_configure_suspend(wl, wlvif); | 1365 | ret = wl1271_configure_suspend(wl, wlvif); |
@@ -1763,6 +1368,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1763 | return ret; | 1368 | return ret; |
1764 | } | 1369 | } |
1765 | } | 1370 | } |
1371 | mutex_unlock(&wl->mutex); | ||
1766 | /* flush any remaining work */ | 1372 | /* flush any remaining work */ |
1767 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | 1373 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); |
1768 | 1374 | ||
@@ -1770,7 +1376,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1770 | * disable and re-enable interrupts in order to flush | 1376 | * disable and re-enable interrupts in order to flush |
1771 | * the threaded_irq | 1377 | * the threaded_irq |
1772 | */ | 1378 | */ |
1773 | wl1271_disable_interrupts(wl); | 1379 | wlcore_disable_interrupts(wl); |
1774 | 1380 | ||
1775 | /* | 1381 | /* |
1776 | * set suspended flag to avoid triggering a new threaded_irq | 1382 | * set suspended flag to avoid triggering a new threaded_irq |
@@ -1778,7 +1384,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1778 | */ | 1384 | */ |
1779 | set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | 1385 | set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); |
1780 | 1386 | ||
1781 | wl1271_enable_interrupts(wl); | 1387 | wlcore_enable_interrupts(wl); |
1782 | flush_work(&wl->tx_work); | 1388 | flush_work(&wl->tx_work); |
1783 | flush_delayed_work(&wl->elp_work); | 1389 | flush_delayed_work(&wl->elp_work); |
1784 | 1390 | ||
@@ -1810,12 +1416,15 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1810 | wl1271_debug(DEBUG_MAC80211, | 1416 | wl1271_debug(DEBUG_MAC80211, |
1811 | "run postponed irq_work directly"); | 1417 | "run postponed irq_work directly"); |
1812 | wl1271_irq(0, wl); | 1418 | wl1271_irq(0, wl); |
1813 | wl1271_enable_interrupts(wl); | 1419 | wlcore_enable_interrupts(wl); |
1814 | } | 1420 | } |
1421 | |||
1422 | mutex_lock(&wl->mutex); | ||
1815 | wl12xx_for_each_wlvif(wl, wlvif) { | 1423 | wl12xx_for_each_wlvif(wl, wlvif) { |
1816 | wl1271_configure_resume(wl, wlvif); | 1424 | wl1271_configure_resume(wl, wlvif); |
1817 | } | 1425 | } |
1818 | wl->wow_enabled = false; | 1426 | wl->wow_enabled = false; |
1427 | mutex_unlock(&wl->mutex); | ||
1819 | 1428 | ||
1820 | return 0; | 1429 | return 0; |
1821 | } | 1430 | } |
@@ -1851,7 +1460,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1851 | * Otherwise, the interrupt handler might be called and exit without | 1460 | * Otherwise, the interrupt handler might be called and exit without |
1852 | * reading the interrupt status. | 1461 | * reading the interrupt status. |
1853 | */ | 1462 | */ |
1854 | wl1271_disable_interrupts(wl); | 1463 | wlcore_disable_interrupts(wl); |
1855 | mutex_lock(&wl->mutex); | 1464 | mutex_lock(&wl->mutex); |
1856 | if (wl->state == WL1271_STATE_OFF) { | 1465 | if (wl->state == WL1271_STATE_OFF) { |
1857 | mutex_unlock(&wl->mutex); | 1466 | mutex_unlock(&wl->mutex); |
@@ -1861,7 +1470,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1861 | * may have been disabled when op_stop was called. It will, | 1470 | * may have been disabled when op_stop was called. It will, |
1862 | * however, balance the above call to disable_interrupts(). | 1471 | * however, balance the above call to disable_interrupts(). |
1863 | */ | 1472 | */ |
1864 | wl1271_enable_interrupts(wl); | 1473 | wlcore_enable_interrupts(wl); |
1865 | return; | 1474 | return; |
1866 | } | 1475 | } |
1867 | 1476 | ||
@@ -1894,7 +1503,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1894 | wl->tx_results_count = 0; | 1503 | wl->tx_results_count = 0; |
1895 | wl->tx_packets_count = 0; | 1504 | wl->tx_packets_count = 0; |
1896 | wl->time_offset = 0; | 1505 | wl->time_offset = 0; |
1897 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | ||
1898 | wl->ap_fw_ps_map = 0; | 1506 | wl->ap_fw_ps_map = 0; |
1899 | wl->ap_ps_map = 0; | 1507 | wl->ap_ps_map = 0; |
1900 | wl->sched_scanning = false; | 1508 | wl->sched_scanning = false; |
@@ -2067,7 +1675,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) | |||
2067 | if (ret < 0) | 1675 | if (ret < 0) |
2068 | goto power_off; | 1676 | goto power_off; |
2069 | 1677 | ||
2070 | ret = wl1271_boot(wl); | 1678 | ret = wl->ops->boot(wl); |
2071 | if (ret < 0) | 1679 | if (ret < 0) |
2072 | goto power_off; | 1680 | goto power_off; |
2073 | 1681 | ||
@@ -2087,7 +1695,7 @@ irq_disable: | |||
2087 | work function will not do anything.) Also, any other | 1695 | work function will not do anything.) Also, any other |
2088 | possible concurrent operations will fail due to the | 1696 | possible concurrent operations will fail due to the |
2089 | current state, hence the wl1271 struct should be safe. */ | 1697 | current state, hence the wl1271 struct should be safe. */ |
2090 | wl1271_disable_interrupts(wl); | 1698 | wlcore_disable_interrupts(wl); |
2091 | wl1271_flush_deferred_work(wl); | 1699 | wl1271_flush_deferred_work(wl); |
2092 | cancel_work_sync(&wl->netstack_work); | 1700 | cancel_work_sync(&wl->netstack_work); |
2093 | mutex_lock(&wl->mutex); | 1701 | mutex_lock(&wl->mutex); |
@@ -2360,10 +1968,12 @@ deinit: | |||
2360 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) | 1968 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) |
2361 | wl12xx_free_rate_policy(wl, | 1969 | wl12xx_free_rate_policy(wl, |
2362 | &wlvif->ap.ucast_rate_idx[i]); | 1970 | &wlvif->ap.ucast_rate_idx[i]); |
1971 | wl1271_free_ap_keys(wl, wlvif); | ||
2363 | } | 1972 | } |
2364 | 1973 | ||
1974 | dev_kfree_skb(wlvif->probereq); | ||
1975 | wlvif->probereq = NULL; | ||
2365 | wl12xx_tx_reset_wlvif(wl, wlvif); | 1976 | wl12xx_tx_reset_wlvif(wl, wlvif); |
2366 | wl1271_free_ap_keys(wl, wlvif); | ||
2367 | if (wl->last_wlvif == wlvif) | 1977 | if (wl->last_wlvif == wlvif) |
2368 | wl->last_wlvif = NULL; | 1978 | wl->last_wlvif = NULL; |
2369 | list_del(&wlvif->list); | 1979 | list_del(&wlvif->list); |
@@ -2946,6 +2556,17 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2946 | int ret; | 2556 | int ret; |
2947 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 2557 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
2948 | 2558 | ||
2559 | /* | ||
2560 | * A role set to GEM cipher requires different Tx settings (namely | ||
2561 | * spare blocks). Note when we are in this mode so the HW can adjust. | ||
2562 | */ | ||
2563 | if (key_type == KEY_GEM) { | ||
2564 | if (action == KEY_ADD_OR_REPLACE) | ||
2565 | wlvif->is_gem = true; | ||
2566 | else if (action == KEY_REMOVE) | ||
2567 | wlvif->is_gem = false; | ||
2568 | } | ||
2569 | |||
2949 | if (is_ap) { | 2570 | if (is_ap) { |
2950 | struct wl1271_station *wl_sta; | 2571 | struct wl1271_station *wl_sta; |
2951 | u8 hlid; | 2572 | u8 hlid; |
@@ -2984,17 +2605,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2984 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 2605 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
2985 | }; | 2606 | }; |
2986 | 2607 | ||
2987 | /* | ||
2988 | * A STA set to GEM cipher requires 2 tx spare blocks. | ||
2989 | * Return to default value when GEM cipher key is removed | ||
2990 | */ | ||
2991 | if (key_type == KEY_GEM) { | ||
2992 | if (action == KEY_ADD_OR_REPLACE) | ||
2993 | wl->tx_spare_blocks = 2; | ||
2994 | else if (action == KEY_REMOVE) | ||
2995 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | ||
2996 | } | ||
2997 | |||
2998 | addr = sta ? sta->addr : bcast_addr; | 2608 | addr = sta ? sta->addr : bcast_addr; |
2999 | 2609 | ||
3000 | if (is_zero_ether_addr(addr)) { | 2610 | if (is_zero_ether_addr(addr)) { |
@@ -3791,8 +3401,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3791 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; | 3401 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; |
3792 | } | 3402 | } |
3793 | 3403 | ||
3794 | if (changed & BSS_CHANGED_BSSID && | 3404 | if (changed & BSS_CHANGED_BSSID) |
3795 | (is_ibss || bss_conf->assoc)) | ||
3796 | if (!is_zero_ether_addr(bss_conf->bssid)) { | 3405 | if (!is_zero_ether_addr(bss_conf->bssid)) { |
3797 | ret = wl12xx_cmd_build_null_data(wl, wlvif); | 3406 | ret = wl12xx_cmd_build_null_data(wl, wlvif); |
3798 | if (ret < 0) | 3407 | if (ret < 0) |
@@ -3801,9 +3410,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3801 | ret = wl1271_build_qos_null_data(wl, vif); | 3410 | ret = wl1271_build_qos_null_data(wl, vif); |
3802 | if (ret < 0) | 3411 | if (ret < 0) |
3803 | goto out; | 3412 | goto out; |
3804 | |||
3805 | /* Need to update the BSSID (for filtering etc) */ | ||
3806 | do_join = true; | ||
3807 | } | 3413 | } |
3808 | 3414 | ||
3809 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { | 3415 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { |
@@ -3830,6 +3436,7 @@ sta_not_found: | |||
3830 | int ieoffset; | 3436 | int ieoffset; |
3831 | wlvif->aid = bss_conf->aid; | 3437 | wlvif->aid = bss_conf->aid; |
3832 | wlvif->beacon_int = bss_conf->beacon_int; | 3438 | wlvif->beacon_int = bss_conf->beacon_int; |
3439 | do_join = true; | ||
3833 | set_assoc = true; | 3440 | set_assoc = true; |
3834 | 3441 | ||
3835 | /* | 3442 | /* |
@@ -4662,60 +4269,12 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
4662 | { .hw_value = 14, .center_freq = 2484, .max_power = 25 }, | 4269 | { .hw_value = 14, .center_freq = 2484, .max_power = 25 }, |
4663 | }; | 4270 | }; |
4664 | 4271 | ||
4665 | /* mapping to indexes for wl1271_rates */ | ||
4666 | static const u8 wl1271_rate_to_idx_2ghz[] = { | ||
4667 | /* MCS rates are used only with 11n */ | ||
4668 | 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
4669 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
4670 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
4671 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
4672 | 4, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
4673 | 3, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
4674 | 2, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
4675 | 1, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
4676 | 0, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
4677 | |||
4678 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
4679 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
4680 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
4681 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
4682 | |||
4683 | /* TI-specific rate */ | ||
4684 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
4685 | |||
4686 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
4687 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
4688 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
4689 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
4690 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
4691 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
4692 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
4693 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
4694 | }; | ||
4695 | |||
4696 | /* 11n STA capabilities */ | ||
4697 | #define HW_RX_HIGHEST_RATE 72 | ||
4698 | |||
4699 | #define WL12XX_HT_CAP { \ | ||
4700 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ | ||
4701 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ | ||
4702 | .ht_supported = true, \ | ||
4703 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ | ||
4704 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | ||
4705 | .mcs = { \ | ||
4706 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ | ||
4707 | .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \ | ||
4708 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
4709 | }, \ | ||
4710 | } | ||
4711 | |||
4712 | /* can't be const, mac80211 writes to this */ | 4272 | /* can't be const, mac80211 writes to this */ |
4713 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 4273 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
4714 | .channels = wl1271_channels, | 4274 | .channels = wl1271_channels, |
4715 | .n_channels = ARRAY_SIZE(wl1271_channels), | 4275 | .n_channels = ARRAY_SIZE(wl1271_channels), |
4716 | .bitrates = wl1271_rates, | 4276 | .bitrates = wl1271_rates, |
4717 | .n_bitrates = ARRAY_SIZE(wl1271_rates), | 4277 | .n_bitrates = ARRAY_SIZE(wl1271_rates), |
4718 | .ht_cap = WL12XX_HT_CAP, | ||
4719 | }; | 4278 | }; |
4720 | 4279 | ||
4721 | /* 5 GHz data rates for WL1273 */ | 4280 | /* 5 GHz data rates for WL1273 */ |
@@ -4784,48 +4343,11 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
4784 | { .hw_value = 165, .center_freq = 5825, .max_power = 25 }, | 4343 | { .hw_value = 165, .center_freq = 5825, .max_power = 25 }, |
4785 | }; | 4344 | }; |
4786 | 4345 | ||
4787 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
4788 | static const u8 wl1271_rate_to_idx_5ghz[] = { | ||
4789 | /* MCS rates are used only with 11n */ | ||
4790 | 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ | ||
4791 | 7, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
4792 | 6, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
4793 | 5, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
4794 | 4, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
4795 | 3, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
4796 | 2, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
4797 | 1, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
4798 | 0, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
4799 | |||
4800 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
4801 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
4802 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
4803 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
4804 | |||
4805 | /* TI-specific rate */ | ||
4806 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
4807 | |||
4808 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
4809 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
4810 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
4811 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
4812 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
4813 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
4814 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
4815 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
4816 | }; | ||
4817 | |||
4818 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 4346 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
4819 | .channels = wl1271_channels_5ghz, | 4347 | .channels = wl1271_channels_5ghz, |
4820 | .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), | 4348 | .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), |
4821 | .bitrates = wl1271_rates_5ghz, | 4349 | .bitrates = wl1271_rates_5ghz, |
4822 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 4350 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
4823 | .ht_cap = WL12XX_HT_CAP, | ||
4824 | }; | ||
4825 | |||
4826 | static const u8 *wl1271_band_rate_to_idx[] = { | ||
4827 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
4828 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
4829 | }; | 4351 | }; |
4830 | 4352 | ||
4831 | static const struct ieee80211_ops wl1271_ops = { | 4353 | static const struct ieee80211_ops wl1271_ops = { |
@@ -4862,18 +4384,18 @@ static const struct ieee80211_ops wl1271_ops = { | |||
4862 | }; | 4384 | }; |
4863 | 4385 | ||
4864 | 4386 | ||
4865 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band) | 4387 | u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band) |
4866 | { | 4388 | { |
4867 | u8 idx; | 4389 | u8 idx; |
4868 | 4390 | ||
4869 | BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | 4391 | BUG_ON(band >= 2); |
4870 | 4392 | ||
4871 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | 4393 | if (unlikely(rate >= wl->hw_tx_rate_tbl_size)) { |
4872 | wl1271_error("Illegal RX rate from HW: %d", rate); | 4394 | wl1271_error("Illegal RX rate from HW: %d", rate); |
4873 | return 0; | 4395 | return 0; |
4874 | } | 4396 | } |
4875 | 4397 | ||
4876 | idx = wl1271_band_rate_to_idx[band][rate]; | 4398 | idx = wl->band_rate_to_idx[band][rate]; |
4877 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | 4399 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { |
4878 | wl1271_error("Unsupported RX rate from HW: %d", rate); | 4400 | wl1271_error("Unsupported RX rate from HW: %d", rate); |
4879 | return 0; | 4401 | return 0; |
@@ -5027,34 +4549,6 @@ static struct bin_attribute fwlog_attr = { | |||
5027 | .read = wl1271_sysfs_read_fwlog, | 4549 | .read = wl1271_sysfs_read_fwlog, |
5028 | }; | 4550 | }; |
5029 | 4551 | ||
5030 | static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | ||
5031 | { | ||
5032 | bool supported = false; | ||
5033 | u8 major, minor; | ||
5034 | |||
5035 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
5036 | major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
5037 | minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); | ||
5038 | |||
5039 | /* in wl128x we have the MAC address if the PG is >= (2, 1) */ | ||
5040 | if (major > 2 || (major == 2 && minor >= 1)) | ||
5041 | supported = true; | ||
5042 | } else { | ||
5043 | major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver); | ||
5044 | minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver); | ||
5045 | |||
5046 | /* in wl127x we have the MAC address if the PG is >= (3, 1) */ | ||
5047 | if (major == 3 && minor >= 1) | ||
5048 | supported = true; | ||
5049 | } | ||
5050 | |||
5051 | wl1271_debug(DEBUG_PROBE, | ||
5052 | "PG Ver major = %d minor = %d, MAC %s present", | ||
5053 | major, minor, supported ? "is" : "is not"); | ||
5054 | |||
5055 | return supported; | ||
5056 | } | ||
5057 | |||
5058 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | 4552 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, |
5059 | u32 oui, u32 nic, int n) | 4553 | u32 oui, u32 nic, int n) |
5060 | { | 4554 | { |
@@ -5080,47 +4574,23 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | |||
5080 | wl->hw->wiphy->addresses = wl->addresses; | 4574 | wl->hw->wiphy->addresses = wl->addresses; |
5081 | } | 4575 | } |
5082 | 4576 | ||
5083 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | ||
5084 | { | ||
5085 | u32 mac1, mac2; | ||
5086 | |||
5087 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); | ||
5088 | |||
5089 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | ||
5090 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | ||
5091 | |||
5092 | /* these are the two parts of the BD_ADDR */ | ||
5093 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | ||
5094 | ((mac1 & 0xff000000) >> 24); | ||
5095 | wl->fuse_nic_addr = mac1 & 0xffffff; | ||
5096 | |||
5097 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); | ||
5098 | } | ||
5099 | |||
5100 | static int wl12xx_get_hw_info(struct wl1271 *wl) | 4577 | static int wl12xx_get_hw_info(struct wl1271 *wl) |
5101 | { | 4578 | { |
5102 | int ret; | 4579 | int ret; |
5103 | u32 die_info; | ||
5104 | 4580 | ||
5105 | ret = wl12xx_set_power_on(wl); | 4581 | ret = wl12xx_set_power_on(wl); |
5106 | if (ret < 0) | 4582 | if (ret < 0) |
5107 | goto out; | 4583 | goto out; |
5108 | 4584 | ||
5109 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); | 4585 | wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); |
5110 | 4586 | ||
5111 | if (wl->chip.id == CHIP_ID_1283_PG20) | 4587 | wl->fuse_oui_addr = 0; |
5112 | die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | 4588 | wl->fuse_nic_addr = 0; |
5113 | else | ||
5114 | die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | ||
5115 | 4589 | ||
5116 | wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | 4590 | wl->hw_pg_ver = wl->ops->get_pg_ver(wl); |
5117 | 4591 | ||
5118 | if (!wl12xx_mac_in_fuse(wl)) { | 4592 | if (wl->ops->get_mac) |
5119 | wl->fuse_oui_addr = 0; | 4593 | wl->ops->get_mac(wl); |
5120 | wl->fuse_nic_addr = 0; | ||
5121 | } else { | ||
5122 | wl12xx_get_fuse_mac(wl); | ||
5123 | } | ||
5124 | 4594 | ||
5125 | wl1271_power_off(wl); | 4595 | wl1271_power_off(wl); |
5126 | out: | 4596 | out: |
@@ -5255,8 +4725,12 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5255 | */ | 4725 | */ |
5256 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, | 4726 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, |
5257 | sizeof(wl1271_band_2ghz)); | 4727 | sizeof(wl1271_band_2ghz)); |
4728 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, &wl->ht_cap, | ||
4729 | sizeof(wl->ht_cap)); | ||
5258 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, | 4730 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, |
5259 | sizeof(wl1271_band_5ghz)); | 4731 | sizeof(wl1271_band_5ghz)); |
4732 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, &wl->ht_cap, | ||
4733 | sizeof(wl->ht_cap)); | ||
5260 | 4734 | ||
5261 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 4735 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
5262 | &wl->bands[IEEE80211_BAND_2GHZ]; | 4736 | &wl->bands[IEEE80211_BAND_2GHZ]; |
@@ -5280,14 +4754,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5280 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | 4754 | wl->hw->sta_data_size = sizeof(struct wl1271_station); |
5281 | wl->hw->vif_data_size = sizeof(struct wl12xx_vif); | 4755 | wl->hw->vif_data_size = sizeof(struct wl12xx_vif); |
5282 | 4756 | ||
5283 | wl->hw->max_rx_aggregation_subframes = 8; | 4757 | wl->hw->max_rx_aggregation_subframes = wl->conf.ht.rx_ba_win_size; |
5284 | 4758 | ||
5285 | return 0; | 4759 | return 0; |
5286 | } | 4760 | } |
5287 | 4761 | ||
5288 | #define WL1271_DEFAULT_CHANNEL 0 | 4762 | #define WL1271_DEFAULT_CHANNEL 0 |
5289 | 4763 | ||
5290 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 4764 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) |
5291 | { | 4765 | { |
5292 | struct ieee80211_hw *hw; | 4766 | struct ieee80211_hw *hw; |
5293 | struct wl1271 *wl; | 4767 | struct wl1271 *wl; |
@@ -5306,6 +4780,13 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5306 | wl = hw->priv; | 4780 | wl = hw->priv; |
5307 | memset(wl, 0, sizeof(*wl)); | 4781 | memset(wl, 0, sizeof(*wl)); |
5308 | 4782 | ||
4783 | wl->priv = kzalloc(priv_size, GFP_KERNEL); | ||
4784 | if (!wl->priv) { | ||
4785 | wl1271_error("could not alloc wl priv"); | ||
4786 | ret = -ENOMEM; | ||
4787 | goto err_priv_alloc; | ||
4788 | } | ||
4789 | |||
5309 | INIT_LIST_HEAD(&wl->wlvif_list); | 4790 | INIT_LIST_HEAD(&wl->wlvif_list); |
5310 | 4791 | ||
5311 | wl->hw = hw; | 4792 | wl->hw = hw; |
@@ -5342,7 +4823,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5342 | wl->quirks = 0; | 4823 | wl->quirks = 0; |
5343 | wl->platform_quirks = 0; | 4824 | wl->platform_quirks = 0; |
5344 | wl->sched_scanning = false; | 4825 | wl->sched_scanning = false; |
5345 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | ||
5346 | wl->system_hlid = WL12XX_SYSTEM_HLID; | 4826 | wl->system_hlid = WL12XX_SYSTEM_HLID; |
5347 | wl->active_sta_count = 0; | 4827 | wl->active_sta_count = 0; |
5348 | wl->fwlog_size = 0; | 4828 | wl->fwlog_size = 0; |
@@ -5352,7 +4832,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5352 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); | 4832 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); |
5353 | 4833 | ||
5354 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 4834 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
5355 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 4835 | for (i = 0; i < wl->num_tx_desc; i++) |
5356 | wl->tx_frames[i] = NULL; | 4836 | wl->tx_frames[i] = NULL; |
5357 | 4837 | ||
5358 | spin_lock_init(&wl->wl_lock); | 4838 | spin_lock_init(&wl->wl_lock); |
@@ -5361,9 +4841,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5361 | wl->fw_type = WL12XX_FW_TYPE_NONE; | 4841 | wl->fw_type = WL12XX_FW_TYPE_NONE; |
5362 | mutex_init(&wl->mutex); | 4842 | mutex_init(&wl->mutex); |
5363 | 4843 | ||
5364 | /* Apply default driver configuration. */ | ||
5365 | wl1271_conf_init(wl); | ||
5366 | |||
5367 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | 4844 | order = get_order(WL1271_AGGR_BUFFER_SIZE); |
5368 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | 4845 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); |
5369 | if (!wl->aggr_buf) { | 4846 | if (!wl->aggr_buf) { |
@@ -5384,8 +4861,17 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
5384 | goto err_dummy_packet; | 4861 | goto err_dummy_packet; |
5385 | } | 4862 | } |
5386 | 4863 | ||
4864 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_DMA); | ||
4865 | if (!wl->mbox) { | ||
4866 | ret = -ENOMEM; | ||
4867 | goto err_fwlog; | ||
4868 | } | ||
4869 | |||
5387 | return hw; | 4870 | return hw; |
5388 | 4871 | ||
4872 | err_fwlog: | ||
4873 | free_page((unsigned long)wl->fwlog); | ||
4874 | |||
5389 | err_dummy_packet: | 4875 | err_dummy_packet: |
5390 | dev_kfree_skb(wl->dummy_packet); | 4876 | dev_kfree_skb(wl->dummy_packet); |
5391 | 4877 | ||
@@ -5397,14 +4883,18 @@ err_wq: | |||
5397 | 4883 | ||
5398 | err_hw: | 4884 | err_hw: |
5399 | wl1271_debugfs_exit(wl); | 4885 | wl1271_debugfs_exit(wl); |
4886 | kfree(wl->priv); | ||
4887 | |||
4888 | err_priv_alloc: | ||
5400 | ieee80211_free_hw(hw); | 4889 | ieee80211_free_hw(hw); |
5401 | 4890 | ||
5402 | err_hw_alloc: | 4891 | err_hw_alloc: |
5403 | 4892 | ||
5404 | return ERR_PTR(ret); | 4893 | return ERR_PTR(ret); |
5405 | } | 4894 | } |
4895 | EXPORT_SYMBOL_GPL(wlcore_alloc_hw); | ||
5406 | 4896 | ||
5407 | static int wl1271_free_hw(struct wl1271 *wl) | 4897 | int wlcore_free_hw(struct wl1271 *wl) |
5408 | { | 4898 | { |
5409 | /* Unblock any fwlog readers */ | 4899 | /* Unblock any fwlog readers */ |
5410 | mutex_lock(&wl->mutex); | 4900 | mutex_lock(&wl->mutex); |
@@ -5434,10 +4924,12 @@ static int wl1271_free_hw(struct wl1271 *wl) | |||
5434 | kfree(wl->tx_res_if); | 4924 | kfree(wl->tx_res_if); |
5435 | destroy_workqueue(wl->freezable_wq); | 4925 | destroy_workqueue(wl->freezable_wq); |
5436 | 4926 | ||
4927 | kfree(wl->priv); | ||
5437 | ieee80211_free_hw(wl->hw); | 4928 | ieee80211_free_hw(wl->hw); |
5438 | 4929 | ||
5439 | return 0; | 4930 | return 0; |
5440 | } | 4931 | } |
4932 | EXPORT_SYMBOL_GPL(wlcore_free_hw); | ||
5441 | 4933 | ||
5442 | static irqreturn_t wl12xx_hardirq(int irq, void *cookie) | 4934 | static irqreturn_t wl12xx_hardirq(int irq, void *cookie) |
5443 | { | 4935 | { |
@@ -5468,22 +4960,22 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie) | |||
5468 | return IRQ_WAKE_THREAD; | 4960 | return IRQ_WAKE_THREAD; |
5469 | } | 4961 | } |
5470 | 4962 | ||
5471 | static int __devinit wl12xx_probe(struct platform_device *pdev) | 4963 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) |
5472 | { | 4964 | { |
5473 | struct wl12xx_platform_data *pdata = pdev->dev.platform_data; | 4965 | struct wl12xx_platform_data *pdata = pdev->dev.platform_data; |
5474 | struct ieee80211_hw *hw; | ||
5475 | struct wl1271 *wl; | ||
5476 | unsigned long irqflags; | 4966 | unsigned long irqflags; |
5477 | int ret = -ENODEV; | 4967 | int ret; |
5478 | 4968 | ||
5479 | hw = wl1271_alloc_hw(); | 4969 | if (!wl->ops || !wl->ptable) { |
5480 | if (IS_ERR(hw)) { | 4970 | ret = -EINVAL; |
5481 | wl1271_error("can't allocate hw"); | 4971 | goto out_free_hw; |
5482 | ret = PTR_ERR(hw); | ||
5483 | goto out; | ||
5484 | } | 4972 | } |
5485 | 4973 | ||
5486 | wl = hw->priv; | 4974 | BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS); |
4975 | |||
4976 | /* adjust some runtime configuration parameters */ | ||
4977 | wlcore_adjust_conf(wl); | ||
4978 | |||
5487 | wl->irq = platform_get_irq(pdev, 0); | 4979 | wl->irq = platform_get_irq(pdev, 0); |
5488 | wl->ref_clock = pdata->board_ref_clock; | 4980 | wl->ref_clock = pdata->board_ref_clock; |
5489 | wl->tcxo_clock = pdata->board_tcxo_clock; | 4981 | wl->tcxo_clock = pdata->board_tcxo_clock; |
@@ -5512,7 +5004,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) | |||
5512 | wl->irq_wake_enabled = true; | 5004 | wl->irq_wake_enabled = true; |
5513 | device_init_wakeup(wl->dev, 1); | 5005 | device_init_wakeup(wl->dev, 1); |
5514 | if (pdata->pwr_in_suspend) | 5006 | if (pdata->pwr_in_suspend) |
5515 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | 5007 | wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; |
5516 | 5008 | ||
5517 | } | 5009 | } |
5518 | disable_irq(wl->irq); | 5010 | disable_irq(wl->irq); |
@@ -5546,7 +5038,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) | |||
5546 | goto out_hw_pg_ver; | 5038 | goto out_hw_pg_ver; |
5547 | } | 5039 | } |
5548 | 5040 | ||
5549 | return 0; | 5041 | goto out; |
5550 | 5042 | ||
5551 | out_hw_pg_ver: | 5043 | out_hw_pg_ver: |
5552 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); | 5044 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); |
@@ -5558,13 +5050,14 @@ out_irq: | |||
5558 | free_irq(wl->irq, wl); | 5050 | free_irq(wl->irq, wl); |
5559 | 5051 | ||
5560 | out_free_hw: | 5052 | out_free_hw: |
5561 | wl1271_free_hw(wl); | 5053 | wlcore_free_hw(wl); |
5562 | 5054 | ||
5563 | out: | 5055 | out: |
5564 | return ret; | 5056 | return ret; |
5565 | } | 5057 | } |
5058 | EXPORT_SYMBOL_GPL(wlcore_probe); | ||
5566 | 5059 | ||
5567 | static int __devexit wl12xx_remove(struct platform_device *pdev) | 5060 | int __devexit wlcore_remove(struct platform_device *pdev) |
5568 | { | 5061 | { |
5569 | struct wl1271 *wl = platform_get_drvdata(pdev); | 5062 | struct wl1271 *wl = platform_get_drvdata(pdev); |
5570 | 5063 | ||
@@ -5574,38 +5067,11 @@ static int __devexit wl12xx_remove(struct platform_device *pdev) | |||
5574 | } | 5067 | } |
5575 | wl1271_unregister_hw(wl); | 5068 | wl1271_unregister_hw(wl); |
5576 | free_irq(wl->irq, wl); | 5069 | free_irq(wl->irq, wl); |
5577 | wl1271_free_hw(wl); | 5070 | wlcore_free_hw(wl); |
5578 | 5071 | ||
5579 | return 0; | 5072 | return 0; |
5580 | } | 5073 | } |
5581 | 5074 | EXPORT_SYMBOL_GPL(wlcore_remove); | |
5582 | static const struct platform_device_id wl12xx_id_table[] __devinitconst = { | ||
5583 | { "wl12xx", 0 }, | ||
5584 | { } /* Terminating Entry */ | ||
5585 | }; | ||
5586 | MODULE_DEVICE_TABLE(platform, wl12xx_id_table); | ||
5587 | |||
5588 | static struct platform_driver wl12xx_driver = { | ||
5589 | .probe = wl12xx_probe, | ||
5590 | .remove = __devexit_p(wl12xx_remove), | ||
5591 | .id_table = wl12xx_id_table, | ||
5592 | .driver = { | ||
5593 | .name = "wl12xx_driver", | ||
5594 | .owner = THIS_MODULE, | ||
5595 | } | ||
5596 | }; | ||
5597 | |||
5598 | static int __init wl12xx_init(void) | ||
5599 | { | ||
5600 | return platform_driver_register(&wl12xx_driver); | ||
5601 | } | ||
5602 | module_init(wl12xx_init); | ||
5603 | |||
5604 | static void __exit wl12xx_exit(void) | ||
5605 | { | ||
5606 | platform_driver_unregister(&wl12xx_driver); | ||
5607 | } | ||
5608 | module_exit(wl12xx_exit); | ||
5609 | 5075 | ||
5610 | u32 wl12xx_debug_level = DEBUG_NONE; | 5076 | u32 wl12xx_debug_level = DEBUG_NONE; |
5611 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); | 5077 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); |
@@ -5619,6 +5085,9 @@ MODULE_PARM_DESC(fwlog, | |||
5619 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); | 5085 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); |
5620 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); | 5086 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); |
5621 | 5087 | ||
5088 | module_param(no_recovery, bool, S_IRUSR | S_IWUSR); | ||
5089 | MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); | ||
5090 | |||
5622 | MODULE_LICENSE("GPL"); | 5091 | MODULE_LICENSE("GPL"); |
5623 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 5092 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
5624 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 5093 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 78f598b4f97b..756eee2257b4 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "reg.h" | ||
25 | #include "ps.h" | 24 | #include "ps.h" |
26 | #include "io.h" | 25 | #include "io.h" |
27 | #include "tx.h" | 26 | #include "tx.h" |
@@ -62,7 +61,7 @@ void wl1271_elp_work(struct work_struct *work) | |||
62 | } | 61 | } |
63 | 62 | ||
64 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 63 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
65 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 64 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); |
66 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); | 65 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
67 | 66 | ||
68 | out: | 67 | out: |
@@ -74,6 +73,9 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
74 | { | 73 | { |
75 | struct wl12xx_vif *wlvif; | 74 | struct wl12xx_vif *wlvif; |
76 | 75 | ||
76 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
77 | return; | ||
78 | |||
77 | /* we shouldn't get consecutive sleep requests */ | 79 | /* we shouldn't get consecutive sleep requests */ |
78 | if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) | 80 | if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) |
79 | return; | 81 | return; |
@@ -125,7 +127,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
125 | wl->elp_compl = &compl; | 127 | wl->elp_compl = &compl; |
126 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 128 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
127 | 129 | ||
128 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 130 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
129 | 131 | ||
130 | if (!pending) { | 132 | if (!pending) { |
131 | ret = wait_for_completion_timeout( | 133 | ret = wait_for_completion_timeout( |
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/ti/wlcore/ps.h index 5f19d4fbbf27..de4f9da8ed26 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/ti/wlcore/ps.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef __PS_H__ | 24 | #ifndef __PS_H__ |
25 | #define __PS_H__ | 25 | #define __PS_H__ |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore.h" |
28 | #include "acx.h" | 28 | #include "acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index cfa6071704c5..89bd9385e90b 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -24,34 +24,36 @@ | |||
24 | #include <linux/gfp.h> | 24 | #include <linux/gfp.h> |
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore.h" |
28 | #include "debug.h" | 28 | #include "debug.h" |
29 | #include "acx.h" | 29 | #include "acx.h" |
30 | #include "reg.h" | ||
31 | #include "rx.h" | 30 | #include "rx.h" |
32 | #include "tx.h" | 31 | #include "tx.h" |
33 | #include "io.h" | 32 | #include "io.h" |
33 | #include "hw_ops.h" | ||
34 | 34 | ||
35 | static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, | 35 | /* |
36 | u32 drv_rx_counter) | 36 | * TODO: this is here just for now, it must be removed when the data |
37 | { | 37 | * operations are in place. |
38 | return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & | 38 | */ |
39 | RX_MEM_BLOCK_MASK; | 39 | #include "../wl12xx/reg.h" |
40 | } | ||
41 | 40 | ||
42 | static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status, | 41 | static u32 wlcore_rx_get_buf_size(struct wl1271 *wl, |
43 | u32 drv_rx_counter) | 42 | u32 rx_pkt_desc) |
44 | { | 43 | { |
45 | return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & | 44 | if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) |
46 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | 45 | return (rx_pkt_desc & ALIGNED_RX_BUF_SIZE_MASK) >> |
46 | ALIGNED_RX_BUF_SIZE_SHIFT; | ||
47 | |||
48 | return (rx_pkt_desc & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | ||
47 | } | 49 | } |
48 | 50 | ||
49 | static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status, | 51 | static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len) |
50 | u32 drv_rx_counter) | ||
51 | { | 52 | { |
52 | /* Convert the value to bool */ | 53 | if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) |
53 | return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & | 54 | return ALIGN(pkt_len, WL12XX_BUS_BLOCK_SIZE); |
54 | RX_BUF_UNALIGNED_PAYLOAD); | 55 | |
56 | return pkt_len; | ||
55 | } | 57 | } |
56 | 58 | ||
57 | static void wl1271_rx_status(struct wl1271 *wl, | 59 | static void wl1271_rx_status(struct wl1271 *wl, |
@@ -66,10 +68,10 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
66 | else | 68 | else |
67 | status->band = IEEE80211_BAND_5GHZ; | 69 | status->band = IEEE80211_BAND_5GHZ; |
68 | 70 | ||
69 | status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); | 71 | status->rate_idx = wlcore_rate_to_idx(wl, desc->rate, status->band); |
70 | 72 | ||
71 | /* 11n support */ | 73 | /* 11n support */ |
72 | if (desc->rate <= CONF_HW_RXTX_RATE_MCS0) | 74 | if (desc->rate <= wl->hw_min_ht_rate) |
73 | status->flag |= RX_FLAG_HT; | 75 | status->flag |= RX_FLAG_HT; |
74 | 76 | ||
75 | status->signal = desc->rssi; | 77 | status->signal = desc->rssi; |
@@ -98,7 +100,7 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
98 | } | 100 | } |
99 | 101 | ||
100 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | 102 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, |
101 | bool unaligned, u8 *hlid) | 103 | enum wl_rx_buf_align rx_align, u8 *hlid) |
102 | { | 104 | { |
103 | struct wl1271_rx_descriptor *desc; | 105 | struct wl1271_rx_descriptor *desc; |
104 | struct sk_buff *skb; | 106 | struct sk_buff *skb; |
@@ -106,8 +108,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
106 | u8 *buf; | 108 | u8 *buf; |
107 | u8 beacon = 0; | 109 | u8 beacon = 0; |
108 | u8 is_data = 0; | 110 | u8 is_data = 0; |
109 | u8 reserved = unaligned ? NET_IP_ALIGN : 0; | 111 | u8 reserved = 0; |
110 | u16 seq_num; | 112 | u16 seq_num; |
113 | u32 pkt_data_len; | ||
111 | 114 | ||
112 | /* | 115 | /* |
113 | * In PLT mode we seem to get frames and mac80211 warns about them, | 116 | * In PLT mode we seem to get frames and mac80211 warns about them, |
@@ -116,6 +119,16 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
116 | if (unlikely(wl->plt)) | 119 | if (unlikely(wl->plt)) |
117 | return -EINVAL; | 120 | return -EINVAL; |
118 | 121 | ||
122 | pkt_data_len = wlcore_hw_get_rx_packet_len(wl, data, length); | ||
123 | if (!pkt_data_len) { | ||
124 | wl1271_error("Invalid packet arrived from HW. length %d", | ||
125 | length); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) | ||
130 | reserved = NET_IP_ALIGN; | ||
131 | |||
119 | /* the data read starts with the descriptor */ | 132 | /* the data read starts with the descriptor */ |
120 | desc = (struct wl1271_rx_descriptor *) data; | 133 | desc = (struct wl1271_rx_descriptor *) data; |
121 | 134 | ||
@@ -142,8 +155,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
142 | return -EINVAL; | 155 | return -EINVAL; |
143 | } | 156 | } |
144 | 157 | ||
145 | /* skb length not included rx descriptor */ | 158 | /* skb length not including rx descriptor */ |
146 | skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL); | 159 | skb = __dev_alloc_skb(pkt_data_len + reserved, GFP_KERNEL); |
147 | if (!skb) { | 160 | if (!skb) { |
148 | wl1271_error("Couldn't allocate RX frame"); | 161 | wl1271_error("Couldn't allocate RX frame"); |
149 | return -ENOMEM; | 162 | return -ENOMEM; |
@@ -152,7 +165,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
152 | /* reserve the unaligned payload(if any) */ | 165 | /* reserve the unaligned payload(if any) */ |
153 | skb_reserve(skb, reserved); | 166 | skb_reserve(skb, reserved); |
154 | 167 | ||
155 | buf = skb_put(skb, length - sizeof(*desc)); | 168 | buf = skb_put(skb, pkt_data_len); |
156 | 169 | ||
157 | /* | 170 | /* |
158 | * Copy packets from aggregation buffer to the skbs without rx | 171 | * Copy packets from aggregation buffer to the skbs without rx |
@@ -160,7 +173,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
160 | * packets copy the packets in offset of 2 bytes guarantee IP header | 173 | * packets copy the packets in offset of 2 bytes guarantee IP header |
161 | * payload aligned to 4 bytes. | 174 | * payload aligned to 4 bytes. |
162 | */ | 175 | */ |
163 | memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); | 176 | memcpy(buf, data + sizeof(*desc), pkt_data_len); |
177 | if (rx_align == WLCORE_RX_BUF_PADDED) | ||
178 | skb_pull(skb, NET_IP_ALIGN); | ||
179 | |||
164 | *hlid = desc->hlid; | 180 | *hlid = desc->hlid; |
165 | 181 | ||
166 | hdr = (struct ieee80211_hdr *)skb->data; | 182 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -177,36 +193,35 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
177 | beacon ? "beacon" : "", | 193 | beacon ? "beacon" : "", |
178 | seq_num, *hlid); | 194 | seq_num, *hlid); |
179 | 195 | ||
180 | skb_trim(skb, skb->len - desc->pad_len); | ||
181 | |||
182 | skb_queue_tail(&wl->deferred_rx_queue, skb); | 196 | skb_queue_tail(&wl->deferred_rx_queue, skb); |
183 | queue_work(wl->freezable_wq, &wl->netstack_work); | 197 | queue_work(wl->freezable_wq, &wl->netstack_work); |
184 | 198 | ||
185 | return is_data; | 199 | return is_data; |
186 | } | 200 | } |
187 | 201 | ||
188 | void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | 202 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) |
189 | { | 203 | { |
190 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | ||
191 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 204 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
192 | u32 buf_size; | 205 | u32 buf_size; |
193 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 206 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
194 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 207 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
195 | u32 rx_counter; | 208 | u32 rx_counter; |
196 | u32 mem_block; | 209 | u32 pkt_len, align_pkt_len; |
197 | u32 pkt_length; | 210 | u32 pkt_offset, des; |
198 | u32 pkt_offset; | ||
199 | u8 hlid; | 211 | u8 hlid; |
200 | bool unaligned = false; | 212 | enum wl_rx_buf_align rx_align; |
201 | 213 | ||
202 | while (drv_rx_counter != fw_rx_counter) { | 214 | while (drv_rx_counter != fw_rx_counter) { |
203 | buf_size = 0; | 215 | buf_size = 0; |
204 | rx_counter = drv_rx_counter; | 216 | rx_counter = drv_rx_counter; |
205 | while (rx_counter != fw_rx_counter) { | 217 | while (rx_counter != fw_rx_counter) { |
206 | pkt_length = wl12xx_rx_get_buf_size(status, rx_counter); | 218 | des = le32_to_cpu(status->rx_pkt_descs[rx_counter]); |
207 | if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) | 219 | pkt_len = wlcore_rx_get_buf_size(wl, des); |
220 | align_pkt_len = wlcore_rx_get_align_buf_size(wl, | ||
221 | pkt_len); | ||
222 | if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE) | ||
208 | break; | 223 | break; |
209 | buf_size += pkt_length; | 224 | buf_size += align_pkt_len; |
210 | rx_counter++; | 225 | rx_counter++; |
211 | rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | 226 | rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; |
212 | } | 227 | } |
@@ -216,38 +231,18 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
216 | break; | 231 | break; |
217 | } | 232 | } |
218 | 233 | ||
219 | if (wl->chip.id != CHIP_ID_1283_PG20) { | ||
220 | /* | ||
221 | * Choose the block we want to read | ||
222 | * For aggregated packets, only the first memory block | ||
223 | * should be retrieved. The FW takes care of the rest. | ||
224 | */ | ||
225 | mem_block = wl12xx_rx_get_mem_block(status, | ||
226 | drv_rx_counter); | ||
227 | |||
228 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + | ||
229 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); | ||
230 | |||
231 | wl->rx_mem_pool_addr.addr_extra = | ||
232 | wl->rx_mem_pool_addr.addr + 4; | ||
233 | |||
234 | wl1271_write(wl, WL1271_SLV_REG_DATA, | ||
235 | &wl->rx_mem_pool_addr, | ||
236 | sizeof(wl->rx_mem_pool_addr), false); | ||
237 | } | ||
238 | |||
239 | /* Read all available packets at once */ | 234 | /* Read all available packets at once */ |
240 | wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | 235 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); |
241 | buf_size, true); | 236 | wlcore_hw_prepare_read(wl, des, buf_size); |
237 | wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | ||
238 | buf_size, true); | ||
242 | 239 | ||
243 | /* Split data into separate packets */ | 240 | /* Split data into separate packets */ |
244 | pkt_offset = 0; | 241 | pkt_offset = 0; |
245 | while (pkt_offset < buf_size) { | 242 | while (pkt_offset < buf_size) { |
246 | pkt_length = wl12xx_rx_get_buf_size(status, | 243 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); |
247 | drv_rx_counter); | 244 | pkt_len = wlcore_rx_get_buf_size(wl, des); |
248 | 245 | rx_align = wlcore_hw_get_rx_buf_align(wl, des); | |
249 | unaligned = wl12xx_rx_get_unaligned(status, | ||
250 | drv_rx_counter); | ||
251 | 246 | ||
252 | /* | 247 | /* |
253 | * the handle data call can only fail in memory-outage | 248 | * the handle data call can only fail in memory-outage |
@@ -256,7 +251,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
256 | */ | 251 | */ |
257 | if (wl1271_rx_handle_data(wl, | 252 | if (wl1271_rx_handle_data(wl, |
258 | wl->aggr_buf + pkt_offset, | 253 | wl->aggr_buf + pkt_offset, |
259 | pkt_length, unaligned, | 254 | pkt_len, rx_align, |
260 | &hlid) == 1) { | 255 | &hlid) == 1) { |
261 | if (hlid < WL12XX_MAX_LINKS) | 256 | if (hlid < WL12XX_MAX_LINKS) |
262 | __set_bit(hlid, active_hlids); | 257 | __set_bit(hlid, active_hlids); |
@@ -269,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
269 | wl->rx_counter++; | 264 | wl->rx_counter++; |
270 | drv_rx_counter++; | 265 | drv_rx_counter++; |
271 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | 266 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; |
272 | pkt_offset += pkt_length; | 267 | pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len); |
273 | } | 268 | } |
274 | } | 269 | } |
275 | 270 | ||
@@ -277,8 +272,9 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
277 | * Write the driver's packet counter to the FW. This is only required | 272 | * Write the driver's packet counter to the FW. This is only required |
278 | * for older hardware revisions | 273 | * for older hardware revisions |
279 | */ | 274 | */ |
280 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) | 275 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) |
281 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 276 | wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, |
277 | wl->rx_counter); | ||
282 | 278 | ||
283 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 279 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
284 | } | 280 | } |
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 86ba6b1d0cdc..6e129e2a8546 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -96,9 +96,19 @@ | |||
96 | #define RX_MEM_BLOCK_MASK 0xFF | 96 | #define RX_MEM_BLOCK_MASK 0xFF |
97 | #define RX_BUF_SIZE_MASK 0xFFF00 | 97 | #define RX_BUF_SIZE_MASK 0xFFF00 |
98 | #define RX_BUF_SIZE_SHIFT_DIV 6 | 98 | #define RX_BUF_SIZE_SHIFT_DIV 6 |
99 | #define ALIGNED_RX_BUF_SIZE_MASK 0xFFFF00 | ||
100 | #define ALIGNED_RX_BUF_SIZE_SHIFT 8 | ||
101 | |||
99 | /* If set, the start of IP payload is not 4 bytes aligned */ | 102 | /* If set, the start of IP payload is not 4 bytes aligned */ |
100 | #define RX_BUF_UNALIGNED_PAYLOAD BIT(20) | 103 | #define RX_BUF_UNALIGNED_PAYLOAD BIT(20) |
101 | 104 | ||
105 | /* Describes the alignment state of a Rx buffer */ | ||
106 | enum wl_rx_buf_align { | ||
107 | WLCORE_RX_BUF_ALIGNED, | ||
108 | WLCORE_RX_BUF_UNALIGNED, | ||
109 | WLCORE_RX_BUF_PADDED, | ||
110 | }; | ||
111 | |||
102 | enum { | 112 | enum { |
103 | WL12XX_RX_CLASS_UNKNOWN, | 113 | WL12XX_RX_CLASS_UNKNOWN, |
104 | WL12XX_RX_CLASS_MANAGEMENT, | 114 | WL12XX_RX_CLASS_MANAGEMENT, |
@@ -126,7 +136,7 @@ struct wl1271_rx_descriptor { | |||
126 | u8 reserved; | 136 | u8 reserved; |
127 | } __packed; | 137 | } __packed; |
128 | 138 | ||
129 | void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status); | 139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); |
130 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
131 | 141 | ||
132 | #endif | 142 | #endif |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index fcba055ef196..ade21a011c45 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/ieee80211.h> | 24 | #include <linux/ieee80211.h> |
25 | 25 | ||
26 | #include "wl12xx.h" | 26 | #include "wlcore.h" |
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "cmd.h" | 28 | #include "cmd.h" |
29 | #include "scan.h" | 29 | #include "scan.h" |
@@ -417,6 +417,23 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
417 | int i, j; | 417 | int i, j; |
418 | u32 flags; | 418 | u32 flags; |
419 | bool force_passive = !req->n_ssids; | 419 | bool force_passive = !req->n_ssids; |
420 | u32 min_dwell_time_active, max_dwell_time_active, delta_per_probe; | ||
421 | u32 dwell_time_passive, dwell_time_dfs; | ||
422 | |||
423 | if (band == IEEE80211_BAND_5GHZ) | ||
424 | delta_per_probe = c->dwell_time_delta_per_probe_5; | ||
425 | else | ||
426 | delta_per_probe = c->dwell_time_delta_per_probe; | ||
427 | |||
428 | min_dwell_time_active = c->base_dwell_time + | ||
429 | req->n_ssids * c->num_probe_reqs * delta_per_probe; | ||
430 | |||
431 | max_dwell_time_active = min_dwell_time_active + c->max_dwell_time_delta; | ||
432 | |||
433 | min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000); | ||
434 | max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000); | ||
435 | dwell_time_passive = DIV_ROUND_UP(c->dwell_time_passive, 1000); | ||
436 | dwell_time_dfs = DIV_ROUND_UP(c->dwell_time_dfs, 1000); | ||
420 | 437 | ||
421 | for (i = 0, j = start; | 438 | for (i = 0, j = start; |
422 | i < req->n_channels && j < max_channels; | 439 | i < req->n_channels && j < max_channels; |
@@ -440,21 +457,24 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | |||
440 | req->channels[i]->flags); | 457 | req->channels[i]->flags); |
441 | wl1271_debug(DEBUG_SCAN, "max_power %d", | 458 | wl1271_debug(DEBUG_SCAN, "max_power %d", |
442 | req->channels[i]->max_power); | 459 | req->channels[i]->max_power); |
460 | wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d", | ||
461 | min_dwell_time_active, | ||
462 | max_dwell_time_active); | ||
443 | 463 | ||
444 | if (flags & IEEE80211_CHAN_RADAR) { | 464 | if (flags & IEEE80211_CHAN_RADAR) { |
445 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; | 465 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; |
446 | 466 | ||
447 | channels[j].passive_duration = | 467 | channels[j].passive_duration = |
448 | cpu_to_le16(c->dwell_time_dfs); | 468 | cpu_to_le16(dwell_time_dfs); |
449 | } else { | 469 | } else { |
450 | channels[j].passive_duration = | 470 | channels[j].passive_duration = |
451 | cpu_to_le16(c->dwell_time_passive); | 471 | cpu_to_le16(dwell_time_passive); |
452 | } | 472 | } |
453 | 473 | ||
454 | channels[j].min_duration = | 474 | channels[j].min_duration = |
455 | cpu_to_le16(c->min_dwell_time_active); | 475 | cpu_to_le16(min_dwell_time_active); |
456 | channels[j].max_duration = | 476 | channels[j].max_duration = |
457 | cpu_to_le16(c->max_dwell_time_active); | 477 | cpu_to_le16(max_dwell_time_active); |
458 | 478 | ||
459 | channels[j].tx_power_att = req->channels[i]->max_power; | 479 | channels[j].tx_power_att = req->channels[i]->max_power; |
460 | channels[j].channel = req->channels[i]->hw_value; | 480 | channels[j].channel = req->channels[i]->hw_value; |
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/ti/wlcore/scan.h index 96ff457a3a0b..81ee36ac2078 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/ti/wlcore/scan.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef __SCAN_H__ | 24 | #ifndef __SCAN_H__ |
25 | #define __SCAN_H__ | 25 | #define __SCAN_H__ |
26 | 26 | ||
27 | #include "wl12xx.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, | 29 | int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, |
30 | const u8 *ssid, size_t ssid_len, | 30 | const u8 *ssid, size_t ssid_len, |
@@ -55,7 +55,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl); | |||
55 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | 55 | #define WL1271_SCAN_BAND_2_4_GHZ 0 |
56 | #define WL1271_SCAN_BAND_5_GHZ 1 | 56 | #define WL1271_SCAN_BAND_5_GHZ 1 |
57 | 57 | ||
58 | #define WL1271_SCAN_TIMEOUT 10000 /* msec */ | 58 | #define WL1271_SCAN_TIMEOUT 30000 /* msec */ |
59 | 59 | ||
60 | enum { | 60 | enum { |
61 | WL1271_SCAN_STATE_IDLE, | 61 | WL1271_SCAN_STATE_IDLE, |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 4b3c32774bae..0a72347cfc4c 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/wl12xx.h> | 33 | #include <linux/wl12xx.h> |
34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
35 | 35 | ||
36 | #include "wl12xx.h" | 36 | #include "wlcore.h" |
37 | #include "wl12xx_80211.h" | 37 | #include "wl12xx_80211.h" |
38 | #include "io.h" | 38 | #include "io.h" |
39 | 39 | ||
@@ -76,7 +76,7 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
76 | 76 | ||
77 | sdio_claim_host(func); | 77 | sdio_claim_host(func); |
78 | 78 | ||
79 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 79 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { |
80 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 80 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
81 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", | 81 | dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", |
82 | addr, ((u8 *)buf)[0]); | 82 | addr, ((u8 *)buf)[0]); |
@@ -105,7 +105,7 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
105 | 105 | ||
106 | sdio_claim_host(func); | 106 | sdio_claim_host(func); |
107 | 107 | ||
108 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 108 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { |
109 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 109 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
110 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", | 110 | dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", |
111 | addr, ((u8 *)buf)[0]); | 111 | addr, ((u8 *)buf)[0]); |
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 2fc18a8dcce8..553cd3cbb98c 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
@@ -30,12 +30,10 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | 32 | ||
33 | #include "wl12xx.h" | 33 | #include "wlcore.h" |
34 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
35 | #include "io.h" | 35 | #include "io.h" |
36 | 36 | ||
37 | #include "reg.h" | ||
38 | |||
39 | #define WSPI_CMD_READ 0x40000000 | 37 | #define WSPI_CMD_READ 0x40000000 |
40 | #define WSPI_CMD_WRITE 0x00000000 | 38 | #define WSPI_CMD_WRITE 0x00000000 |
41 | #define WSPI_CMD_FIXED 0x20000000 | 39 | #define WSPI_CMD_FIXED 0x20000000 |
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index b41428f5b3b2..0e59ea2cdd39 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c | |||
@@ -25,10 +25,9 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <net/genetlink.h> | 26 | #include <net/genetlink.h> |
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wlcore.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | #include "acx.h" | 30 | #include "acx.h" |
31 | #include "reg.h" | ||
32 | #include "ps.h" | 31 | #include "ps.h" |
33 | #include "io.h" | 32 | #include "io.h" |
34 | 33 | ||
diff --git a/drivers/net/wireless/wl12xx/testmode.h b/drivers/net/wireless/ti/wlcore/testmode.h index 8071654259ea..8071654259ea 100644 --- a/drivers/net/wireless/wl12xx/testmode.h +++ b/drivers/net/wireless/ti/wlcore/testmode.h | |||
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 43ae49143d68..6893bc207994 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -25,13 +25,19 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | 27 | ||
28 | #include "wl12xx.h" | 28 | #include "wlcore.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | #include "io.h" | 30 | #include "io.h" |
31 | #include "reg.h" | ||
32 | #include "ps.h" | 31 | #include "ps.h" |
33 | #include "tx.h" | 32 | #include "tx.h" |
34 | #include "event.h" | 33 | #include "event.h" |
34 | #include "hw_ops.h" | ||
35 | |||
36 | /* | ||
37 | * TODO: this is here just for now, it must be removed when the data | ||
38 | * operations are in place. | ||
39 | */ | ||
40 | #include "../wl12xx/reg.h" | ||
35 | 41 | ||
36 | static int wl1271_set_default_wep_key(struct wl1271 *wl, | 42 | static int wl1271_set_default_wep_key(struct wl1271 *wl, |
37 | struct wl12xx_vif *wlvif, u8 id) | 43 | struct wl12xx_vif *wlvif, u8 id) |
@@ -56,8 +62,8 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
56 | { | 62 | { |
57 | int id; | 63 | int id; |
58 | 64 | ||
59 | id = find_first_zero_bit(wl->tx_frames_map, ACX_TX_DESCRIPTORS); | 65 | id = find_first_zero_bit(wl->tx_frames_map, wl->num_tx_desc); |
60 | if (id >= ACX_TX_DESCRIPTORS) | 66 | if (id >= wl->num_tx_desc) |
61 | return -EBUSY; | 67 | return -EBUSY; |
62 | 68 | ||
63 | __set_bit(id, wl->tx_frames_map); | 69 | __set_bit(id, wl->tx_frames_map); |
@@ -69,7 +75,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
69 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) | 75 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) |
70 | { | 76 | { |
71 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { | 77 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { |
72 | if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS)) | 78 | if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc)) |
73 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 79 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
74 | 80 | ||
75 | wl->tx_frames[id] = NULL; | 81 | wl->tx_frames[id] = NULL; |
@@ -167,14 +173,15 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
167 | return wlvif->dev_hlid; | 173 | return wlvif->dev_hlid; |
168 | } | 174 | } |
169 | 175 | ||
170 | static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, | 176 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, |
171 | unsigned int packet_length) | 177 | unsigned int packet_length) |
172 | { | 178 | { |
173 | if (wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT) | 179 | if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) |
174 | return ALIGN(packet_length, WL1271_TX_ALIGN_TO); | ||
175 | else | ||
176 | return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); | 180 | return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); |
181 | else | ||
182 | return ALIGN(packet_length, WL1271_TX_ALIGN_TO); | ||
177 | } | 183 | } |
184 | EXPORT_SYMBOL(wlcore_calc_packet_alignment); | ||
178 | 185 | ||
179 | static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 186 | static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
180 | struct sk_buff *skb, u32 extra, u32 buf_offset, | 187 | struct sk_buff *skb, u32 extra, u32 buf_offset, |
@@ -182,10 +189,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
182 | { | 189 | { |
183 | struct wl1271_tx_hw_descr *desc; | 190 | struct wl1271_tx_hw_descr *desc; |
184 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 191 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
185 | u32 len; | ||
186 | u32 total_blocks; | 192 | u32 total_blocks; |
187 | int id, ret = -EBUSY, ac; | 193 | int id, ret = -EBUSY, ac; |
188 | u32 spare_blocks = wl->tx_spare_blocks; | 194 | u32 spare_blocks = wl->normal_tx_spare; |
189 | bool is_dummy = false; | 195 | bool is_dummy = false; |
190 | 196 | ||
191 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) | 197 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) |
@@ -196,30 +202,19 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
196 | if (id < 0) | 202 | if (id < 0) |
197 | return id; | 203 | return id; |
198 | 204 | ||
199 | /* approximate the number of blocks required for this packet | 205 | if (unlikely(wl12xx_is_dummy_packet(wl, skb))) |
200 | in the firmware */ | ||
201 | len = wl12xx_calc_packet_alignment(wl, total_len); | ||
202 | |||
203 | /* in case of a dummy packet, use default amount of spare mem blocks */ | ||
204 | if (unlikely(wl12xx_is_dummy_packet(wl, skb))) { | ||
205 | is_dummy = true; | 206 | is_dummy = true; |
206 | spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | 207 | else if (wlvif->is_gem) |
207 | } | 208 | spare_blocks = wl->gem_tx_spare; |
208 | 209 | ||
209 | total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + | 210 | total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); |
210 | spare_blocks; | ||
211 | 211 | ||
212 | if (total_blocks <= wl->tx_blocks_available) { | 212 | if (total_blocks <= wl->tx_blocks_available) { |
213 | desc = (struct wl1271_tx_hw_descr *)skb_push( | 213 | desc = (struct wl1271_tx_hw_descr *)skb_push( |
214 | skb, total_len - skb->len); | 214 | skb, total_len - skb->len); |
215 | 215 | ||
216 | /* HW descriptor fields change between wl127x and wl128x */ | 216 | wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks, |
217 | if (wl->chip.id == CHIP_ID_1283_PG20) { | 217 | spare_blocks); |
218 | desc->wl128x_mem.total_mem_blocks = total_blocks; | ||
219 | } else { | ||
220 | desc->wl127x_mem.extra_blocks = spare_blocks; | ||
221 | desc->wl127x_mem.total_mem_blocks = total_blocks; | ||
222 | } | ||
223 | 218 | ||
224 | desc->id = id; | 219 | desc->id = id; |
225 | 220 | ||
@@ -256,7 +251,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
256 | { | 251 | { |
257 | struct timespec ts; | 252 | struct timespec ts; |
258 | struct wl1271_tx_hw_descr *desc; | 253 | struct wl1271_tx_hw_descr *desc; |
259 | int aligned_len, ac, rate_idx; | 254 | int ac, rate_idx; |
260 | s64 hosttime; | 255 | s64 hosttime; |
261 | u16 tx_attr = 0; | 256 | u16 tx_attr = 0; |
262 | __le16 frame_control; | 257 | __le16 frame_control; |
@@ -329,44 +324,16 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
329 | } | 324 | } |
330 | 325 | ||
331 | tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; | 326 | tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; |
332 | desc->reserved = 0; | ||
333 | |||
334 | aligned_len = wl12xx_calc_packet_alignment(wl, skb->len); | ||
335 | |||
336 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
337 | desc->wl128x_mem.extra_bytes = aligned_len - skb->len; | ||
338 | desc->length = cpu_to_le16(aligned_len >> 2); | ||
339 | |||
340 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " | ||
341 | "tx_attr: 0x%x len: %d life: %d mem: %d", | ||
342 | desc->hlid, tx_attr, | ||
343 | le16_to_cpu(desc->length), | ||
344 | le16_to_cpu(desc->life_time), | ||
345 | desc->wl128x_mem.total_mem_blocks); | ||
346 | } else { | ||
347 | int pad; | ||
348 | |||
349 | /* Store the aligned length in terms of words */ | ||
350 | desc->length = cpu_to_le16(aligned_len >> 2); | ||
351 | |||
352 | /* calculate number of padding bytes */ | ||
353 | pad = aligned_len - skb->len; | ||
354 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | ||
355 | |||
356 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " | ||
357 | "tx_attr: 0x%x len: %d life: %d mem: %d", pad, | ||
358 | desc->hlid, tx_attr, | ||
359 | le16_to_cpu(desc->length), | ||
360 | le16_to_cpu(desc->life_time), | ||
361 | desc->wl127x_mem.total_mem_blocks); | ||
362 | } | ||
363 | 327 | ||
364 | /* for WEP shared auth - no fw encryption is needed */ | 328 | /* for WEP shared auth - no fw encryption is needed */ |
365 | if (ieee80211_is_auth(frame_control) && | 329 | if (ieee80211_is_auth(frame_control) && |
366 | ieee80211_has_protected(frame_control)) | 330 | ieee80211_has_protected(frame_control)) |
367 | tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; | 331 | tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; |
368 | 332 | ||
333 | desc->reserved = 0; | ||
369 | desc->tx_attr = cpu_to_le16(tx_attr); | 334 | desc->tx_attr = cpu_to_le16(tx_attr); |
335 | |||
336 | wlcore_hw_set_tx_desc_data_len(wl, desc, skb); | ||
370 | } | 337 | } |
371 | 338 | ||
372 | /* caller must hold wl->mutex */ | 339 | /* caller must hold wl->mutex */ |
@@ -432,7 +399,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
432 | * In special cases, we want to align to a specific block size | 399 | * In special cases, we want to align to a specific block size |
433 | * (eg. for wl128x with SDIO we align to 256). | 400 | * (eg. for wl128x with SDIO we align to 256). |
434 | */ | 401 | */ |
435 | total_len = wl12xx_calc_packet_alignment(wl, skb->len); | 402 | total_len = wlcore_calc_packet_alignment(wl, skb->len); |
436 | 403 | ||
437 | memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); | 404 | memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); |
438 | memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); | 405 | memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); |
@@ -718,8 +685,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
718 | * Flush buffer and try again. | 685 | * Flush buffer and try again. |
719 | */ | 686 | */ |
720 | wl1271_skb_queue_head(wl, wlvif, skb); | 687 | wl1271_skb_queue_head(wl, wlvif, skb); |
721 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | 688 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
722 | buf_offset, true); | 689 | buf_offset, true); |
723 | sent_packets = true; | 690 | sent_packets = true; |
724 | buf_offset = 0; | 691 | buf_offset = 0; |
725 | continue; | 692 | continue; |
@@ -753,8 +720,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
753 | 720 | ||
754 | out_ack: | 721 | out_ack: |
755 | if (buf_offset) { | 722 | if (buf_offset) { |
756 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | 723 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
757 | buf_offset, true); | 724 | buf_offset, true); |
758 | sent_packets = true; | 725 | sent_packets = true; |
759 | } | 726 | } |
760 | if (sent_packets) { | 727 | if (sent_packets) { |
@@ -762,8 +729,8 @@ out_ack: | |||
762 | * Interrupt the firmware with the new packets. This is only | 729 | * Interrupt the firmware with the new packets. This is only |
763 | * required for older hardware revisions | 730 | * required for older hardware revisions |
764 | */ | 731 | */ |
765 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) | 732 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) |
766 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, | 733 | wl1271_write32(wl, WL12XX_HOST_WR_ACCESS, |
767 | wl->tx_packets_count); | 734 | wl->tx_packets_count); |
768 | 735 | ||
769 | wl1271_handle_tx_low_watermark(wl); | 736 | wl1271_handle_tx_low_watermark(wl); |
@@ -792,11 +759,20 @@ static u8 wl1271_tx_get_rate_flags(u8 rate_class_index) | |||
792 | { | 759 | { |
793 | u8 flags = 0; | 760 | u8 flags = 0; |
794 | 761 | ||
795 | if (rate_class_index >= CONF_HW_RXTX_RATE_MCS_MIN && | 762 | /* |
796 | rate_class_index <= CONF_HW_RXTX_RATE_MCS_MAX) | 763 | * TODO: use wl12xx constants when this code is moved to wl12xx, as |
764 | * only it uses Tx-completion. | ||
765 | */ | ||
766 | if (rate_class_index <= 8) | ||
797 | flags |= IEEE80211_TX_RC_MCS; | 767 | flags |= IEEE80211_TX_RC_MCS; |
798 | if (rate_class_index == CONF_HW_RXTX_RATE_MCS7_SGI) | 768 | |
769 | /* | ||
770 | * TODO: use wl12xx constants when this code is moved to wl12xx, as | ||
771 | * only it uses Tx-completion. | ||
772 | */ | ||
773 | if (rate_class_index == 0) | ||
799 | flags |= IEEE80211_TX_RC_SHORT_GI; | 774 | flags |= IEEE80211_TX_RC_SHORT_GI; |
775 | |||
800 | return flags; | 776 | return flags; |
801 | } | 777 | } |
802 | 778 | ||
@@ -813,7 +789,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
813 | u8 retries = 0; | 789 | u8 retries = 0; |
814 | 790 | ||
815 | /* check for id legality */ | 791 | /* check for id legality */ |
816 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { | 792 | if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) { |
817 | wl1271_warning("TX result illegal id: %d", id); | 793 | wl1271_warning("TX result illegal id: %d", id); |
818 | return; | 794 | return; |
819 | } | 795 | } |
@@ -834,7 +810,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
834 | if (result->status == TX_SUCCESS) { | 810 | if (result->status == TX_SUCCESS) { |
835 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 811 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
836 | info->flags |= IEEE80211_TX_STAT_ACK; | 812 | info->flags |= IEEE80211_TX_STAT_ACK; |
837 | rate = wl1271_rate_to_idx(result->rate_class_index, | 813 | rate = wlcore_rate_to_idx(wl, result->rate_class_index, |
838 | wlvif->band); | 814 | wlvif->band); |
839 | rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index); | 815 | rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index); |
840 | retries = result->ack_failures; | 816 | retries = result->ack_failures; |
@@ -929,6 +905,7 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
929 | wl->tx_results_count++; | 905 | wl->tx_results_count++; |
930 | } | 906 | } |
931 | } | 907 | } |
908 | EXPORT_SYMBOL(wl1271_tx_complete); | ||
932 | 909 | ||
933 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 910 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
934 | { | 911 | { |
@@ -1006,7 +983,7 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
1006 | if (reset_tx_queues) | 983 | if (reset_tx_queues) |
1007 | wl1271_handle_tx_low_watermark(wl); | 984 | wl1271_handle_tx_low_watermark(wl); |
1008 | 985 | ||
1009 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { | 986 | for (i = 0; i < wl->num_tx_desc; i++) { |
1010 | if (wl->tx_frames[i] == NULL) | 987 | if (wl->tx_frames[i] == NULL) |
1011 | continue; | 988 | continue; |
1012 | 989 | ||
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index 5cf8c32d40d1..2fd6e5dc6f75 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
@@ -25,9 +25,6 @@ | |||
25 | #ifndef __TX_H__ | 25 | #ifndef __TX_H__ |
26 | #define __TX_H__ | 26 | #define __TX_H__ |
27 | 27 | ||
28 | #define TX_HW_BLOCK_SPARE_DEFAULT 1 | ||
29 | #define TX_HW_BLOCK_SIZE 252 | ||
30 | |||
31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 | 28 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 |
32 | #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 | 29 | #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 |
33 | 30 | ||
@@ -212,7 +209,7 @@ void wl1271_tx_complete(struct wl1271 *wl); | |||
212 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 209 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
213 | void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); | 210 | void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); |
214 | void wl1271_tx_flush(struct wl1271 *wl); | 211 | void wl1271_tx_flush(struct wl1271 *wl); |
215 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 212 | u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band); |
216 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, | 213 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, |
217 | enum ieee80211_band rate_band); | 214 | enum ieee80211_band rate_band); |
218 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); | 215 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); |
@@ -224,6 +221,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); | |||
224 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); | 221 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); |
225 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); | 222 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); |
226 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); | 223 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); |
224 | unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, | ||
225 | unsigned int packet_length); | ||
227 | 226 | ||
228 | /* from main.c */ | 227 | /* from main.c */ |
229 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); | 228 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h index 749a15a75d38..a9b220c43e54 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx.h | |||
@@ -89,8 +89,6 @@ | |||
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 ACX_TX_DESCRIPTORS 16 | ||
93 | |||
94 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | 92 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) |
95 | 93 | ||
96 | enum wl1271_state { | 94 | enum wl1271_state { |
@@ -105,26 +103,6 @@ enum wl12xx_fw_type { | |||
105 | WL12XX_FW_TYPE_PLT, | 103 | WL12XX_FW_TYPE_PLT, |
106 | }; | 104 | }; |
107 | 105 | ||
108 | enum wl1271_partition_type { | ||
109 | PART_DOWN, | ||
110 | PART_WORK, | ||
111 | PART_DRPW, | ||
112 | |||
113 | PART_TABLE_LEN | ||
114 | }; | ||
115 | |||
116 | struct wl1271_partition { | ||
117 | u32 size; | ||
118 | u32 start; | ||
119 | }; | ||
120 | |||
121 | struct wl1271_partition_set { | ||
122 | struct wl1271_partition mem; | ||
123 | struct wl1271_partition reg; | ||
124 | struct wl1271_partition mem2; | ||
125 | struct wl1271_partition mem3; | ||
126 | }; | ||
127 | |||
128 | struct wl1271; | 106 | struct wl1271; |
129 | 107 | ||
130 | enum { | 108 | enum { |
@@ -167,8 +145,21 @@ struct wl1271_stats { | |||
167 | 145 | ||
168 | #define AP_MAX_STATIONS 8 | 146 | #define AP_MAX_STATIONS 8 |
169 | 147 | ||
148 | struct wl_fw_packet_counters { | ||
149 | /* Cumulative counter of released packets per AC */ | ||
150 | u8 tx_released_pkts[NUM_TX_QUEUES]; | ||
151 | |||
152 | /* Cumulative counter of freed packets per HLID */ | ||
153 | u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; | ||
154 | |||
155 | /* Cumulative counter of released Voice memory blocks */ | ||
156 | u8 tx_voice_released_blks; | ||
157 | |||
158 | u8 padding[3]; | ||
159 | } __packed; | ||
160 | |||
170 | /* FW status registers */ | 161 | /* FW status registers */ |
171 | struct wl12xx_fw_status { | 162 | struct wl_fw_status { |
172 | __le32 intr; | 163 | __le32 intr; |
173 | u8 fw_rx_counter; | 164 | u8 fw_rx_counter; |
174 | u8 drv_rx_counter; | 165 | u8 drv_rx_counter; |
@@ -195,16 +186,12 @@ struct wl12xx_fw_status { | |||
195 | /* Size (in Memory Blocks) of TX pool */ | 186 | /* Size (in Memory Blocks) of TX pool */ |
196 | __le32 tx_total; | 187 | __le32 tx_total; |
197 | 188 | ||
198 | /* Cumulative counter of released packets per AC */ | 189 | struct wl_fw_packet_counters counters; |
199 | u8 tx_released_pkts[NUM_TX_QUEUES]; | ||
200 | 190 | ||
201 | /* Cumulative counter of freed packets per HLID */ | ||
202 | u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; | ||
203 | |||
204 | /* Cumulative counter of released Voice memory blocks */ | ||
205 | u8 tx_voice_released_blks; | ||
206 | u8 padding_1[3]; | ||
207 | __le32 log_start_addr; | 191 | __le32 log_start_addr; |
192 | |||
193 | /* Private status to be used by the lower drivers */ | ||
194 | u8 priv[0]; | ||
208 | } __packed; | 195 | } __packed; |
209 | 196 | ||
210 | struct wl1271_rx_mem_pool_addr { | 197 | struct wl1271_rx_mem_pool_addr { |
@@ -292,214 +279,6 @@ struct wl1271_link { | |||
292 | u8 ba_bitmap; | 279 | u8 ba_bitmap; |
293 | }; | 280 | }; |
294 | 281 | ||
295 | struct wl1271 { | ||
296 | struct ieee80211_hw *hw; | ||
297 | bool mac80211_registered; | ||
298 | |||
299 | struct device *dev; | ||
300 | |||
301 | void *if_priv; | ||
302 | |||
303 | struct wl1271_if_operations *if_ops; | ||
304 | |||
305 | void (*set_power)(bool enable); | ||
306 | int irq; | ||
307 | int ref_clock; | ||
308 | |||
309 | spinlock_t wl_lock; | ||
310 | |||
311 | enum wl1271_state state; | ||
312 | enum wl12xx_fw_type fw_type; | ||
313 | bool plt; | ||
314 | u8 last_vif_count; | ||
315 | struct mutex mutex; | ||
316 | |||
317 | unsigned long flags; | ||
318 | |||
319 | struct wl1271_partition_set part; | ||
320 | |||
321 | struct wl1271_chip chip; | ||
322 | |||
323 | int cmd_box_addr; | ||
324 | int event_box_addr; | ||
325 | |||
326 | u8 *fw; | ||
327 | size_t fw_len; | ||
328 | void *nvs; | ||
329 | size_t nvs_len; | ||
330 | |||
331 | s8 hw_pg_ver; | ||
332 | |||
333 | /* address read from the fuse ROM */ | ||
334 | u32 fuse_oui_addr; | ||
335 | u32 fuse_nic_addr; | ||
336 | |||
337 | /* we have up to 2 MAC addresses */ | ||
338 | struct mac_address addresses[2]; | ||
339 | int channel; | ||
340 | u8 system_hlid; | ||
341 | |||
342 | unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; | ||
343 | unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; | ||
344 | unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; | ||
345 | unsigned long rate_policies_map[ | ||
346 | BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; | ||
347 | |||
348 | struct list_head wlvif_list; | ||
349 | |||
350 | u8 sta_count; | ||
351 | u8 ap_count; | ||
352 | |||
353 | struct wl1271_acx_mem_map *target_mem_map; | ||
354 | |||
355 | /* Accounting for allocated / available TX blocks on HW */ | ||
356 | u32 tx_blocks_freed; | ||
357 | u32 tx_blocks_available; | ||
358 | u32 tx_allocated_blocks; | ||
359 | u32 tx_results_count; | ||
360 | |||
361 | /* amount of spare TX blocks to use */ | ||
362 | u32 tx_spare_blocks; | ||
363 | |||
364 | /* Accounting for allocated / available Tx packets in HW */ | ||
365 | u32 tx_pkts_freed[NUM_TX_QUEUES]; | ||
366 | u32 tx_allocated_pkts[NUM_TX_QUEUES]; | ||
367 | |||
368 | /* Transmitted TX packets counter for chipset interface */ | ||
369 | u32 tx_packets_count; | ||
370 | |||
371 | /* Time-offset between host and chipset clocks */ | ||
372 | s64 time_offset; | ||
373 | |||
374 | /* Frames scheduled for transmission, not handled yet */ | ||
375 | int tx_queue_count[NUM_TX_QUEUES]; | ||
376 | long stopped_queues_map; | ||
377 | |||
378 | /* Frames received, not handled yet by mac80211 */ | ||
379 | struct sk_buff_head deferred_rx_queue; | ||
380 | |||
381 | /* Frames sent, not returned yet to mac80211 */ | ||
382 | struct sk_buff_head deferred_tx_queue; | ||
383 | |||
384 | struct work_struct tx_work; | ||
385 | struct workqueue_struct *freezable_wq; | ||
386 | |||
387 | /* Pending TX frames */ | ||
388 | unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)]; | ||
389 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; | ||
390 | int tx_frames_cnt; | ||
391 | |||
392 | /* FW Rx counter */ | ||
393 | u32 rx_counter; | ||
394 | |||
395 | /* Rx memory pool address */ | ||
396 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; | ||
397 | |||
398 | /* Intermediate buffer, used for packet aggregation */ | ||
399 | u8 *aggr_buf; | ||
400 | |||
401 | /* Reusable dummy packet template */ | ||
402 | struct sk_buff *dummy_packet; | ||
403 | |||
404 | /* Network stack work */ | ||
405 | struct work_struct netstack_work; | ||
406 | |||
407 | /* FW log buffer */ | ||
408 | u8 *fwlog; | ||
409 | |||
410 | /* Number of valid bytes in the FW log buffer */ | ||
411 | ssize_t fwlog_size; | ||
412 | |||
413 | /* Sysfs FW log entry readers wait queue */ | ||
414 | wait_queue_head_t fwlog_waitq; | ||
415 | |||
416 | /* Hardware recovery work */ | ||
417 | struct work_struct recovery_work; | ||
418 | |||
419 | /* The mbox event mask */ | ||
420 | u32 event_mask; | ||
421 | |||
422 | /* Mailbox pointers */ | ||
423 | u32 mbox_ptr[2]; | ||
424 | |||
425 | /* Are we currently scanning */ | ||
426 | struct ieee80211_vif *scan_vif; | ||
427 | struct wl1271_scan scan; | ||
428 | struct delayed_work scan_complete_work; | ||
429 | |||
430 | bool sched_scanning; | ||
431 | |||
432 | /* The current band */ | ||
433 | enum ieee80211_band band; | ||
434 | |||
435 | struct completion *elp_compl; | ||
436 | struct delayed_work elp_work; | ||
437 | |||
438 | /* in dBm */ | ||
439 | int power_level; | ||
440 | |||
441 | struct wl1271_stats stats; | ||
442 | |||
443 | __le32 buffer_32; | ||
444 | u32 buffer_cmd; | ||
445 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; | ||
446 | |||
447 | struct wl12xx_fw_status *fw_status; | ||
448 | struct wl1271_tx_hw_res_if *tx_res_if; | ||
449 | |||
450 | /* Current chipset configuration */ | ||
451 | struct conf_drv_settings conf; | ||
452 | |||
453 | bool sg_enabled; | ||
454 | |||
455 | bool enable_11a; | ||
456 | |||
457 | /* Most recently reported noise in dBm */ | ||
458 | s8 noise; | ||
459 | |||
460 | /* bands supported by this instance of wl12xx */ | ||
461 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
462 | |||
463 | int tcxo_clock; | ||
464 | |||
465 | /* | ||
466 | * wowlan trigger was configured during suspend. | ||
467 | * (currently, only "ANY" trigger is supported) | ||
468 | */ | ||
469 | bool wow_enabled; | ||
470 | bool irq_wake_enabled; | ||
471 | |||
472 | /* | ||
473 | * AP-mode - links indexed by HLID. The global and broadcast links | ||
474 | * are always active. | ||
475 | */ | ||
476 | struct wl1271_link links[WL12XX_MAX_LINKS]; | ||
477 | |||
478 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ | ||
479 | u32 ap_fw_ps_map; | ||
480 | |||
481 | /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ | ||
482 | unsigned long ap_ps_map; | ||
483 | |||
484 | /* Quirks of specific hardware revisions */ | ||
485 | unsigned int quirks; | ||
486 | |||
487 | /* Platform limitations */ | ||
488 | unsigned int platform_quirks; | ||
489 | |||
490 | /* number of currently active RX BA sessions */ | ||
491 | int ba_rx_session_count; | ||
492 | |||
493 | /* AP-mode - number of currently connected stations */ | ||
494 | int active_sta_count; | ||
495 | |||
496 | /* last wlvif we transmitted from */ | ||
497 | struct wl12xx_vif *last_wlvif; | ||
498 | |||
499 | /* work to fire when Tx is stuck */ | ||
500 | struct delayed_work tx_watchdog_work; | ||
501 | }; | ||
502 | |||
503 | struct wl1271_station { | 282 | struct wl1271_station { |
504 | u8 hlid; | 283 | u8 hlid; |
505 | }; | 284 | }; |
@@ -605,6 +384,9 @@ struct wl12xx_vif { | |||
605 | struct work_struct rx_streaming_disable_work; | 384 | struct work_struct rx_streaming_disable_work; |
606 | struct timer_list rx_streaming_timer; | 385 | struct timer_list rx_streaming_timer; |
607 | 386 | ||
387 | /* does the current role use GEM for encryption (AP or STA) */ | ||
388 | bool is_gem; | ||
389 | |||
608 | /* | 390 | /* |
609 | * This struct must be last! | 391 | * This struct must be last! |
610 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 392 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
@@ -679,17 +461,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | |||
679 | #define HW_BG_RATES_MASK 0xffff | 461 | #define HW_BG_RATES_MASK 0xffff |
680 | #define HW_HT_RATES_OFFSET 16 | 462 | #define HW_HT_RATES_OFFSET 16 |
681 | 463 | ||
682 | /* Quirks */ | ||
683 | |||
684 | /* Each RX/TX transaction requires an end-of-transaction transfer */ | ||
685 | #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) | ||
686 | |||
687 | /* wl127x and SPI don't support SDIO block size alignment */ | ||
688 | #define WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT BIT(2) | ||
689 | |||
690 | /* Older firmwares did not implement the FW logger over bus feature */ | ||
691 | #define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4) | ||
692 | |||
693 | #define WL12XX_HW_BLOCK_SIZE 256 | 464 | #define WL12XX_HW_BLOCK_SIZE 256 |
694 | 465 | ||
695 | #endif | 466 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/ti/wlcore/wl12xx_80211.h index 22b0bc98d7b5..22b0bc98d7b5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx_80211.h | |||
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/ti/wlcore/wl12xx_platform_data.c index 998e95895f9d..998e95895f9d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c +++ b/drivers/net/wireless/ti/wlcore/wl12xx_platform_data.c | |||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h new file mode 100644 index 000000000000..39f9fadfebd9 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -0,0 +1,448 @@ | |||
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 __WLCORE_H__ | ||
23 | #define __WLCORE_H__ | ||
24 | |||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #include "wl12xx.h" | ||
28 | #include "event.h" | ||
29 | |||
30 | /* The maximum number of Tx descriptors in all chip families */ | ||
31 | #define WLCORE_MAX_TX_DESCRIPTORS 32 | ||
32 | |||
33 | /* forward declaration */ | ||
34 | struct wl1271_tx_hw_descr; | ||
35 | enum wl_rx_buf_align; | ||
36 | |||
37 | struct wlcore_ops { | ||
38 | int (*identify_chip)(struct wl1271 *wl); | ||
39 | int (*identify_fw)(struct wl1271 *wl); | ||
40 | int (*boot)(struct wl1271 *wl); | ||
41 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | ||
42 | void *buf, size_t len); | ||
43 | void (*ack_event)(struct wl1271 *wl); | ||
44 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); | ||
45 | void (*set_tx_desc_blocks)(struct wl1271 *wl, | ||
46 | struct wl1271_tx_hw_descr *desc, | ||
47 | u32 blks, u32 spare_blks); | ||
48 | void (*set_tx_desc_data_len)(struct wl1271 *wl, | ||
49 | struct wl1271_tx_hw_descr *desc, | ||
50 | struct sk_buff *skb); | ||
51 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, | ||
52 | u32 rx_desc); | ||
53 | void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); | ||
54 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, | ||
55 | u32 data_len); | ||
56 | void (*tx_delayed_compl)(struct wl1271 *wl); | ||
57 | void (*tx_immediate_compl)(struct wl1271 *wl); | ||
58 | int (*hw_init)(struct wl1271 *wl); | ||
59 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | ||
60 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, | ||
61 | struct wl12xx_vif *wlvif); | ||
62 | s8 (*get_pg_ver)(struct wl1271 *wl); | ||
63 | void (*get_mac)(struct wl1271 *wl); | ||
64 | }; | ||
65 | |||
66 | enum wlcore_partitions { | ||
67 | PART_DOWN, | ||
68 | PART_WORK, | ||
69 | PART_BOOT, | ||
70 | PART_DRPW, | ||
71 | PART_TOP_PRCM_ELP_SOC, | ||
72 | PART_PHY_INIT, | ||
73 | |||
74 | PART_TABLE_LEN, | ||
75 | }; | ||
76 | |||
77 | struct wlcore_partition { | ||
78 | u32 size; | ||
79 | u32 start; | ||
80 | }; | ||
81 | |||
82 | struct wlcore_partition_set { | ||
83 | struct wlcore_partition mem; | ||
84 | struct wlcore_partition reg; | ||
85 | struct wlcore_partition mem2; | ||
86 | struct wlcore_partition mem3; | ||
87 | }; | ||
88 | |||
89 | enum wlcore_registers { | ||
90 | /* register addresses, used with partition translation */ | ||
91 | REG_ECPU_CONTROL, | ||
92 | REG_INTERRUPT_NO_CLEAR, | ||
93 | REG_INTERRUPT_ACK, | ||
94 | REG_COMMAND_MAILBOX_PTR, | ||
95 | REG_EVENT_MAILBOX_PTR, | ||
96 | REG_INTERRUPT_TRIG, | ||
97 | REG_INTERRUPT_MASK, | ||
98 | REG_PC_ON_RECOVERY, | ||
99 | REG_CHIP_ID_B, | ||
100 | REG_CMD_MBOX_ADDRESS, | ||
101 | |||
102 | /* data access memory addresses, used with partition translation */ | ||
103 | REG_SLV_MEM_DATA, | ||
104 | REG_SLV_REG_DATA, | ||
105 | |||
106 | /* raw data access memory addresses */ | ||
107 | REG_RAW_FW_STATUS_ADDR, | ||
108 | |||
109 | REG_TABLE_LEN, | ||
110 | }; | ||
111 | |||
112 | struct wl1271 { | ||
113 | struct ieee80211_hw *hw; | ||
114 | bool mac80211_registered; | ||
115 | |||
116 | struct device *dev; | ||
117 | |||
118 | void *if_priv; | ||
119 | |||
120 | struct wl1271_if_operations *if_ops; | ||
121 | |||
122 | void (*set_power)(bool enable); | ||
123 | int irq; | ||
124 | int ref_clock; | ||
125 | |||
126 | spinlock_t wl_lock; | ||
127 | |||
128 | enum wl1271_state state; | ||
129 | enum wl12xx_fw_type fw_type; | ||
130 | bool plt; | ||
131 | u8 last_vif_count; | ||
132 | struct mutex mutex; | ||
133 | |||
134 | unsigned long flags; | ||
135 | |||
136 | struct wlcore_partition_set curr_part; | ||
137 | |||
138 | struct wl1271_chip chip; | ||
139 | |||
140 | int cmd_box_addr; | ||
141 | |||
142 | u8 *fw; | ||
143 | size_t fw_len; | ||
144 | void *nvs; | ||
145 | size_t nvs_len; | ||
146 | |||
147 | s8 hw_pg_ver; | ||
148 | |||
149 | /* address read from the fuse ROM */ | ||
150 | u32 fuse_oui_addr; | ||
151 | u32 fuse_nic_addr; | ||
152 | |||
153 | /* we have up to 2 MAC addresses */ | ||
154 | struct mac_address addresses[2]; | ||
155 | int channel; | ||
156 | u8 system_hlid; | ||
157 | |||
158 | unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; | ||
159 | unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; | ||
160 | unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; | ||
161 | unsigned long rate_policies_map[ | ||
162 | BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; | ||
163 | |||
164 | struct list_head wlvif_list; | ||
165 | |||
166 | u8 sta_count; | ||
167 | u8 ap_count; | ||
168 | |||
169 | struct wl1271_acx_mem_map *target_mem_map; | ||
170 | |||
171 | /* Accounting for allocated / available TX blocks on HW */ | ||
172 | u32 tx_blocks_freed; | ||
173 | u32 tx_blocks_available; | ||
174 | u32 tx_allocated_blocks; | ||
175 | u32 tx_results_count; | ||
176 | |||
177 | /* Accounting for allocated / available Tx packets in HW */ | ||
178 | u32 tx_pkts_freed[NUM_TX_QUEUES]; | ||
179 | u32 tx_allocated_pkts[NUM_TX_QUEUES]; | ||
180 | |||
181 | /* Transmitted TX packets counter for chipset interface */ | ||
182 | u32 tx_packets_count; | ||
183 | |||
184 | /* Time-offset between host and chipset clocks */ | ||
185 | s64 time_offset; | ||
186 | |||
187 | /* Frames scheduled for transmission, not handled yet */ | ||
188 | int tx_queue_count[NUM_TX_QUEUES]; | ||
189 | long stopped_queues_map; | ||
190 | |||
191 | /* Frames received, not handled yet by mac80211 */ | ||
192 | struct sk_buff_head deferred_rx_queue; | ||
193 | |||
194 | /* Frames sent, not returned yet to mac80211 */ | ||
195 | struct sk_buff_head deferred_tx_queue; | ||
196 | |||
197 | struct work_struct tx_work; | ||
198 | struct workqueue_struct *freezable_wq; | ||
199 | |||
200 | /* Pending TX frames */ | ||
201 | unsigned long tx_frames_map[BITS_TO_LONGS(WLCORE_MAX_TX_DESCRIPTORS)]; | ||
202 | struct sk_buff *tx_frames[WLCORE_MAX_TX_DESCRIPTORS]; | ||
203 | int tx_frames_cnt; | ||
204 | |||
205 | /* FW Rx counter */ | ||
206 | u32 rx_counter; | ||
207 | |||
208 | /* Rx memory pool address */ | ||
209 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; | ||
210 | |||
211 | /* Intermediate buffer, used for packet aggregation */ | ||
212 | u8 *aggr_buf; | ||
213 | |||
214 | /* Reusable dummy packet template */ | ||
215 | struct sk_buff *dummy_packet; | ||
216 | |||
217 | /* Network stack work */ | ||
218 | struct work_struct netstack_work; | ||
219 | |||
220 | /* FW log buffer */ | ||
221 | u8 *fwlog; | ||
222 | |||
223 | /* Number of valid bytes in the FW log buffer */ | ||
224 | ssize_t fwlog_size; | ||
225 | |||
226 | /* Sysfs FW log entry readers wait queue */ | ||
227 | wait_queue_head_t fwlog_waitq; | ||
228 | |||
229 | /* Hardware recovery work */ | ||
230 | struct work_struct recovery_work; | ||
231 | |||
232 | /* Pointer that holds DMA-friendly block for the mailbox */ | ||
233 | struct event_mailbox *mbox; | ||
234 | |||
235 | /* The mbox event mask */ | ||
236 | u32 event_mask; | ||
237 | |||
238 | /* Mailbox pointers */ | ||
239 | u32 mbox_ptr[2]; | ||
240 | |||
241 | /* Are we currently scanning */ | ||
242 | struct ieee80211_vif *scan_vif; | ||
243 | struct wl1271_scan scan; | ||
244 | struct delayed_work scan_complete_work; | ||
245 | |||
246 | bool sched_scanning; | ||
247 | |||
248 | /* The current band */ | ||
249 | enum ieee80211_band band; | ||
250 | |||
251 | struct completion *elp_compl; | ||
252 | struct delayed_work elp_work; | ||
253 | |||
254 | /* in dBm */ | ||
255 | int power_level; | ||
256 | |||
257 | struct wl1271_stats stats; | ||
258 | |||
259 | __le32 buffer_32; | ||
260 | u32 buffer_cmd; | ||
261 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; | ||
262 | |||
263 | struct wl_fw_status *fw_status; | ||
264 | struct wl1271_tx_hw_res_if *tx_res_if; | ||
265 | |||
266 | /* Current chipset configuration */ | ||
267 | struct wlcore_conf conf; | ||
268 | |||
269 | bool sg_enabled; | ||
270 | |||
271 | bool enable_11a; | ||
272 | |||
273 | /* Most recently reported noise in dBm */ | ||
274 | s8 noise; | ||
275 | |||
276 | /* bands supported by this instance of wl12xx */ | ||
277 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
278 | |||
279 | int tcxo_clock; | ||
280 | |||
281 | /* | ||
282 | * wowlan trigger was configured during suspend. | ||
283 | * (currently, only "ANY" trigger is supported) | ||
284 | */ | ||
285 | bool wow_enabled; | ||
286 | bool irq_wake_enabled; | ||
287 | |||
288 | /* | ||
289 | * AP-mode - links indexed by HLID. The global and broadcast links | ||
290 | * are always active. | ||
291 | */ | ||
292 | struct wl1271_link links[WL12XX_MAX_LINKS]; | ||
293 | |||
294 | /* AP-mode - a bitmap of links currently in PS mode according to FW */ | ||
295 | u32 ap_fw_ps_map; | ||
296 | |||
297 | /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ | ||
298 | unsigned long ap_ps_map; | ||
299 | |||
300 | /* Quirks of specific hardware revisions */ | ||
301 | unsigned int quirks; | ||
302 | |||
303 | /* Platform limitations */ | ||
304 | unsigned int platform_quirks; | ||
305 | |||
306 | /* number of currently active RX BA sessions */ | ||
307 | int ba_rx_session_count; | ||
308 | |||
309 | /* AP-mode - number of currently connected stations */ | ||
310 | int active_sta_count; | ||
311 | |||
312 | /* last wlvif we transmitted from */ | ||
313 | struct wl12xx_vif *last_wlvif; | ||
314 | |||
315 | /* work to fire when Tx is stuck */ | ||
316 | struct delayed_work tx_watchdog_work; | ||
317 | |||
318 | struct wlcore_ops *ops; | ||
319 | /* pointer to the lower driver partition table */ | ||
320 | const struct wlcore_partition_set *ptable; | ||
321 | /* pointer to the lower driver register table */ | ||
322 | const int *rtable; | ||
323 | /* name of the firmwares to load - for PLT, single role, multi-role */ | ||
324 | const char *plt_fw_name; | ||
325 | const char *sr_fw_name; | ||
326 | const char *mr_fw_name; | ||
327 | |||
328 | /* per-chip-family private structure */ | ||
329 | void *priv; | ||
330 | |||
331 | /* number of TX descriptors the HW supports. */ | ||
332 | u32 num_tx_desc; | ||
333 | |||
334 | /* spare Tx blocks for normal/GEM operating modes */ | ||
335 | u32 normal_tx_spare; | ||
336 | u32 gem_tx_spare; | ||
337 | |||
338 | /* translate HW Tx rates to standard rate-indices */ | ||
339 | const u8 **band_rate_to_idx; | ||
340 | |||
341 | /* size of table for HW rates that can be received from chip */ | ||
342 | u8 hw_tx_rate_tbl_size; | ||
343 | |||
344 | /* this HW rate and below are considered HT rates for this chip */ | ||
345 | u8 hw_min_ht_rate; | ||
346 | |||
347 | /* HW HT (11n) capabilities */ | ||
348 | struct ieee80211_sta_ht_cap ht_cap; | ||
349 | |||
350 | /* size of the private FW status data */ | ||
351 | size_t fw_status_priv_len; | ||
352 | }; | ||
353 | |||
354 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | ||
355 | int __devexit wlcore_remove(struct platform_device *pdev); | ||
356 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); | ||
357 | int wlcore_free_hw(struct wl1271 *wl); | ||
358 | |||
359 | /* Firmware image load chunk size */ | ||
360 | #define CHUNK_SIZE 16384 | ||
361 | |||
362 | /* Quirks */ | ||
363 | |||
364 | /* Each RX/TX transaction requires an end-of-transaction transfer */ | ||
365 | #define WLCORE_QUIRK_END_OF_TRANSACTION BIT(0) | ||
366 | |||
367 | /* wl127x and SPI don't support SDIO block size alignment */ | ||
368 | #define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN BIT(2) | ||
369 | |||
370 | /* means aggregated Rx packets are aligned to a SDIO block */ | ||
371 | #define WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN BIT(3) | ||
372 | |||
373 | /* Older firmwares did not implement the FW logger over bus feature */ | ||
374 | #define WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4) | ||
375 | |||
376 | /* Older firmwares use an old NVS format */ | ||
377 | #define WLCORE_QUIRK_LEGACY_NVS BIT(5) | ||
378 | |||
379 | /* Some firmwares may not support ELP */ | ||
380 | #define WLCORE_QUIRK_NO_ELP BIT(6) | ||
381 | |||
382 | /* TODO: move to the lower drivers when all usages are abstracted */ | ||
383 | #define CHIP_ID_1271_PG10 (0x4030101) | ||
384 | #define CHIP_ID_1271_PG20 (0x4030111) | ||
385 | #define CHIP_ID_1283_PG10 (0x05030101) | ||
386 | #define CHIP_ID_1283_PG20 (0x05030111) | ||
387 | |||
388 | /* TODO: move all these common registers and values elsewhere */ | ||
389 | #define HW_ACCESS_ELP_CTRL_REG 0x1FFFC | ||
390 | |||
391 | /* ELP register commands */ | ||
392 | #define ELPCTRL_WAKE_UP 0x1 | ||
393 | #define ELPCTRL_WAKE_UP_WLAN_READY 0x5 | ||
394 | #define ELPCTRL_SLEEP 0x0 | ||
395 | /* ELP WLAN_READY bit */ | ||
396 | #define ELPCTRL_WLAN_READY 0x2 | ||
397 | |||
398 | /************************************************************************* | ||
399 | |||
400 | Interrupt Trigger Register (Host -> WiLink) | ||
401 | |||
402 | **************************************************************************/ | ||
403 | |||
404 | /* Hardware to Embedded CPU Interrupts - first 32-bit register set */ | ||
405 | |||
406 | /* | ||
407 | * The host sets this bit to inform the Wlan | ||
408 | * FW that a TX packet is in the XFER | ||
409 | * Buffer #0. | ||
410 | */ | ||
411 | #define INTR_TRIG_TX_PROC0 BIT(2) | ||
412 | |||
413 | /* | ||
414 | * The host sets this bit to inform the FW | ||
415 | * that it read a packet from RX XFER | ||
416 | * Buffer #0. | ||
417 | */ | ||
418 | #define INTR_TRIG_RX_PROC0 BIT(3) | ||
419 | |||
420 | #define INTR_TRIG_DEBUG_ACK BIT(4) | ||
421 | |||
422 | #define INTR_TRIG_STATE_CHANGED BIT(5) | ||
423 | |||
424 | /* Hardware to Embedded CPU Interrupts - second 32-bit register set */ | ||
425 | |||
426 | /* | ||
427 | * The host sets this bit to inform the FW | ||
428 | * that it read a packet from RX XFER | ||
429 | * Buffer #1. | ||
430 | */ | ||
431 | #define INTR_TRIG_RX_PROC1 BIT(17) | ||
432 | |||
433 | /* | ||
434 | * The host sets this bit to inform the Wlan | ||
435 | * hardware that a TX packet is in the XFER | ||
436 | * Buffer #1. | ||
437 | */ | ||
438 | #define INTR_TRIG_TX_PROC1 BIT(18) | ||
439 | |||
440 | #define ACX_SLV_SOFT_RESET_BIT BIT(1) | ||
441 | #define SOFT_RESET_MAX_TIME 1000000 | ||
442 | #define SOFT_RESET_STALL_TIME 1000 | ||
443 | |||
444 | #define ECPU_CONTROL_HALT 0x00000101 | ||
445 | |||
446 | #define WELP_ARM_COMMAND_VAL 0x4 | ||
447 | |||
448 | #endif /* __WLCORE_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig deleted file mode 100644 index af08c8609c63..000000000000 --- a/drivers/net/wireless/wl12xx/Kconfig +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | menuconfig WL12XX_MENU | ||
2 | tristate "TI wl12xx driver support" | ||
3 | depends on MAC80211 && EXPERIMENTAL | ||
4 | ---help--- | ||
5 | This will enable TI wl12xx driver support for the following chips: | ||
6 | wl1271, wl1273, wl1281 and wl1283. | ||
7 | The drivers make use of the mac80211 stack. | ||
8 | |||
9 | config WL12XX | ||
10 | tristate "TI wl12xx support" | ||
11 | depends on WL12XX_MENU && GENERIC_HARDIRQS | ||
12 | depends on INET | ||
13 | select FW_LOADER | ||
14 | ---help--- | ||
15 | This module adds support for wireless adapters based on TI wl1271 and | ||
16 | TI wl1273 chipsets. This module does *not* include support for wl1251. | ||
17 | For wl1251 support, use the separate homonymous driver instead. | ||
18 | |||
19 | If you choose to build a module, it will be called wl12xx. Say N if | ||
20 | unsure. | ||
21 | |||
22 | config WL12XX_SPI | ||
23 | tristate "TI wl12xx SPI support" | ||
24 | depends on WL12XX && SPI_MASTER | ||
25 | select CRC7 | ||
26 | ---help--- | ||
27 | This module adds support for the SPI interface of adapters using | ||
28 | TI wl12xx chipsets. Select this if your platform is using | ||
29 | the SPI bus. | ||
30 | |||
31 | If you choose to build a module, it'll be called wl12xx_spi. | ||
32 | Say N if unsure. | ||
33 | |||
34 | config WL12XX_SDIO | ||
35 | tristate "TI wl12xx SDIO support" | ||
36 | depends on WL12XX && MMC | ||
37 | ---help--- | ||
38 | This module adds support for the SDIO interface of adapters using | ||
39 | TI wl12xx chipsets. Select this if your platform is using | ||
40 | the SDIO bus. | ||
41 | |||
42 | If you choose to build a module, it'll be called wl12xx_sdio. | ||
43 | Say N if unsure. | ||
44 | |||
45 | config WL12XX_PLATFORM_DATA | ||
46 | bool | ||
47 | depends on WL12XX_SDIO != n || WL1251_SDIO != n | ||
48 | default y | ||
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile deleted file mode 100644 index 98f289c907a9..000000000000 --- a/drivers/net/wireless/wl12xx/Makefile +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ | ||
2 | boot.o init.o debugfs.o scan.o | ||
3 | |||
4 | wl12xx_spi-objs = spi.o | ||
5 | wl12xx_sdio-objs = sdio.o | ||
6 | |||
7 | wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o | ||
8 | obj-$(CONFIG_WL12XX) += wl12xx.o | ||
9 | obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o | ||
10 | obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o | ||
11 | |||
12 | # small builtin driver bit | ||
13 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | ||
14 | |||
15 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c deleted file mode 100644 index 954101d03f06..000000000000 --- a/drivers/net/wireless/wl12xx/boot.c +++ /dev/null | |||
@@ -1,786 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/slab.h> | ||
25 | #include <linux/wl12xx.h> | ||
26 | #include <linux/export.h> | ||
27 | |||
28 | #include "debug.h" | ||
29 | #include "acx.h" | ||
30 | #include "reg.h" | ||
31 | #include "boot.h" | ||
32 | #include "io.h" | ||
33 | #include "event.h" | ||
34 | #include "rx.h" | ||
35 | |||
36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | ||
37 | { | ||
38 | u32 cpu_ctrl; | ||
39 | |||
40 | /* 10.5.0 run the firmware (I) */ | ||
41 | cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); | ||
42 | |||
43 | /* 10.5.1 run the firmware (II) */ | ||
44 | cpu_ctrl |= flag; | ||
45 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | ||
46 | } | ||
47 | |||
48 | static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl) | ||
49 | { | ||
50 | unsigned int quirks = 0; | ||
51 | unsigned int *fw_ver = wl->chip.fw_ver; | ||
52 | |||
53 | /* Only new station firmwares support routing fw logs to the host */ | ||
54 | if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && | ||
55 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) | ||
56 | quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
57 | |||
58 | /* This feature is not yet supported for AP mode */ | ||
59 | if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) | ||
60 | quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED; | ||
61 | |||
62 | return quirks; | ||
63 | } | ||
64 | |||
65 | static void wl1271_parse_fw_ver(struct wl1271 *wl) | ||
66 | { | ||
67 | int ret; | ||
68 | |||
69 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", | ||
70 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], | ||
71 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], | ||
72 | &wl->chip.fw_ver[4]); | ||
73 | |||
74 | if (ret != 5) { | ||
75 | wl1271_warning("fw version incorrect value"); | ||
76 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | /* Check if any quirks are needed with older fw versions */ | ||
81 | wl->quirks |= wl12xx_get_fw_ver_quirks(wl); | ||
82 | } | ||
83 | |||
84 | static void wl1271_boot_fw_version(struct wl1271 *wl) | ||
85 | { | ||
86 | struct wl1271_static_data static_data; | ||
87 | |||
88 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), | ||
89 | false); | ||
90 | |||
91 | strncpy(wl->chip.fw_ver_str, static_data.fw_version, | ||
92 | sizeof(wl->chip.fw_ver_str)); | ||
93 | |||
94 | /* make sure the string is NULL-terminated */ | ||
95 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; | ||
96 | |||
97 | wl1271_parse_fw_ver(wl); | ||
98 | } | ||
99 | |||
100 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | ||
101 | size_t fw_data_len, u32 dest) | ||
102 | { | ||
103 | struct wl1271_partition_set partition; | ||
104 | int addr, chunk_num, partition_limit; | ||
105 | u8 *p, *chunk; | ||
106 | |||
107 | /* whal_FwCtrl_LoadFwImageSm() */ | ||
108 | |||
109 | wl1271_debug(DEBUG_BOOT, "starting firmware upload"); | ||
110 | |||
111 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", | ||
112 | fw_data_len, CHUNK_SIZE); | ||
113 | |||
114 | if ((fw_data_len % 4) != 0) { | ||
115 | wl1271_error("firmware length not multiple of four"); | ||
116 | return -EIO; | ||
117 | } | ||
118 | |||
119 | chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
120 | if (!chunk) { | ||
121 | wl1271_error("allocation for firmware upload chunk failed"); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition)); | ||
126 | partition.mem.start = dest; | ||
127 | wl1271_set_partition(wl, &partition); | ||
128 | |||
129 | /* 10.1 set partition limit and chunk num */ | ||
130 | chunk_num = 0; | ||
131 | partition_limit = wl12xx_part_table[PART_DOWN].mem.size; | ||
132 | |||
133 | while (chunk_num < fw_data_len / CHUNK_SIZE) { | ||
134 | /* 10.2 update partition, if needed */ | ||
135 | addr = dest + (chunk_num + 2) * CHUNK_SIZE; | ||
136 | if (addr > partition_limit) { | ||
137 | addr = dest + chunk_num * CHUNK_SIZE; | ||
138 | partition_limit = chunk_num * CHUNK_SIZE + | ||
139 | wl12xx_part_table[PART_DOWN].mem.size; | ||
140 | partition.mem.start = addr; | ||
141 | wl1271_set_partition(wl, &partition); | ||
142 | } | ||
143 | |||
144 | /* 10.3 upload the chunk */ | ||
145 | addr = dest + chunk_num * CHUNK_SIZE; | ||
146 | p = buf + chunk_num * CHUNK_SIZE; | ||
147 | memcpy(chunk, p, CHUNK_SIZE); | ||
148 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | ||
149 | p, addr); | ||
150 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); | ||
151 | |||
152 | chunk_num++; | ||
153 | } | ||
154 | |||
155 | /* 10.4 upload the last chunk */ | ||
156 | addr = dest + chunk_num * CHUNK_SIZE; | ||
157 | p = buf + chunk_num * CHUNK_SIZE; | ||
158 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | ||
159 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | ||
160 | fw_data_len % CHUNK_SIZE, p, addr); | ||
161 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | ||
162 | |||
163 | kfree(chunk); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int wl1271_boot_upload_firmware(struct wl1271 *wl) | ||
168 | { | ||
169 | u32 chunks, addr, len; | ||
170 | int ret = 0; | ||
171 | u8 *fw; | ||
172 | |||
173 | fw = wl->fw; | ||
174 | chunks = be32_to_cpup((__be32 *) fw); | ||
175 | fw += sizeof(u32); | ||
176 | |||
177 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); | ||
178 | |||
179 | while (chunks--) { | ||
180 | addr = be32_to_cpup((__be32 *) fw); | ||
181 | fw += sizeof(u32); | ||
182 | len = be32_to_cpup((__be32 *) fw); | ||
183 | fw += sizeof(u32); | ||
184 | |||
185 | if (len > 300000) { | ||
186 | wl1271_info("firmware chunk too long: %u", len); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", | ||
190 | chunks, addr, len); | ||
191 | ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); | ||
192 | if (ret != 0) | ||
193 | break; | ||
194 | fw += len; | ||
195 | } | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static int wl1271_boot_upload_nvs(struct wl1271 *wl) | ||
201 | { | ||
202 | size_t nvs_len, burst_len; | ||
203 | int i; | ||
204 | u32 dest_addr, val; | ||
205 | u8 *nvs_ptr, *nvs_aligned; | ||
206 | |||
207 | if (wl->nvs == NULL) | ||
208 | return -ENODEV; | ||
209 | |||
210 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
211 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | ||
212 | |||
213 | if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { | ||
214 | if (nvs->general_params.dual_mode_select) | ||
215 | wl->enable_11a = true; | ||
216 | } else { | ||
217 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
218 | wl->nvs_len, | ||
219 | sizeof(struct wl128x_nvs_file)); | ||
220 | kfree(wl->nvs); | ||
221 | wl->nvs = NULL; | ||
222 | wl->nvs_len = 0; | ||
223 | return -EILSEQ; | ||
224 | } | ||
225 | |||
226 | /* only the first part of the NVS needs to be uploaded */ | ||
227 | nvs_len = sizeof(nvs->nvs); | ||
228 | nvs_ptr = (u8 *)nvs->nvs; | ||
229 | |||
230 | } else { | ||
231 | struct wl1271_nvs_file *nvs = | ||
232 | (struct wl1271_nvs_file *)wl->nvs; | ||
233 | /* | ||
234 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz | ||
235 | * band configurations) can be removed when those NVS files stop | ||
236 | * floating around. | ||
237 | */ | ||
238 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || | ||
239 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { | ||
240 | if (nvs->general_params.dual_mode_select) | ||
241 | wl->enable_11a = true; | ||
242 | } | ||
243 | |||
244 | if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && | ||
245 | (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
246 | wl->enable_11a)) { | ||
247 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
248 | wl->nvs_len, sizeof(struct wl1271_nvs_file)); | ||
249 | kfree(wl->nvs); | ||
250 | wl->nvs = NULL; | ||
251 | wl->nvs_len = 0; | ||
252 | return -EILSEQ; | ||
253 | } | ||
254 | |||
255 | /* only the first part of the NVS needs to be uploaded */ | ||
256 | nvs_len = sizeof(nvs->nvs); | ||
257 | nvs_ptr = (u8 *) nvs->nvs; | ||
258 | } | ||
259 | |||
260 | /* update current MAC address to NVS */ | ||
261 | nvs_ptr[11] = wl->addresses[0].addr[0]; | ||
262 | nvs_ptr[10] = wl->addresses[0].addr[1]; | ||
263 | nvs_ptr[6] = wl->addresses[0].addr[2]; | ||
264 | nvs_ptr[5] = wl->addresses[0].addr[3]; | ||
265 | nvs_ptr[4] = wl->addresses[0].addr[4]; | ||
266 | nvs_ptr[3] = wl->addresses[0].addr[5]; | ||
267 | |||
268 | /* | ||
269 | * Layout before the actual NVS tables: | ||
270 | * 1 byte : burst length. | ||
271 | * 2 bytes: destination address. | ||
272 | * n bytes: data to burst copy. | ||
273 | * | ||
274 | * This is ended by a 0 length, then the NVS tables. | ||
275 | */ | ||
276 | |||
277 | /* FIXME: Do we need to check here whether the LSB is 1? */ | ||
278 | while (nvs_ptr[0]) { | ||
279 | burst_len = nvs_ptr[0]; | ||
280 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); | ||
281 | |||
282 | /* | ||
283 | * Due to our new wl1271_translate_reg_addr function, | ||
284 | * we need to add the REGISTER_BASE to the destination | ||
285 | */ | ||
286 | dest_addr += REGISTERS_BASE; | ||
287 | |||
288 | /* We move our pointer to the data */ | ||
289 | nvs_ptr += 3; | ||
290 | |||
291 | for (i = 0; i < burst_len; i++) { | ||
292 | if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) | ||
293 | goto out_badnvs; | ||
294 | |||
295 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | ||
296 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | ||
297 | |||
298 | wl1271_debug(DEBUG_BOOT, | ||
299 | "nvs burst write 0x%x: 0x%x", | ||
300 | dest_addr, val); | ||
301 | wl1271_write32(wl, dest_addr, val); | ||
302 | |||
303 | nvs_ptr += 4; | ||
304 | dest_addr += 4; | ||
305 | } | ||
306 | |||
307 | if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) | ||
308 | goto out_badnvs; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * We've reached the first zero length, the first NVS table | ||
313 | * is located at an aligned offset which is at least 7 bytes further. | ||
314 | * NOTE: The wl->nvs->nvs element must be first, in order to | ||
315 | * simplify the casting, we assume it is at the beginning of | ||
316 | * the wl->nvs structure. | ||
317 | */ | ||
318 | nvs_ptr = (u8 *)wl->nvs + | ||
319 | ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); | ||
320 | |||
321 | if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) | ||
322 | goto out_badnvs; | ||
323 | |||
324 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | ||
325 | |||
326 | /* Now we must set the partition correctly */ | ||
327 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); | ||
328 | |||
329 | /* Copy the NVS tables to a new block to ensure alignment */ | ||
330 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | ||
331 | if (!nvs_aligned) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | /* And finally we upload the NVS tables */ | ||
335 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); | ||
336 | |||
337 | kfree(nvs_aligned); | ||
338 | return 0; | ||
339 | |||
340 | out_badnvs: | ||
341 | wl1271_error("nvs data is malformed"); | ||
342 | return -EILSEQ; | ||
343 | } | ||
344 | |||
345 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | ||
346 | { | ||
347 | wl1271_enable_interrupts(wl); | ||
348 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | ||
349 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | ||
350 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | ||
351 | } | ||
352 | |||
353 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | ||
354 | { | ||
355 | unsigned long timeout; | ||
356 | u32 boot_data; | ||
357 | |||
358 | /* perform soft reset */ | ||
359 | wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | ||
360 | |||
361 | /* SOFT_RESET is self clearing */ | ||
362 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | ||
363 | while (1) { | ||
364 | boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); | ||
365 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | ||
366 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | ||
367 | break; | ||
368 | |||
369 | if (time_after(jiffies, timeout)) { | ||
370 | /* 1.2 check pWhalBus->uSelfClearTime if the | ||
371 | * timeout was reached */ | ||
372 | wl1271_error("soft reset timeout"); | ||
373 | return -1; | ||
374 | } | ||
375 | |||
376 | udelay(SOFT_RESET_STALL_TIME); | ||
377 | } | ||
378 | |||
379 | /* disable Rx/Tx */ | ||
380 | wl1271_write32(wl, ENABLE, 0x0); | ||
381 | |||
382 | /* disable auto calibration on start*/ | ||
383 | wl1271_write32(wl, SPARE_A2, 0xffff); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int wl1271_boot_run_firmware(struct wl1271 *wl) | ||
389 | { | ||
390 | int loop, ret; | ||
391 | u32 chip_id, intr; | ||
392 | |||
393 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | ||
394 | |||
395 | chip_id = wl1271_read32(wl, CHIP_ID_B); | ||
396 | |||
397 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | ||
398 | |||
399 | if (chip_id != wl->chip.id) { | ||
400 | wl1271_error("chip id doesn't match after firmware boot"); | ||
401 | return -EIO; | ||
402 | } | ||
403 | |||
404 | /* wait for init to complete */ | ||
405 | loop = 0; | ||
406 | while (loop++ < INIT_LOOP) { | ||
407 | udelay(INIT_LOOP_DELAY); | ||
408 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | ||
409 | |||
410 | if (intr == 0xffffffff) { | ||
411 | wl1271_error("error reading hardware complete " | ||
412 | "init indication"); | ||
413 | return -EIO; | ||
414 | } | ||
415 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | ||
416 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { | ||
417 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, | ||
418 | WL1271_ACX_INTR_INIT_COMPLETE); | ||
419 | break; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (loop > INIT_LOOP) { | ||
424 | wl1271_error("timeout waiting for the hardware to " | ||
425 | "complete initialization"); | ||
426 | return -EIO; | ||
427 | } | ||
428 | |||
429 | /* get hardware config command mail box */ | ||
430 | wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); | ||
431 | |||
432 | /* get hardware config event mail box */ | ||
433 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); | ||
434 | |||
435 | /* set the working partition to its "running" mode offset */ | ||
436 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); | ||
437 | |||
438 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", | ||
439 | wl->cmd_box_addr, wl->event_box_addr); | ||
440 | |||
441 | wl1271_boot_fw_version(wl); | ||
442 | |||
443 | /* | ||
444 | * in case of full asynchronous mode the firmware event must be | ||
445 | * ready to receive event from the command mailbox | ||
446 | */ | ||
447 | |||
448 | /* unmask required mbox events */ | ||
449 | wl->event_mask = BSS_LOSE_EVENT_ID | | ||
450 | SCAN_COMPLETE_EVENT_ID | | ||
451 | ROLE_STOP_COMPLETE_EVENT_ID | | ||
452 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
453 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | ||
454 | SOFT_GEMINI_SENSE_EVENT_ID | | ||
455 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
456 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
457 | DUMMY_PACKET_EVENT_ID | | ||
458 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
459 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
460 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
461 | INACTIVE_STA_EVENT_ID | | ||
462 | MAX_TX_RETRY_EVENT_ID | | ||
463 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | ||
464 | |||
465 | ret = wl1271_event_unmask(wl); | ||
466 | if (ret < 0) { | ||
467 | wl1271_error("EVENT mask setting failed"); | ||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | wl1271_event_mbox_config(wl); | ||
472 | |||
473 | /* firmware startup completed */ | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) | ||
478 | { | ||
479 | u32 polarity; | ||
480 | |||
481 | polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY); | ||
482 | |||
483 | /* We use HIGH polarity, so unset the LOW bit */ | ||
484 | polarity &= ~POLARITY_LOW; | ||
485 | wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | ||
491 | { | ||
492 | u16 spare_reg; | ||
493 | |||
494 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ | ||
495 | spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); | ||
496 | if (spare_reg == 0xFFFF) | ||
497 | return -EFAULT; | ||
498 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); | ||
499 | wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); | ||
500 | |||
501 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ | ||
502 | wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, | ||
503 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); | ||
504 | |||
505 | /* Delay execution for 15msec, to let the HW settle */ | ||
506 | mdelay(15); | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | ||
512 | { | ||
513 | u16 tcxo_detection; | ||
514 | |||
515 | tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG); | ||
516 | if (tcxo_detection & TCXO_DET_FAILED) | ||
517 | return false; | ||
518 | |||
519 | return true; | ||
520 | } | ||
521 | |||
522 | static bool wl128x_is_fref_valid(struct wl1271 *wl) | ||
523 | { | ||
524 | u16 fref_detection; | ||
525 | |||
526 | fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG); | ||
527 | if (fref_detection & FREF_CLK_DETECT_FAIL) | ||
528 | return false; | ||
529 | |||
530 | return true; | ||
531 | } | ||
532 | |||
533 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) | ||
534 | { | ||
535 | wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); | ||
536 | wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
537 | wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | ||
543 | { | ||
544 | u16 spare_reg; | ||
545 | u16 pll_config; | ||
546 | u8 input_freq; | ||
547 | |||
548 | /* Mask bits [3:1] in the sys_clk_cfg register */ | ||
549 | spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); | ||
550 | if (spare_reg == 0xFFFF) | ||
551 | return -EFAULT; | ||
552 | spare_reg |= BIT(2); | ||
553 | wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); | ||
554 | |||
555 | /* Handle special cases of the TCXO clock */ | ||
556 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | ||
557 | wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) | ||
558 | return wl128x_manually_configure_mcs_pll(wl); | ||
559 | |||
560 | /* Set the input frequency according to the selected clock source */ | ||
561 | input_freq = (clk & 1) + 1; | ||
562 | |||
563 | pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG); | ||
564 | if (pll_config == 0xFFFF) | ||
565 | return -EFAULT; | ||
566 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); | ||
567 | pll_config |= MCS_PLL_ENABLE_HP; | ||
568 | wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * WL128x has two clocks input - TCXO and FREF. | ||
575 | * TCXO is the main clock of the device, while FREF is used to sync | ||
576 | * between the GPS and the cellular modem. | ||
577 | * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used | ||
578 | * as the WLAN/BT main clock. | ||
579 | */ | ||
580 | static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | ||
581 | { | ||
582 | u16 sys_clk_cfg; | ||
583 | |||
584 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | ||
585 | if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || | ||
586 | wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { | ||
587 | if (!wl128x_switch_tcxo_to_fref(wl)) | ||
588 | return -EINVAL; | ||
589 | goto fref_clk; | ||
590 | } | ||
591 | |||
592 | /* Query the HW, to determine which clock source we should use */ | ||
593 | sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); | ||
594 | if (sys_clk_cfg == 0xFFFF) | ||
595 | return -EINVAL; | ||
596 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) | ||
597 | goto fref_clk; | ||
598 | |||
599 | /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ | ||
600 | if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || | ||
601 | wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { | ||
602 | if (!wl128x_switch_tcxo_to_fref(wl)) | ||
603 | return -EINVAL; | ||
604 | goto fref_clk; | ||
605 | } | ||
606 | |||
607 | /* TCXO clock is selected */ | ||
608 | if (!wl128x_is_tcxo_valid(wl)) | ||
609 | return -EINVAL; | ||
610 | *selected_clock = wl->tcxo_clock; | ||
611 | goto config_mcs_pll; | ||
612 | |||
613 | fref_clk: | ||
614 | /* FREF clock is selected */ | ||
615 | if (!wl128x_is_fref_valid(wl)) | ||
616 | return -EINVAL; | ||
617 | *selected_clock = wl->ref_clock; | ||
618 | |||
619 | config_mcs_pll: | ||
620 | return wl128x_configure_mcs_pll(wl, *selected_clock); | ||
621 | } | ||
622 | |||
623 | static int wl127x_boot_clk(struct wl1271 *wl) | ||
624 | { | ||
625 | u32 pause; | ||
626 | u32 clk; | ||
627 | |||
628 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | ||
629 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | ||
630 | |||
631 | if (wl->ref_clock == CONF_REF_CLK_19_2_E || | ||
632 | wl->ref_clock == CONF_REF_CLK_38_4_E || | ||
633 | wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) | ||
634 | /* ref clk: 19.2/38.4/38.4-XTAL */ | ||
635 | clk = 0x3; | ||
636 | else if (wl->ref_clock == CONF_REF_CLK_26_E || | ||
637 | wl->ref_clock == CONF_REF_CLK_52_E) | ||
638 | /* ref clk: 26/52 */ | ||
639 | clk = 0x5; | ||
640 | else | ||
641 | return -EINVAL; | ||
642 | |||
643 | if (wl->ref_clock != CONF_REF_CLK_19_2_E) { | ||
644 | u16 val; | ||
645 | /* Set clock type (open drain) */ | ||
646 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | ||
647 | val &= FREF_CLK_TYPE_BITS; | ||
648 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | ||
649 | |||
650 | /* Set clock pull mode (no pull) */ | ||
651 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
652 | val |= NO_PULL; | ||
653 | wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
654 | } else { | ||
655 | u16 val; | ||
656 | /* Set clock polarity */ | ||
657 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY); | ||
658 | val &= FREF_CLK_POLARITY_BITS; | ||
659 | val |= CLK_REQ_OUTN_SEL; | ||
660 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | ||
661 | } | ||
662 | |||
663 | wl1271_write32(wl, PLL_PARAMETERS, clk); | ||
664 | |||
665 | pause = wl1271_read32(wl, PLL_PARAMETERS); | ||
666 | |||
667 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | ||
668 | |||
669 | pause &= ~(WU_COUNTER_PAUSE_VAL); | ||
670 | pause |= WU_COUNTER_PAUSE_VAL; | ||
671 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | /* uploads NVS and firmware */ | ||
677 | int wl1271_load_firmware(struct wl1271 *wl) | ||
678 | { | ||
679 | int ret = 0; | ||
680 | u32 tmp, clk; | ||
681 | int selected_clock = -1; | ||
682 | |||
683 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
684 | ret = wl128x_boot_clk(wl, &selected_clock); | ||
685 | if (ret < 0) | ||
686 | goto out; | ||
687 | } else { | ||
688 | ret = wl127x_boot_clk(wl); | ||
689 | if (ret < 0) | ||
690 | goto out; | ||
691 | } | ||
692 | |||
693 | /* Continue the ELP wake up sequence */ | ||
694 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | ||
695 | udelay(500); | ||
696 | |||
697 | wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); | ||
698 | |||
699 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | ||
700 | to be used by DRPw FW. The RTRIM value will be added by the FW | ||
701 | before taking DRPw out of reset */ | ||
702 | |||
703 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); | ||
704 | clk = wl1271_read32(wl, DRPW_SCRATCH_START); | ||
705 | |||
706 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | ||
707 | |||
708 | if (wl->chip.id == CHIP_ID_1283_PG20) { | ||
709 | clk |= ((selected_clock & 0x3) << 1) << 4; | ||
710 | } else { | ||
711 | clk |= (wl->ref_clock << 1) << 4; | ||
712 | } | ||
713 | |||
714 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); | ||
715 | |||
716 | wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); | ||
717 | |||
718 | /* Disable interrupts */ | ||
719 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | ||
720 | |||
721 | ret = wl1271_boot_soft_reset(wl); | ||
722 | if (ret < 0) | ||
723 | goto out; | ||
724 | |||
725 | /* 2. start processing NVS file */ | ||
726 | ret = wl1271_boot_upload_nvs(wl); | ||
727 | if (ret < 0) | ||
728 | goto out; | ||
729 | |||
730 | /* write firmware's last address (ie. it's length) to | ||
731 | * ACX_EEPROMLESS_IND_REG */ | ||
732 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | ||
733 | |||
734 | wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); | ||
735 | |||
736 | tmp = wl1271_read32(wl, CHIP_ID_B); | ||
737 | |||
738 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | ||
739 | |||
740 | /* 6. read the EEPROM parameters */ | ||
741 | tmp = wl1271_read32(wl, SCR_PAD2); | ||
742 | |||
743 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | ||
744 | * to upload_fw) */ | ||
745 | |||
746 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
747 | wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); | ||
748 | |||
749 | ret = wl1271_boot_upload_firmware(wl); | ||
750 | if (ret < 0) | ||
751 | goto out; | ||
752 | |||
753 | out: | ||
754 | return ret; | ||
755 | } | ||
756 | EXPORT_SYMBOL_GPL(wl1271_load_firmware); | ||
757 | |||
758 | int wl1271_boot(struct wl1271 *wl) | ||
759 | { | ||
760 | int ret; | ||
761 | |||
762 | /* upload NVS and firmware */ | ||
763 | ret = wl1271_load_firmware(wl); | ||
764 | if (ret) | ||
765 | return ret; | ||
766 | |||
767 | /* 10.5 start firmware */ | ||
768 | ret = wl1271_boot_run_firmware(wl); | ||
769 | if (ret < 0) | ||
770 | goto out; | ||
771 | |||
772 | ret = wl1271_boot_write_irq_polarity(wl); | ||
773 | if (ret < 0) | ||
774 | goto out; | ||
775 | |||
776 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | ||
777 | WL1271_ACX_ALL_EVENTS_VECTOR); | ||
778 | |||
779 | /* Enable firmware interrupts now */ | ||
780 | wl1271_boot_enable_interrupts(wl); | ||
781 | |||
782 | wl1271_event_mbox_config(wl); | ||
783 | |||
784 | out: | ||
785 | return ret; | ||
786 | } | ||
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h deleted file mode 100644 index c3adc09f403d..000000000000 --- a/drivers/net/wireless/wl12xx/boot.h +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __BOOT_H__ | ||
25 | #define __BOOT_H__ | ||
26 | |||
27 | #include "wl12xx.h" | ||
28 | |||
29 | int wl1271_boot(struct wl1271 *wl); | ||
30 | int wl1271_load_firmware(struct wl1271 *wl); | ||
31 | |||
32 | #define WL1271_NO_SUBBANDS 8 | ||
33 | #define WL1271_NO_POWER_LEVELS 4 | ||
34 | #define WL1271_FW_VERSION_MAX_LEN 20 | ||
35 | |||
36 | struct wl1271_static_data { | ||
37 | u8 mac_address[ETH_ALEN]; | ||
38 | u8 padding[2]; | ||
39 | u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; | ||
40 | u32 hw_version; | ||
41 | u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; | ||
42 | }; | ||
43 | |||
44 | /* number of times we try to read the INIT interrupt */ | ||
45 | #define INIT_LOOP 20000 | ||
46 | |||
47 | /* delay between retries */ | ||
48 | #define INIT_LOOP_DELAY 50 | ||
49 | |||
50 | #define WU_COUNTER_PAUSE_VAL 0x3FF | ||
51 | #define WELP_ARM_COMMAND_VAL 0x4 | ||
52 | |||
53 | #define OCP_REG_POLARITY 0x0064 | ||
54 | #define OCP_REG_CLK_TYPE 0x0448 | ||
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | ||
56 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
57 | |||
58 | #define CMD_MBOX_ADDRESS 0x407B4 | ||
59 | |||
60 | #define POLARITY_LOW BIT(1) | ||
61 | #define NO_PULL (BIT(14) | BIT(15)) | ||
62 | |||
63 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | ||
64 | #define CLK_REQ_PRCM 0x100 | ||
65 | #define FREF_CLK_POLARITY_BITS 0xfffff8ff | ||
66 | #define CLK_REQ_OUTN_SEL 0x700 | ||
67 | |||
68 | /* PLL configuration algorithm for wl128x */ | ||
69 | #define SYS_CLK_CFG_REG 0x2200 | ||
70 | /* Bit[0] - 0-TCXO, 1-FREF */ | ||
71 | #define MCS_PLL_CLK_SEL_FREF BIT(0) | ||
72 | /* Bit[3:2] - 01-TCXO, 10-FREF */ | ||
73 | #define WL_CLK_REQ_TYPE_FREF BIT(3) | ||
74 | #define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) | ||
75 | /* Bit[4] - 0-TCXO, 1-FREF */ | ||
76 | #define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) | ||
77 | |||
78 | #define TCXO_ILOAD_INT_REG 0x2264 | ||
79 | #define TCXO_CLK_DETECT_REG 0x2266 | ||
80 | |||
81 | #define TCXO_DET_FAILED BIT(4) | ||
82 | |||
83 | #define FREF_ILOAD_INT_REG 0x2084 | ||
84 | #define FREF_CLK_DETECT_REG 0x2086 | ||
85 | #define FREF_CLK_DETECT_FAIL BIT(4) | ||
86 | |||
87 | /* Use this reg for masking during driver access */ | ||
88 | #define WL_SPARE_REG 0x2320 | ||
89 | #define WL_SPARE_VAL BIT(2) | ||
90 | /* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ | ||
91 | #define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) | ||
92 | |||
93 | #define PLL_LOCK_COUNTERS_REG 0xD8C | ||
94 | #define PLL_LOCK_COUNTERS_COEX 0x0F | ||
95 | #define PLL_LOCK_COUNTERS_MCS 0xF0 | ||
96 | #define MCS_PLL_OVERRIDE_REG 0xD90 | ||
97 | #define MCS_PLL_CONFIG_REG 0xD92 | ||
98 | #define MCS_SEL_IN_FREQ_MASK 0x0070 | ||
99 | #define MCS_SEL_IN_FREQ_SHIFT 4 | ||
100 | #define MCS_PLL_CONFIG_REG_VAL 0x73 | ||
101 | #define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) | ||
102 | |||
103 | #define MCS_PLL_M_REG 0xD94 | ||
104 | #define MCS_PLL_N_REG 0xD96 | ||
105 | #define MCS_PLL_M_REG_VAL 0xC8 | ||
106 | #define MCS_PLL_N_REG_VAL 0x07 | ||
107 | |||
108 | #define SDIO_IO_DS 0xd14 | ||
109 | |||
110 | /* SDIO/wSPI DS configuration values */ | ||
111 | enum { | ||
112 | HCI_IO_DS_8MA = 0, | ||
113 | HCI_IO_DS_4MA = 1, /* default */ | ||
114 | HCI_IO_DS_6MA = 2, | ||
115 | HCI_IO_DS_2MA = 3, | ||
116 | }; | ||
117 | |||
118 | /* end PLL configuration algorithm for wl128x */ | ||
119 | |||
120 | #endif | ||