diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-09-21 15:49:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-09-21 15:49:14 -0400 |
commit | b618f6f885579a6237e5bf4582fa6167972ddef4 (patch) | |
tree | b11508178570b98ce9cb2d76ecebd046a6f0e77c | |
parent | 462fb2af9788a82a534f8184abfde31574e1cfa0 (diff) | |
parent | 6e5c2b4e8addfaab8ef54dedaf7b607e1585c35b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
arch/arm/mach-omap2/board-omap3pandora.c
drivers/net/wireless/ath/ath5k/base.c
155 files changed, 17208 insertions, 3272 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 102352e6d61d..017bf493166e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1120,6 +1120,13 @@ W: http://wireless.kernel.org/en/users/Drivers/ar9170 | |||
1120 | S: Maintained | 1120 | S: Maintained |
1121 | F: drivers/net/wireless/ath/ar9170/ | 1121 | F: drivers/net/wireless/ath/ar9170/ |
1122 | 1122 | ||
1123 | CARL9170 LINUX COMMUNITY WIRELESS DRIVER | ||
1124 | M: Christian Lamparter <chunkeey@googlemail.com> | ||
1125 | L: linux-wireless@vger.kernel.org | ||
1126 | W: http://wireless.kernel.org/en/users/Drivers/carl9170 | ||
1127 | S: Maintained | ||
1128 | F: drivers/net/wireless/ath/carl9170/ | ||
1129 | |||
1123 | ATK0110 HWMON DRIVER | 1130 | ATK0110 HWMON DRIVER |
1124 | M: Luca Tettamanti <kronos.it@gmail.com> | 1131 | M: Luca Tettamanti <kronos.it@gmail.com> |
1125 | L: lm-sensors@lm-sensors.org | 1132 | L: lm-sensors@lm-sensors.org |
@@ -6427,7 +6434,7 @@ W: http://wireless.kernel.org | |||
6427 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 6434 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
6428 | S: Maintained | 6435 | S: Maintained |
6429 | F: drivers/net/wireless/wl12xx/wl1271* | 6436 | F: drivers/net/wireless/wl12xx/wl1271* |
6430 | F: include/linux/spi/wl12xx.h | 6437 | F: include/linux/wl12xx.h |
6431 | 6438 | ||
6432 | WL3501 WIRELESS PCMCIA CARD DRIVER | 6439 | WL3501 WIRELESS PCMCIA CARD DRIVER |
6433 | M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 6440 | M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> |
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index dd3af2be13be..7ea1eb4a26b4 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/spi/ads7846.h> | 25 | #include <linux/spi/ads7846.h> |
26 | #include <linux/regulator/machine.h> | 26 | #include <linux/regulator/machine.h> |
27 | #include <linux/i2c/twl.h> | 27 | #include <linux/i2c/twl.h> |
28 | #include <linux/spi/wl12xx.h> | 28 | #include <linux/wl12xx.h> |
29 | #include <linux/mtd/partitions.h> | 29 | #include <linux/mtd/partitions.h> |
30 | #include <linux/mtd/nand.h> | 30 | #include <linux/mtd/nand.h> |
31 | #include <linux/leds.h> | 31 | #include <linux/leds.h> |
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 9a5eb87425fc..ce28a851dcd3 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/input.h> | 14 | #include <linux/input.h> |
15 | #include <linux/input/matrix_keypad.h> | 15 | #include <linux/input/matrix_keypad.h> |
16 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
17 | #include <linux/spi/wl12xx.h> | 17 | #include <linux/wl12xx.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/i2c/twl.h> | 19 | #include <linux/i2c/twl.h> |
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 6b3984964cc5..6aa0728fa15d 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/i2c/twl.h> | 17 | #include <linux/i2c/twl.h> |
18 | #include <linux/regulator/machine.h> | 18 | #include <linux/regulator/machine.h> |
19 | #include <linux/regulator/fixed.h> | ||
20 | #include <linux/wl12xx.h> | ||
19 | 21 | ||
20 | #include <asm/mach-types.h> | 22 | #include <asm/mach-types.h> |
21 | #include <asm/mach/arch.h> | 23 | #include <asm/mach/arch.h> |
@@ -27,6 +29,9 @@ | |||
27 | #include "mux.h" | 29 | #include "mux.h" |
28 | #include "hsmmc.h" | 30 | #include "hsmmc.h" |
29 | 31 | ||
32 | #define OMAP_ZOOM_WLAN_PMENA_GPIO (101) | ||
33 | #define OMAP_ZOOM_WLAN_IRQ_GPIO (162) | ||
34 | |||
30 | /* Zoom2 has Qwerty keyboard*/ | 35 | /* Zoom2 has Qwerty keyboard*/ |
31 | static int board_keymap[] = { | 36 | static int board_keymap[] = { |
32 | KEY(0, 0, KEY_E), | 37 | KEY(0, 0, KEY_E), |
@@ -106,6 +111,11 @@ static struct regulator_consumer_supply zoom_vmmc2_supply = { | |||
106 | .supply = "vmmc", | 111 | .supply = "vmmc", |
107 | }; | 112 | }; |
108 | 113 | ||
114 | static struct regulator_consumer_supply zoom_vmmc3_supply = { | ||
115 | .supply = "vmmc", | ||
116 | .dev_name = "mmci-omap-hs.2", | ||
117 | }; | ||
118 | |||
109 | /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ | 119 | /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ |
110 | static struct regulator_init_data zoom_vmmc1 = { | 120 | static struct regulator_init_data zoom_vmmc1 = { |
111 | .constraints = { | 121 | .constraints = { |
@@ -151,6 +161,38 @@ static struct regulator_init_data zoom_vsim = { | |||
151 | .consumer_supplies = &zoom_vsim_supply, | 161 | .consumer_supplies = &zoom_vsim_supply, |
152 | }; | 162 | }; |
153 | 163 | ||
164 | static struct regulator_init_data zoom_vmmc3 = { | ||
165 | .constraints = { | ||
166 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
167 | }, | ||
168 | .num_consumer_supplies = 1, | ||
169 | .consumer_supplies = &zoom_vmmc3_supply, | ||
170 | }; | ||
171 | |||
172 | static struct fixed_voltage_config zoom_vwlan = { | ||
173 | .supply_name = "vwl1271", | ||
174 | .microvolts = 1800000, /* 1.8V */ | ||
175 | .gpio = OMAP_ZOOM_WLAN_PMENA_GPIO, | ||
176 | .startup_delay = 70000, /* 70msec */ | ||
177 | .enable_high = 1, | ||
178 | .enabled_at_boot = 0, | ||
179 | .init_data = &zoom_vmmc3, | ||
180 | }; | ||
181 | |||
182 | static struct platform_device omap_vwlan_device = { | ||
183 | .name = "reg-fixed-voltage", | ||
184 | .id = 1, | ||
185 | .dev = { | ||
186 | .platform_data = &zoom_vwlan, | ||
187 | }, | ||
188 | }; | ||
189 | |||
190 | struct wl12xx_platform_data omap_zoom_wlan_data __initdata = { | ||
191 | .irq = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO), | ||
192 | /* ZOOM ref clock is 26 MHz */ | ||
193 | .board_ref_clock = 1, | ||
194 | }; | ||
195 | |||
154 | static struct omap2_hsmmc_info mmc[] __initdata = { | 196 | static struct omap2_hsmmc_info mmc[] __initdata = { |
155 | { | 197 | { |
156 | .name = "external", | 198 | .name = "external", |
@@ -168,6 +210,14 @@ static struct omap2_hsmmc_info mmc[] __initdata = { | |||
168 | .nonremovable = true, | 210 | .nonremovable = true, |
169 | .power_saving = true, | 211 | .power_saving = true, |
170 | }, | 212 | }, |
213 | { | ||
214 | .name = "wl1271", | ||
215 | .mmc = 3, | ||
216 | .wires = 4, | ||
217 | .gpio_wp = -EINVAL, | ||
218 | .gpio_cd = -EINVAL, | ||
219 | .nonremovable = true, | ||
220 | }, | ||
171 | {} /* Terminator */ | 221 | {} /* Terminator */ |
172 | }; | 222 | }; |
173 | 223 | ||
@@ -279,7 +329,11 @@ static void enable_board_wakeup_source(void) | |||
279 | 329 | ||
280 | void __init zoom_peripherals_init(void) | 330 | void __init zoom_peripherals_init(void) |
281 | { | 331 | { |
332 | if (wl12xx_set_platform_data(&omap_zoom_wlan_data)) | ||
333 | pr_err("error setting wl12xx data\n"); | ||
334 | |||
282 | omap_i2c_init(); | 335 | omap_i2c_init(); |
336 | platform_device_register(&omap_vwlan_device); | ||
283 | usb_musb_init(&musb_board_data); | 337 | usb_musb_init(&musb_board_data); |
284 | enable_board_wakeup_source(); | 338 | enable_board_wakeup_source(); |
285 | } | 339 | } |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 5d4ce4d2b32b..85af697574a6 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -50,5 +50,7 @@ obj-$(CONFIG_ATH_COMMON) += ath/ | |||
50 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o | 50 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o |
51 | 51 | ||
52 | obj-$(CONFIG_WL12XX) += wl12xx/ | 52 | obj-$(CONFIG_WL12XX) += wl12xx/ |
53 | # small builtin driver bit | ||
54 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/wl12xx_platform_data.o | ||
53 | 55 | ||
54 | obj-$(CONFIG_IWM) += iwmc3200wifi/ | 56 | obj-$(CONFIG_IWM) += iwmc3200wifi/ |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 7d26506957d7..924ed095dd99 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -105,7 +105,7 @@ static struct pci_driver airo_driver = { | |||
105 | of statistics in the /proc filesystem */ | 105 | of statistics in the /proc filesystem */ |
106 | 106 | ||
107 | #define IGNLABEL(comment) NULL | 107 | #define IGNLABEL(comment) NULL |
108 | static char *statsLabels[] = { | 108 | static const char *statsLabels[] = { |
109 | "RxOverrun", | 109 | "RxOverrun", |
110 | IGNLABEL("RxPlcpCrcErr"), | 110 | IGNLABEL("RxPlcpCrcErr"), |
111 | IGNLABEL("RxPlcpFormatErr"), | 111 | IGNLABEL("RxPlcpFormatErr"), |
@@ -932,7 +932,7 @@ typedef struct aironet_ioctl { | |||
932 | unsigned char __user *data; // d-data | 932 | unsigned char __user *data; // d-data |
933 | } aironet_ioctl; | 933 | } aironet_ioctl; |
934 | 934 | ||
935 | static char swversion[] = "2.1"; | 935 | static const char swversion[] = "2.1"; |
936 | #endif /* CISCO_EXT */ | 936 | #endif /* CISCO_EXT */ |
937 | 937 | ||
938 | #define NUM_MODULES 2 | 938 | #define NUM_MODULES 2 |
@@ -1374,7 +1374,7 @@ static int micsetup(struct airo_info *ai) { | |||
1374 | return SUCCESS; | 1374 | return SUCCESS; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02}; | 1377 | static const u8 micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02}; |
1378 | 1378 | ||
1379 | /*=========================================================================== | 1379 | /*=========================================================================== |
1380 | * Description: Mic a packet | 1380 | * Description: Mic a packet |
@@ -5023,7 +5023,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file) | |||
5023 | airo_config_commit(dev, NULL, NULL, NULL); | 5023 | airo_config_commit(dev, NULL, NULL, NULL); |
5024 | } | 5024 | } |
5025 | 5025 | ||
5026 | static char *get_rmode(__le16 mode) | 5026 | static const char *get_rmode(__le16 mode) |
5027 | { | 5027 | { |
5028 | switch(mode & RXMODE_MASK) { | 5028 | switch(mode & RXMODE_MASK) { |
5029 | case RXMODE_RFMON: return "rfmon"; | 5029 | case RXMODE_RFMON: return "rfmon"; |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 0a75be027afa..92c216263ee9 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -25,5 +25,6 @@ config ATH_DEBUG | |||
25 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 25 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
26 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 26 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
27 | source "drivers/net/wireless/ath/ar9170/Kconfig" | 27 | source "drivers/net/wireless/ath/ar9170/Kconfig" |
28 | source "drivers/net/wireless/ath/carl9170/Kconfig" | ||
28 | 29 | ||
29 | endif | 30 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 8113a5042afa..6d711ec97ec2 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -1,11 +1,13 @@ | |||
1 | obj-$(CONFIG_ATH5K) += ath5k/ | 1 | obj-$(CONFIG_ATH5K) += ath5k/ |
2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ | 2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ |
3 | obj-$(CONFIG_AR9170_USB) += ar9170/ | 3 | obj-$(CONFIG_AR9170_USB) += ar9170/ |
4 | obj-$(CONFIG_CARL9170) += carl9170/ | ||
4 | 5 | ||
5 | obj-$(CONFIG_ATH_COMMON) += ath.o | 6 | obj-$(CONFIG_ATH_COMMON) += ath.o |
6 | 7 | ||
7 | ath-objs := main.o \ | 8 | ath-objs := main.o \ |
8 | regd.o \ | 9 | regd.o \ |
9 | hw.o | 10 | hw.o \ |
11 | key.o | ||
10 | 12 | ||
11 | ath-$(CONFIG_ATH_DEBUG) += debug.o | 13 | ath-$(CONFIG_ATH_DEBUG) += debug.o |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index a706202fa67c..dd236c3b52f6 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -71,6 +71,32 @@ struct ath_regulatory { | |||
71 | struct reg_dmn_pair_mapping *regpair; | 71 | struct reg_dmn_pair_mapping *regpair; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | enum ath_crypt_caps { | ||
75 | ATH_CRYPT_CAP_CIPHER_AESCCM = BIT(0), | ||
76 | ATH_CRYPT_CAP_MIC_COMBINED = BIT(1), | ||
77 | }; | ||
78 | |||
79 | struct ath_keyval { | ||
80 | u8 kv_type; | ||
81 | u8 kv_pad; | ||
82 | u16 kv_len; | ||
83 | u8 kv_val[16]; /* TK */ | ||
84 | u8 kv_mic[8]; /* Michael MIC key */ | ||
85 | u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware | ||
86 | * supports both MIC keys in the same key cache entry; | ||
87 | * in that case, kv_mic is the RX key) */ | ||
88 | }; | ||
89 | |||
90 | enum ath_cipher { | ||
91 | ATH_CIPHER_WEP = 0, | ||
92 | ATH_CIPHER_AES_OCB = 1, | ||
93 | ATH_CIPHER_AES_CCM = 2, | ||
94 | ATH_CIPHER_CKIP = 3, | ||
95 | ATH_CIPHER_TKIP = 4, | ||
96 | ATH_CIPHER_CLR = 5, | ||
97 | ATH_CIPHER_MIC = 127 | ||
98 | }; | ||
99 | |||
74 | /** | 100 | /** |
75 | * struct ath_ops - Register read/write operations | 101 | * struct ath_ops - Register read/write operations |
76 | * | 102 | * |
@@ -120,7 +146,7 @@ struct ath_common { | |||
120 | u32 keymax; | 146 | u32 keymax; |
121 | DECLARE_BITMAP(keymap, ATH_KEYMAX); | 147 | DECLARE_BITMAP(keymap, ATH_KEYMAX); |
122 | DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); | 148 | DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); |
123 | u8 splitmic; | 149 | enum ath_crypt_caps crypt_caps; |
124 | 150 | ||
125 | struct ath_regulatory regulatory; | 151 | struct ath_regulatory regulatory; |
126 | const struct ath_ops *ops; | 152 | const struct ath_ops *ops; |
@@ -132,5 +158,11 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | |||
132 | gfp_t gfp_mask); | 158 | gfp_t gfp_mask); |
133 | 159 | ||
134 | void ath_hw_setbssidmask(struct ath_common *common); | 160 | void ath_hw_setbssidmask(struct ath_common *common); |
161 | void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key); | ||
162 | int ath_key_config(struct ath_common *common, | ||
163 | struct ieee80211_vif *vif, | ||
164 | struct ieee80211_sta *sta, | ||
165 | struct ieee80211_key_conf *key); | ||
166 | bool ath_hw_keyreset(struct ath_common *common, u16 entry); | ||
135 | 167 | ||
136 | #endif /* ATH_H */ | 168 | #endif /* ATH_H */ |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index f399c4dd8e69..b96bb985b56d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -206,6 +206,8 @@ | |||
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | 206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ |
207 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ | 207 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ |
208 | 208 | ||
209 | #define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */ | ||
210 | |||
209 | #define AR5K_INIT_CARR_SENSE_EN 1 | 211 | #define AR5K_INIT_CARR_SENSE_EN 1 |
210 | 212 | ||
211 | /*Swap RX/TX Descriptor for big endian archs*/ | 213 | /*Swap RX/TX Descriptor for big endian archs*/ |
@@ -256,8 +258,6 @@ | |||
256 | (AR5K_INIT_PROG_IFS_TURBO) \ | 258 | (AR5K_INIT_PROG_IFS_TURBO) \ |
257 | ) | 259 | ) |
258 | 260 | ||
259 | /* token to use for aifs, cwmin, cwmax in MadWiFi */ | ||
260 | #define AR5K_TXQ_USEDEFAULT ((u32) -1) | ||
261 | 261 | ||
262 | /* GENERIC CHIPSET DEFINITIONS */ | 262 | /* GENERIC CHIPSET DEFINITIONS */ |
263 | 263 | ||
@@ -528,9 +528,9 @@ struct ath5k_txq_info { | |||
528 | enum ath5k_tx_queue tqi_type; | 528 | enum ath5k_tx_queue tqi_type; |
529 | enum ath5k_tx_queue_subtype tqi_subtype; | 529 | enum ath5k_tx_queue_subtype tqi_subtype; |
530 | u16 tqi_flags; /* Tx queue flags (see above) */ | 530 | u16 tqi_flags; /* Tx queue flags (see above) */ |
531 | u32 tqi_aifs; /* Arbitrated Interframe Space */ | 531 | u8 tqi_aifs; /* Arbitrated Interframe Space */ |
532 | s32 tqi_cw_min; /* Minimum Contention Window */ | 532 | u16 tqi_cw_min; /* Minimum Contention Window */ |
533 | s32 tqi_cw_max; /* Maximum Contention Window */ | 533 | u16 tqi_cw_max; /* Maximum Contention Window */ |
534 | u32 tqi_cbr_period; /* Constant bit rate period */ | 534 | u32 tqi_cbr_period; /* Constant bit rate period */ |
535 | u32 tqi_cbr_overflow_limit; | 535 | u32 tqi_cbr_overflow_limit; |
536 | u32 tqi_burst_time; | 536 | u32 tqi_burst_time; |
@@ -1028,8 +1028,6 @@ struct ath5k_hw { | |||
1028 | bool ah_turbo; | 1028 | bool ah_turbo; |
1029 | bool ah_calibration; | 1029 | bool ah_calibration; |
1030 | bool ah_single_chip; | 1030 | bool ah_single_chip; |
1031 | bool ah_aes_support; | ||
1032 | bool ah_combined_mic; | ||
1033 | 1031 | ||
1034 | enum ath5k_version ah_version; | 1032 | enum ath5k_version ah_version; |
1035 | enum ath5k_radio ah_radio; | 1033 | enum ath5k_radio ah_radio; |
@@ -1044,9 +1042,6 @@ struct ath5k_hw { | |||
1044 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version | 1042 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version |
1045 | 1043 | ||
1046 | u32 ah_atim_window; | 1044 | u32 ah_atim_window; |
1047 | u32 ah_aifs; | ||
1048 | u32 ah_cw_min; | ||
1049 | u32 ah_cw_max; | ||
1050 | u32 ah_limit_tx_retries; | 1045 | u32 ah_limit_tx_retries; |
1051 | u8 ah_coverage_class; | 1046 | u8 ah_coverage_class; |
1052 | 1047 | ||
@@ -1207,11 +1202,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | |||
1207 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | 1202 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); |
1208 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | 1203 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); |
1209 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | 1204 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); |
1210 | /* Key table (WEP) functions */ | ||
1211 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | ||
1212 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
1213 | const struct ieee80211_key_conf *key, const u8 *mac); | ||
1214 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | ||
1215 | 1205 | ||
1216 | /* Queue Control Unit, DFS Control Unit Functions */ | 1206 | /* Queue Control Unit, DFS Control Unit Functions */ |
1217 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 1207 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index aabad4f13e2a..6e02de311cdd 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -119,8 +119,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; |
120 | ah->ah_imr = 0; | 120 | ah->ah_imr = 0; |
121 | ah->ah_atim_window = 0; | 121 | ah->ah_atim_window = 0; |
122 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
123 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 122 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; |
125 | ah->ah_software_retry = false; | 123 | ah->ah_software_retry = false; |
126 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | 124 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; |
@@ -314,12 +312,16 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
314 | } | 312 | } |
315 | 313 | ||
316 | /* Crypto settings */ | 314 | /* Crypto settings */ |
317 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && | 315 | common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? |
318 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 316 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); |
319 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); | 317 | |
318 | if (srev >= AR5K_SREV_AR5212_V4 && | ||
319 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | ||
320 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) | ||
321 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; | ||
320 | 322 | ||
321 | if (srev >= AR5K_SREV_AR2414) { | 323 | if (srev >= AR5K_SREV_AR2414) { |
322 | ah->ah_combined_mic = true; | 324 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
323 | AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, | 325 | AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, |
324 | AR5K_MISC_MODE_COMBINED_MIC); | 326 | AR5K_MISC_MODE_COMBINED_MIC); |
325 | } | 327 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 116ac66c6e3e..95072db0ec21 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -70,11 +70,6 @@ static int modparam_all_channels; | |||
70 | module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); | 70 | module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); |
71 | MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); | 71 | MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); |
72 | 72 | ||
73 | |||
74 | /******************\ | ||
75 | * Internal defines * | ||
76 | \******************/ | ||
77 | |||
78 | /* Module info */ | 73 | /* Module info */ |
79 | MODULE_AUTHOR("Jiri Slaby"); | 74 | MODULE_AUTHOR("Jiri Slaby"); |
80 | MODULE_AUTHOR("Nick Kossifidis"); | 75 | MODULE_AUTHOR("Nick Kossifidis"); |
@@ -83,6 +78,10 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); | |||
83 | MODULE_LICENSE("Dual BSD/GPL"); | 78 | MODULE_LICENSE("Dual BSD/GPL"); |
84 | MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); | 79 | MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); |
85 | 80 | ||
81 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); | ||
82 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | ||
83 | struct ieee80211_vif *vif); | ||
84 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | ||
86 | 85 | ||
87 | /* Known PCI ids */ | 86 | /* Known PCI ids */ |
88 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | 87 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { |
@@ -190,129 +189,6 @@ static const struct ieee80211_rate ath5k_rates[] = { | |||
190 | /* XR missing */ | 189 | /* XR missing */ |
191 | }; | 190 | }; |
192 | 191 | ||
193 | /* | ||
194 | * Prototypes - PCI stack related functions | ||
195 | */ | ||
196 | static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | ||
197 | const struct pci_device_id *id); | ||
198 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | ||
199 | #ifdef CONFIG_PM_SLEEP | ||
200 | static int ath5k_pci_suspend(struct device *dev); | ||
201 | static int ath5k_pci_resume(struct device *dev); | ||
202 | |||
203 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
204 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
205 | #else | ||
206 | #define ATH5K_PM_OPS NULL | ||
207 | #endif /* CONFIG_PM_SLEEP */ | ||
208 | |||
209 | static struct pci_driver ath5k_pci_driver = { | ||
210 | .name = KBUILD_MODNAME, | ||
211 | .id_table = ath5k_pci_id_table, | ||
212 | .probe = ath5k_pci_probe, | ||
213 | .remove = __devexit_p(ath5k_pci_remove), | ||
214 | .driver.pm = ATH5K_PM_OPS, | ||
215 | }; | ||
216 | |||
217 | |||
218 | |||
219 | /* | ||
220 | * Prototypes - MAC 802.11 stack related functions | ||
221 | */ | ||
222 | static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
223 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
224 | struct ath5k_txq *txq); | ||
225 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); | ||
226 | static int ath5k_start(struct ieee80211_hw *hw); | ||
227 | static void ath5k_stop(struct ieee80211_hw *hw); | ||
228 | static int ath5k_add_interface(struct ieee80211_hw *hw, | ||
229 | struct ieee80211_vif *vif); | ||
230 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | ||
231 | struct ieee80211_vif *vif); | ||
232 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | ||
233 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
234 | struct netdev_hw_addr_list *mc_list); | ||
235 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | ||
236 | unsigned int changed_flags, | ||
237 | unsigned int *new_flags, | ||
238 | u64 multicast); | ||
239 | static int ath5k_set_key(struct ieee80211_hw *hw, | ||
240 | enum set_key_cmd cmd, | ||
241 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
242 | struct ieee80211_key_conf *key); | ||
243 | static int ath5k_get_stats(struct ieee80211_hw *hw, | ||
244 | struct ieee80211_low_level_stats *stats); | ||
245 | static int ath5k_get_survey(struct ieee80211_hw *hw, | ||
246 | int idx, struct survey_info *survey); | ||
247 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | ||
248 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | ||
249 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | ||
250 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | ||
251 | struct ieee80211_vif *vif); | ||
252 | static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | ||
253 | struct ieee80211_vif *vif, | ||
254 | struct ieee80211_bss_conf *bss_conf, | ||
255 | u32 changes); | ||
256 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); | ||
257 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); | ||
258 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, | ||
259 | u8 coverage_class); | ||
260 | |||
261 | static const struct ieee80211_ops ath5k_hw_ops = { | ||
262 | .tx = ath5k_tx, | ||
263 | .start = ath5k_start, | ||
264 | .stop = ath5k_stop, | ||
265 | .add_interface = ath5k_add_interface, | ||
266 | .remove_interface = ath5k_remove_interface, | ||
267 | .config = ath5k_config, | ||
268 | .prepare_multicast = ath5k_prepare_multicast, | ||
269 | .configure_filter = ath5k_configure_filter, | ||
270 | .set_key = ath5k_set_key, | ||
271 | .get_stats = ath5k_get_stats, | ||
272 | .get_survey = ath5k_get_survey, | ||
273 | .conf_tx = NULL, | ||
274 | .get_tsf = ath5k_get_tsf, | ||
275 | .set_tsf = ath5k_set_tsf, | ||
276 | .reset_tsf = ath5k_reset_tsf, | ||
277 | .bss_info_changed = ath5k_bss_info_changed, | ||
278 | .sw_scan_start = ath5k_sw_scan_start, | ||
279 | .sw_scan_complete = ath5k_sw_scan_complete, | ||
280 | .set_coverage_class = ath5k_set_coverage_class, | ||
281 | }; | ||
282 | |||
283 | /* | ||
284 | * Prototypes - Internal functions | ||
285 | */ | ||
286 | /* Attach detach */ | ||
287 | static int ath5k_attach(struct pci_dev *pdev, | ||
288 | struct ieee80211_hw *hw); | ||
289 | static void ath5k_detach(struct pci_dev *pdev, | ||
290 | struct ieee80211_hw *hw); | ||
291 | /* Channel/mode setup */ | ||
292 | static inline short ath5k_ieee2mhz(short chan); | ||
293 | static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, | ||
294 | struct ieee80211_channel *channels, | ||
295 | unsigned int mode, | ||
296 | unsigned int max); | ||
297 | static int ath5k_setup_bands(struct ieee80211_hw *hw); | ||
298 | static int ath5k_chan_set(struct ath5k_softc *sc, | ||
299 | struct ieee80211_channel *chan); | ||
300 | static void ath5k_setcurmode(struct ath5k_softc *sc, | ||
301 | unsigned int mode); | ||
302 | static void ath5k_mode_setup(struct ath5k_softc *sc); | ||
303 | |||
304 | /* Descriptor setup */ | ||
305 | static int ath5k_desc_alloc(struct ath5k_softc *sc, | ||
306 | struct pci_dev *pdev); | ||
307 | static void ath5k_desc_free(struct ath5k_softc *sc, | ||
308 | struct pci_dev *pdev); | ||
309 | /* Buffers setup */ | ||
310 | static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | ||
311 | struct ath5k_buf *bf); | ||
312 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | ||
313 | struct ath5k_buf *bf, | ||
314 | struct ath5k_txq *txq, int padsize); | ||
315 | |||
316 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, | 192 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, |
317 | struct ath5k_buf *bf) | 193 | struct ath5k_buf *bf) |
318 | { | 194 | { |
@@ -345,35 +221,6 @@ static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, | |||
345 | } | 221 | } |
346 | 222 | ||
347 | 223 | ||
348 | /* Queues setup */ | ||
349 | static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, | ||
350 | int qtype, int subtype); | ||
351 | static int ath5k_beaconq_setup(struct ath5k_hw *ah); | ||
352 | static int ath5k_beaconq_config(struct ath5k_softc *sc); | ||
353 | static void ath5k_txq_drainq(struct ath5k_softc *sc, | ||
354 | struct ath5k_txq *txq); | ||
355 | static void ath5k_txq_cleanup(struct ath5k_softc *sc); | ||
356 | static void ath5k_txq_release(struct ath5k_softc *sc); | ||
357 | /* Rx handling */ | ||
358 | static int ath5k_rx_start(struct ath5k_softc *sc); | ||
359 | static void ath5k_rx_stop(struct ath5k_softc *sc); | ||
360 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | ||
361 | struct sk_buff *skb, | ||
362 | struct ath5k_rx_status *rs); | ||
363 | static void ath5k_tasklet_rx(unsigned long data); | ||
364 | /* Tx handling */ | ||
365 | static void ath5k_tx_processq(struct ath5k_softc *sc, | ||
366 | struct ath5k_txq *txq); | ||
367 | static void ath5k_tasklet_tx(unsigned long data); | ||
368 | /* Beacon handling */ | ||
369 | static int ath5k_beacon_setup(struct ath5k_softc *sc, | ||
370 | struct ath5k_buf *bf); | ||
371 | static void ath5k_beacon_send(struct ath5k_softc *sc); | ||
372 | static void ath5k_beacon_config(struct ath5k_softc *sc); | ||
373 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | ||
374 | static void ath5k_tasklet_beacon(unsigned long data); | ||
375 | static void ath5k_tasklet_ani(unsigned long data); | ||
376 | |||
377 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 224 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
378 | { | 225 | { |
379 | u64 tsf = ath5k_hw_get_tsf64(ah); | 226 | u64 tsf = ath5k_hw_get_tsf64(ah); |
@@ -384,50 +231,6 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | |||
384 | return (tsf & ~0x7fff) | rstamp; | 231 | return (tsf & ~0x7fff) | rstamp; |
385 | } | 232 | } |
386 | 233 | ||
387 | /* Interrupt handling */ | ||
388 | static int ath5k_init(struct ath5k_softc *sc); | ||
389 | static int ath5k_stop_locked(struct ath5k_softc *sc); | ||
390 | static int ath5k_stop_hw(struct ath5k_softc *sc); | ||
391 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | ||
392 | static void ath5k_reset_work(struct work_struct *work); | ||
393 | |||
394 | static void ath5k_tasklet_calibrate(unsigned long data); | ||
395 | |||
396 | /* | ||
397 | * Module init/exit functions | ||
398 | */ | ||
399 | static int __init | ||
400 | init_ath5k_pci(void) | ||
401 | { | ||
402 | int ret; | ||
403 | |||
404 | ath5k_debug_init(); | ||
405 | |||
406 | ret = pci_register_driver(&ath5k_pci_driver); | ||
407 | if (ret) { | ||
408 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void __exit | ||
416 | exit_ath5k_pci(void) | ||
417 | { | ||
418 | pci_unregister_driver(&ath5k_pci_driver); | ||
419 | |||
420 | ath5k_debug_finish(); | ||
421 | } | ||
422 | |||
423 | module_init(init_ath5k_pci); | ||
424 | module_exit(exit_ath5k_pci); | ||
425 | |||
426 | |||
427 | /********************\ | ||
428 | * PCI Initialization * | ||
429 | \********************/ | ||
430 | |||
431 | static const char * | 234 | static const char * |
432 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | 235 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) |
433 | { | 236 | { |
@@ -466,299 +269,6 @@ static const struct ath_ops ath5k_common_ops = { | |||
466 | .write = ath5k_iowrite32, | 269 | .write = ath5k_iowrite32, |
467 | }; | 270 | }; |
468 | 271 | ||
469 | static int __devinit | ||
470 | ath5k_pci_probe(struct pci_dev *pdev, | ||
471 | const struct pci_device_id *id) | ||
472 | { | ||
473 | void __iomem *mem; | ||
474 | struct ath5k_softc *sc; | ||
475 | struct ath_common *common; | ||
476 | struct ieee80211_hw *hw; | ||
477 | int ret; | ||
478 | u8 csz; | ||
479 | |||
480 | /* | ||
481 | * L0s needs to be disabled on all ath5k cards. | ||
482 | * | ||
483 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
484 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
485 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
486 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
487 | * though but cannot currently undue the effect of a blacklist, for | ||
488 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
489 | * the device link capability. | ||
490 | * | ||
491 | * It may be possible in the future to implement some PCI API to allow | ||
492 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
493 | * best to accept that both L0s and L1 will be disabled completely for | ||
494 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
495 | * issue present. Motivation for adding this new API will be to help | ||
496 | * with power consumption for some of these devices. | ||
497 | */ | ||
498 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
499 | |||
500 | ret = pci_enable_device(pdev); | ||
501 | if (ret) { | ||
502 | dev_err(&pdev->dev, "can't enable device\n"); | ||
503 | goto err; | ||
504 | } | ||
505 | |||
506 | /* XXX 32-bit addressing only */ | ||
507 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
508 | if (ret) { | ||
509 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
510 | goto err_dis; | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * Cache line size is used to size and align various | ||
515 | * structures used to communicate with the hardware. | ||
516 | */ | ||
517 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
518 | if (csz == 0) { | ||
519 | /* | ||
520 | * Linux 2.4.18 (at least) writes the cache line size | ||
521 | * register as a 16-bit wide register which is wrong. | ||
522 | * We must have this setup properly for rx buffer | ||
523 | * DMA to work so force a reasonable value here if it | ||
524 | * comes up zero. | ||
525 | */ | ||
526 | csz = L1_CACHE_BYTES >> 2; | ||
527 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
528 | } | ||
529 | /* | ||
530 | * The default setting of latency timer yields poor results, | ||
531 | * set it to the value used by other systems. It may be worth | ||
532 | * tweaking this setting more. | ||
533 | */ | ||
534 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
535 | |||
536 | /* Enable bus mastering */ | ||
537 | pci_set_master(pdev); | ||
538 | |||
539 | /* | ||
540 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
541 | * PCI Tx retries from interfering with C3 CPU state. | ||
542 | */ | ||
543 | pci_write_config_byte(pdev, 0x41, 0); | ||
544 | |||
545 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
546 | if (ret) { | ||
547 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
548 | goto err_dis; | ||
549 | } | ||
550 | |||
551 | mem = pci_iomap(pdev, 0, 0); | ||
552 | if (!mem) { | ||
553 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
554 | ret = -EIO; | ||
555 | goto err_reg; | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * Allocate hw (mac80211 main struct) | ||
560 | * and hw->priv (driver private data) | ||
561 | */ | ||
562 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
563 | if (hw == NULL) { | ||
564 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
565 | ret = -ENOMEM; | ||
566 | goto err_map; | ||
567 | } | ||
568 | |||
569 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
570 | |||
571 | /* Initialize driver private data */ | ||
572 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
573 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
574 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
575 | IEEE80211_HW_SIGNAL_DBM; | ||
576 | |||
577 | hw->wiphy->interface_modes = | ||
578 | BIT(NL80211_IFTYPE_AP) | | ||
579 | BIT(NL80211_IFTYPE_STATION) | | ||
580 | BIT(NL80211_IFTYPE_ADHOC) | | ||
581 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
582 | |||
583 | hw->extra_tx_headroom = 2; | ||
584 | hw->channel_change_time = 5000; | ||
585 | sc = hw->priv; | ||
586 | sc->hw = hw; | ||
587 | sc->pdev = pdev; | ||
588 | |||
589 | ath5k_debug_init_device(sc); | ||
590 | |||
591 | /* | ||
592 | * Mark the device as detached to avoid processing | ||
593 | * interrupts until setup is complete. | ||
594 | */ | ||
595 | __set_bit(ATH_STAT_INVALID, sc->status); | ||
596 | |||
597 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
598 | sc->opmode = NL80211_IFTYPE_STATION; | ||
599 | sc->bintval = 1000; | ||
600 | mutex_init(&sc->lock); | ||
601 | spin_lock_init(&sc->rxbuflock); | ||
602 | spin_lock_init(&sc->txbuflock); | ||
603 | spin_lock_init(&sc->block); | ||
604 | |||
605 | /* Set private data */ | ||
606 | pci_set_drvdata(pdev, sc); | ||
607 | |||
608 | /* Setup interrupt handler */ | ||
609 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | ||
610 | if (ret) { | ||
611 | ATH5K_ERR(sc, "request_irq failed\n"); | ||
612 | goto err_free; | ||
613 | } | ||
614 | |||
615 | /* If we passed the test, malloc an ath5k_hw struct */ | ||
616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
617 | if (!sc->ah) { | ||
618 | ret = -ENOMEM; | ||
619 | ATH5K_ERR(sc, "out of memory\n"); | ||
620 | goto err_irq; | ||
621 | } | ||
622 | |||
623 | sc->ah->ah_sc = sc; | ||
624 | sc->ah->ah_iobase = sc->iobase; | ||
625 | common = ath5k_hw_common(sc->ah); | ||
626 | common->ops = &ath5k_common_ops; | ||
627 | common->ah = sc->ah; | ||
628 | common->hw = hw; | ||
629 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
630 | |||
631 | /* Initialize device */ | ||
632 | ret = ath5k_hw_attach(sc); | ||
633 | if (ret) { | ||
634 | goto err_free_ah; | ||
635 | } | ||
636 | |||
637 | /* set up multi-rate retry capabilities */ | ||
638 | if (sc->ah->ah_version == AR5K_AR5212) { | ||
639 | hw->max_rates = 4; | ||
640 | hw->max_rate_tries = 11; | ||
641 | } | ||
642 | |||
643 | /* Finish private driver data initialization */ | ||
644 | ret = ath5k_attach(pdev, hw); | ||
645 | if (ret) | ||
646 | goto err_ah; | ||
647 | |||
648 | ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", | ||
649 | ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), | ||
650 | sc->ah->ah_mac_srev, | ||
651 | sc->ah->ah_phy_revision); | ||
652 | |||
653 | if (!sc->ah->ah_single_chip) { | ||
654 | /* Single chip radio (!RF5111) */ | ||
655 | if (sc->ah->ah_radio_5ghz_revision && | ||
656 | !sc->ah->ah_radio_2ghz_revision) { | ||
657 | /* No 5GHz support -> report 2GHz radio */ | ||
658 | if (!test_bit(AR5K_MODE_11A, | ||
659 | sc->ah->ah_capabilities.cap_mode)) { | ||
660 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
661 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
662 | sc->ah->ah_radio_5ghz_revision), | ||
663 | sc->ah->ah_radio_5ghz_revision); | ||
664 | /* No 2GHz support (5110 and some | ||
665 | * 5Ghz only cards) -> report 5Ghz radio */ | ||
666 | } else if (!test_bit(AR5K_MODE_11B, | ||
667 | sc->ah->ah_capabilities.cap_mode)) { | ||
668 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
669 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
670 | sc->ah->ah_radio_5ghz_revision), | ||
671 | sc->ah->ah_radio_5ghz_revision); | ||
672 | /* Multiband radio */ | ||
673 | } else { | ||
674 | ATH5K_INFO(sc, "RF%s multiband radio found" | ||
675 | " (0x%x)\n", | ||
676 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
677 | sc->ah->ah_radio_5ghz_revision), | ||
678 | sc->ah->ah_radio_5ghz_revision); | ||
679 | } | ||
680 | } | ||
681 | /* Multi chip radio (RF5111 - RF2111) -> | ||
682 | * report both 2GHz/5GHz radios */ | ||
683 | else if (sc->ah->ah_radio_5ghz_revision && | ||
684 | sc->ah->ah_radio_2ghz_revision){ | ||
685 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
686 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
687 | sc->ah->ah_radio_5ghz_revision), | ||
688 | sc->ah->ah_radio_5ghz_revision); | ||
689 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
690 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
691 | sc->ah->ah_radio_2ghz_revision), | ||
692 | sc->ah->ah_radio_2ghz_revision); | ||
693 | } | ||
694 | } | ||
695 | |||
696 | |||
697 | /* ready to process interrupts */ | ||
698 | __clear_bit(ATH_STAT_INVALID, sc->status); | ||
699 | |||
700 | return 0; | ||
701 | err_ah: | ||
702 | ath5k_hw_detach(sc->ah); | ||
703 | err_free_ah: | ||
704 | kfree(sc->ah); | ||
705 | err_irq: | ||
706 | free_irq(pdev->irq, sc); | ||
707 | err_free: | ||
708 | ieee80211_free_hw(hw); | ||
709 | err_map: | ||
710 | pci_iounmap(pdev, mem); | ||
711 | err_reg: | ||
712 | pci_release_region(pdev, 0); | ||
713 | err_dis: | ||
714 | pci_disable_device(pdev); | ||
715 | err: | ||
716 | return ret; | ||
717 | } | ||
718 | |||
719 | static void __devexit | ||
720 | ath5k_pci_remove(struct pci_dev *pdev) | ||
721 | { | ||
722 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
723 | |||
724 | ath5k_debug_finish_device(sc); | ||
725 | ath5k_detach(pdev, sc->hw); | ||
726 | ath5k_hw_detach(sc->ah); | ||
727 | kfree(sc->ah); | ||
728 | free_irq(pdev->irq, sc); | ||
729 | pci_iounmap(pdev, sc->iobase); | ||
730 | pci_release_region(pdev, 0); | ||
731 | pci_disable_device(pdev); | ||
732 | ieee80211_free_hw(sc->hw); | ||
733 | } | ||
734 | |||
735 | #ifdef CONFIG_PM_SLEEP | ||
736 | static int ath5k_pci_suspend(struct device *dev) | ||
737 | { | ||
738 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); | ||
739 | |||
740 | ath5k_led_off(sc); | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int ath5k_pci_resume(struct device *dev) | ||
745 | { | ||
746 | struct pci_dev *pdev = to_pci_dev(dev); | ||
747 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
748 | |||
749 | /* | ||
750 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
751 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
752 | * PCI Tx retries from interfering with C3 CPU state | ||
753 | */ | ||
754 | pci_write_config_byte(pdev, 0x41, 0); | ||
755 | |||
756 | ath5k_led_enable(sc); | ||
757 | return 0; | ||
758 | } | ||
759 | #endif /* CONFIG_PM_SLEEP */ | ||
760 | |||
761 | |||
762 | /***********************\ | 272 | /***********************\ |
763 | * Driver Initialization * | 273 | * Driver Initialization * |
764 | \***********************/ | 274 | \***********************/ |
@@ -772,170 +282,6 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
772 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 282 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
773 | } | 283 | } |
774 | 284 | ||
775 | static int | ||
776 | ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
777 | { | ||
778 | struct ath5k_softc *sc = hw->priv; | ||
779 | struct ath5k_hw *ah = sc->ah; | ||
780 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); | ||
781 | u8 mac[ETH_ALEN] = {}; | ||
782 | int ret; | ||
783 | |||
784 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); | ||
785 | |||
786 | /* | ||
787 | * Check if the MAC has multi-rate retry support. | ||
788 | * We do this by trying to setup a fake extended | ||
789 | * descriptor. MACs that don't have support will | ||
790 | * return false w/o doing anything. MACs that do | ||
791 | * support it will return true w/o doing anything. | ||
792 | */ | ||
793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | ||
794 | |||
795 | if (ret < 0) | ||
796 | goto err; | ||
797 | if (ret > 0) | ||
798 | __set_bit(ATH_STAT_MRRETRY, sc->status); | ||
799 | |||
800 | /* | ||
801 | * Collect the channel list. The 802.11 layer | ||
802 | * is resposible for filtering this list based | ||
803 | * on settings like the phy mode and regulatory | ||
804 | * domain restrictions. | ||
805 | */ | ||
806 | ret = ath5k_setup_bands(hw); | ||
807 | if (ret) { | ||
808 | ATH5K_ERR(sc, "can't get channels\n"); | ||
809 | goto err; | ||
810 | } | ||
811 | |||
812 | /* NB: setup here so ath5k_rate_update is happy */ | ||
813 | if (test_bit(AR5K_MODE_11A, ah->ah_modes)) | ||
814 | ath5k_setcurmode(sc, AR5K_MODE_11A); | ||
815 | else | ||
816 | ath5k_setcurmode(sc, AR5K_MODE_11B); | ||
817 | |||
818 | /* | ||
819 | * Allocate tx+rx descriptors and populate the lists. | ||
820 | */ | ||
821 | ret = ath5k_desc_alloc(sc, pdev); | ||
822 | if (ret) { | ||
823 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
824 | goto err; | ||
825 | } | ||
826 | |||
827 | /* | ||
828 | * Allocate hardware transmit queues: one queue for | ||
829 | * beacon frames and one data queue for each QoS | ||
830 | * priority. Note that hw functions handle resetting | ||
831 | * these queues at the needed time. | ||
832 | */ | ||
833 | ret = ath5k_beaconq_setup(ah); | ||
834 | if (ret < 0) { | ||
835 | ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); | ||
836 | goto err_desc; | ||
837 | } | ||
838 | sc->bhalq = ret; | ||
839 | sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); | ||
840 | if (IS_ERR(sc->cabq)) { | ||
841 | ATH5K_ERR(sc, "can't setup cab queue\n"); | ||
842 | ret = PTR_ERR(sc->cabq); | ||
843 | goto err_bhal; | ||
844 | } | ||
845 | |||
846 | sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); | ||
847 | if (IS_ERR(sc->txq)) { | ||
848 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
849 | ret = PTR_ERR(sc->txq); | ||
850 | goto err_queues; | ||
851 | } | ||
852 | |||
853 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | ||
854 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | ||
855 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | ||
856 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | ||
857 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
858 | |||
859 | INIT_WORK(&sc->reset_work, ath5k_reset_work); | ||
860 | |||
861 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
862 | if (ret) { | ||
863 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
864 | sc->pdev->device); | ||
865 | goto err_queues; | ||
866 | } | ||
867 | |||
868 | SET_IEEE80211_PERM_ADDR(hw, mac); | ||
869 | /* All MAC address bits matter for ACKs */ | ||
870 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
871 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
872 | |||
873 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | ||
874 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); | ||
875 | if (ret) { | ||
876 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); | ||
877 | goto err_queues; | ||
878 | } | ||
879 | |||
880 | ret = ieee80211_register_hw(hw); | ||
881 | if (ret) { | ||
882 | ATH5K_ERR(sc, "can't register ieee80211 hw\n"); | ||
883 | goto err_queues; | ||
884 | } | ||
885 | |||
886 | if (!ath_is_world_regd(regulatory)) | ||
887 | regulatory_hint(hw->wiphy, regulatory->alpha2); | ||
888 | |||
889 | ath5k_init_leds(sc); | ||
890 | |||
891 | ath5k_sysfs_register(sc); | ||
892 | |||
893 | return 0; | ||
894 | err_queues: | ||
895 | ath5k_txq_release(sc); | ||
896 | err_bhal: | ||
897 | ath5k_hw_release_tx_queue(ah, sc->bhalq); | ||
898 | err_desc: | ||
899 | ath5k_desc_free(sc, pdev); | ||
900 | err: | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | static void | ||
905 | ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
906 | { | ||
907 | struct ath5k_softc *sc = hw->priv; | ||
908 | |||
909 | /* | ||
910 | * NB: the order of these is important: | ||
911 | * o call the 802.11 layer before detaching ath5k_hw to | ||
912 | * ensure callbacks into the driver to delete global | ||
913 | * key cache entries can be handled | ||
914 | * o reclaim the tx queue data structures after calling | ||
915 | * the 802.11 layer as we'll get called back to reclaim | ||
916 | * node state and potentially want to use them | ||
917 | * o to cleanup the tx queues the hal is called, so detach | ||
918 | * it last | ||
919 | * XXX: ??? detach ath5k_hw ??? | ||
920 | * Other than that, it's straightforward... | ||
921 | */ | ||
922 | ieee80211_unregister_hw(hw); | ||
923 | ath5k_desc_free(sc, pdev); | ||
924 | ath5k_txq_release(sc); | ||
925 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | ||
926 | ath5k_unregister_leds(sc); | ||
927 | |||
928 | ath5k_sysfs_unregister(sc); | ||
929 | /* | ||
930 | * NB: can't reclaim these until after ieee80211_ifdetach | ||
931 | * returns because we'll get called back to reclaim node | ||
932 | * state and potentially want to use them. | ||
933 | */ | ||
934 | } | ||
935 | |||
936 | |||
937 | |||
938 | |||
939 | /********************\ | 285 | /********************\ |
940 | * Channel/mode setup * | 286 | * Channel/mode setup * |
941 | \********************/ | 287 | \********************/ |
@@ -1391,6 +737,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1391 | 737 | ||
1392 | spin_lock_bh(&txq->lock); | 738 | spin_lock_bh(&txq->lock); |
1393 | list_add_tail(&bf->list, &txq->q); | 739 | list_add_tail(&bf->list, &txq->q); |
740 | txq->txq_len++; | ||
1394 | if (txq->link == NULL) /* is this first packet? */ | 741 | if (txq->link == NULL) /* is this first packet? */ |
1395 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); | 742 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); |
1396 | else /* no, so only link it */ | 743 | else /* no, so only link it */ |
@@ -1494,9 +841,6 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
1494 | } | 841 | } |
1495 | 842 | ||
1496 | 843 | ||
1497 | |||
1498 | |||
1499 | |||
1500 | /**************\ | 844 | /**************\ |
1501 | * Queues setup * | 845 | * Queues setup * |
1502 | \**************/ | 846 | \**************/ |
@@ -1509,9 +853,11 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1509 | struct ath5k_txq *txq; | 853 | struct ath5k_txq *txq; |
1510 | struct ath5k_txq_info qi = { | 854 | struct ath5k_txq_info qi = { |
1511 | .tqi_subtype = subtype, | 855 | .tqi_subtype = subtype, |
1512 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | 856 | /* XXX: default values not correct for B and XR channels, |
1513 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | 857 | * but who cares? */ |
1514 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT | 858 | .tqi_aifs = AR5K_TUNE_AIFS, |
859 | .tqi_cw_min = AR5K_TUNE_CWMIN, | ||
860 | .tqi_cw_max = AR5K_TUNE_CWMAX | ||
1515 | }; | 861 | }; |
1516 | int qnum; | 862 | int qnum; |
1517 | 863 | ||
@@ -1550,6 +896,9 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1550 | INIT_LIST_HEAD(&txq->q); | 896 | INIT_LIST_HEAD(&txq->q); |
1551 | spin_lock_init(&txq->lock); | 897 | spin_lock_init(&txq->lock); |
1552 | txq->setup = true; | 898 | txq->setup = true; |
899 | txq->txq_len = 0; | ||
900 | txq->txq_poll_mark = false; | ||
901 | txq->txq_stuck = 0; | ||
1553 | } | 902 | } |
1554 | return &sc->txqs[qnum]; | 903 | return &sc->txqs[qnum]; |
1555 | } | 904 | } |
@@ -1558,9 +907,11 @@ static int | |||
1558 | ath5k_beaconq_setup(struct ath5k_hw *ah) | 907 | ath5k_beaconq_setup(struct ath5k_hw *ah) |
1559 | { | 908 | { |
1560 | struct ath5k_txq_info qi = { | 909 | struct ath5k_txq_info qi = { |
1561 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | 910 | /* XXX: default values not correct for B and XR channels, |
1562 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | 911 | * but who cares? */ |
1563 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT, | 912 | .tqi_aifs = AR5K_TUNE_AIFS, |
913 | .tqi_cw_min = AR5K_TUNE_CWMIN, | ||
914 | .tqi_cw_max = AR5K_TUNE_CWMAX, | ||
1564 | /* NB: for dynamic turbo, don't enable any other interrupts */ | 915 | /* NB: for dynamic turbo, don't enable any other interrupts */ |
1565 | .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE | 916 | .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE |
1566 | }; | 917 | }; |
@@ -1594,7 +945,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1594 | */ | 945 | */ |
1595 | qi.tqi_aifs = 0; | 946 | qi.tqi_aifs = 0; |
1596 | qi.tqi_cw_min = 0; | 947 | qi.tqi_cw_min = 0; |
1597 | qi.tqi_cw_max = 2 * ah->ah_cw_min; | 948 | qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN; |
1598 | } | 949 | } |
1599 | 950 | ||
1600 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 951 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
@@ -1644,9 +995,11 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1644 | spin_lock_bh(&sc->txbuflock); | 995 | spin_lock_bh(&sc->txbuflock); |
1645 | list_move_tail(&bf->list, &sc->txbuf); | 996 | list_move_tail(&bf->list, &sc->txbuf); |
1646 | sc->txbuf_len++; | 997 | sc->txbuf_len++; |
998 | txq->txq_len--; | ||
1647 | spin_unlock_bh(&sc->txbuflock); | 999 | spin_unlock_bh(&sc->txbuflock); |
1648 | } | 1000 | } |
1649 | txq->link = NULL; | 1001 | txq->link = NULL; |
1002 | txq->txq_poll_mark = false; | ||
1650 | spin_unlock_bh(&txq->lock); | 1003 | spin_unlock_bh(&txq->lock); |
1651 | } | 1004 | } |
1652 | 1005 | ||
@@ -1696,8 +1049,6 @@ ath5k_txq_release(struct ath5k_softc *sc) | |||
1696 | } | 1049 | } |
1697 | 1050 | ||
1698 | 1051 | ||
1699 | |||
1700 | |||
1701 | /*************\ | 1052 | /*************\ |
1702 | * RX Handling * | 1053 | * RX Handling * |
1703 | \*************/ | 1054 | \*************/ |
@@ -2121,6 +1472,117 @@ unlock: | |||
2121 | * TX Handling * | 1472 | * TX Handling * |
2122 | \*************/ | 1473 | \*************/ |
2123 | 1474 | ||
1475 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
1476 | struct ath5k_txq *txq) | ||
1477 | { | ||
1478 | struct ath5k_softc *sc = hw->priv; | ||
1479 | struct ath5k_buf *bf; | ||
1480 | unsigned long flags; | ||
1481 | int padsize; | ||
1482 | |||
1483 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | ||
1484 | |||
1485 | /* | ||
1486 | * The hardware expects the header padded to 4 byte boundaries. | ||
1487 | * If this is not the case, we add the padding after the header. | ||
1488 | */ | ||
1489 | padsize = ath5k_add_padding(skb); | ||
1490 | if (padsize < 0) { | ||
1491 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" | ||
1492 | " headroom to pad"); | ||
1493 | goto drop_packet; | ||
1494 | } | ||
1495 | |||
1496 | if (txq->txq_len >= ATH5K_TXQ_LEN_MAX) | ||
1497 | ieee80211_stop_queue(hw, txq->qnum); | ||
1498 | |||
1499 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
1500 | if (list_empty(&sc->txbuf)) { | ||
1501 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | ||
1502 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1503 | ieee80211_stop_queues(hw); | ||
1504 | goto drop_packet; | ||
1505 | } | ||
1506 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | ||
1507 | list_del(&bf->list); | ||
1508 | sc->txbuf_len--; | ||
1509 | if (list_empty(&sc->txbuf)) | ||
1510 | ieee80211_stop_queues(hw); | ||
1511 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1512 | |||
1513 | bf->skb = skb; | ||
1514 | |||
1515 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { | ||
1516 | bf->skb = NULL; | ||
1517 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
1518 | list_add_tail(&bf->list, &sc->txbuf); | ||
1519 | sc->txbuf_len++; | ||
1520 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1521 | goto drop_packet; | ||
1522 | } | ||
1523 | return NETDEV_TX_OK; | ||
1524 | |||
1525 | drop_packet: | ||
1526 | dev_kfree_skb_any(skb); | ||
1527 | return NETDEV_TX_OK; | ||
1528 | } | ||
1529 | |||
1530 | static void | ||
1531 | ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | ||
1532 | struct ath5k_tx_status *ts) | ||
1533 | { | ||
1534 | struct ieee80211_tx_info *info; | ||
1535 | int i; | ||
1536 | |||
1537 | sc->stats.tx_all_count++; | ||
1538 | info = IEEE80211_SKB_CB(skb); | ||
1539 | |||
1540 | ieee80211_tx_info_clear_status(info); | ||
1541 | for (i = 0; i < 4; i++) { | ||
1542 | struct ieee80211_tx_rate *r = | ||
1543 | &info->status.rates[i]; | ||
1544 | |||
1545 | if (ts->ts_rate[i]) { | ||
1546 | r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]); | ||
1547 | r->count = ts->ts_retry[i]; | ||
1548 | } else { | ||
1549 | r->idx = -1; | ||
1550 | r->count = 0; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | /* count the successful attempt as well */ | ||
1555 | info->status.rates[ts->ts_final_idx].count++; | ||
1556 | |||
1557 | if (unlikely(ts->ts_status)) { | ||
1558 | sc->stats.ack_fail++; | ||
1559 | if (ts->ts_status & AR5K_TXERR_FILT) { | ||
1560 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1561 | sc->stats.txerr_filt++; | ||
1562 | } | ||
1563 | if (ts->ts_status & AR5K_TXERR_XRETRY) | ||
1564 | sc->stats.txerr_retry++; | ||
1565 | if (ts->ts_status & AR5K_TXERR_FIFO) | ||
1566 | sc->stats.txerr_fifo++; | ||
1567 | } else { | ||
1568 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1569 | info->status.ack_signal = ts->ts_rssi; | ||
1570 | } | ||
1571 | |||
1572 | /* | ||
1573 | * Remove MAC header padding before giving the frame | ||
1574 | * back to mac80211. | ||
1575 | */ | ||
1576 | ath5k_remove_padding(skb); | ||
1577 | |||
1578 | if (ts->ts_antenna > 0 && ts->ts_antenna < 5) | ||
1579 | sc->stats.antenna_tx[ts->ts_antenna]++; | ||
1580 | else | ||
1581 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
1582 | |||
1583 | ieee80211_tx_status(sc->hw, skb); | ||
1584 | } | ||
1585 | |||
2124 | static void | 1586 | static void |
2125 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | 1587 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) |
2126 | { | 1588 | { |
@@ -2128,96 +1590,51 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2128 | struct ath5k_buf *bf, *bf0; | 1590 | struct ath5k_buf *bf, *bf0; |
2129 | struct ath5k_desc *ds; | 1591 | struct ath5k_desc *ds; |
2130 | struct sk_buff *skb; | 1592 | struct sk_buff *skb; |
2131 | struct ieee80211_tx_info *info; | 1593 | int ret; |
2132 | int i, ret; | ||
2133 | 1594 | ||
2134 | spin_lock(&txq->lock); | 1595 | spin_lock(&txq->lock); |
2135 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1596 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
2136 | ds = bf->desc; | ||
2137 | |||
2138 | /* | ||
2139 | * It's possible that the hardware can say the buffer is | ||
2140 | * completed when it hasn't yet loaded the ds_link from | ||
2141 | * host memory and moved on. If there are more TX | ||
2142 | * descriptors in the queue, wait for TXDP to change | ||
2143 | * before processing this one. | ||
2144 | */ | ||
2145 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr && | ||
2146 | !list_is_last(&bf->list, &txq->q)) | ||
2147 | break; | ||
2148 | 1597 | ||
2149 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); | 1598 | txq->txq_poll_mark = false; |
2150 | if (unlikely(ret == -EINPROGRESS)) | ||
2151 | break; | ||
2152 | else if (unlikely(ret)) { | ||
2153 | ATH5K_ERR(sc, "error %d while processing queue %u\n", | ||
2154 | ret, txq->qnum); | ||
2155 | break; | ||
2156 | } | ||
2157 | 1599 | ||
2158 | sc->stats.tx_all_count++; | 1600 | /* skb might already have been processed last time. */ |
2159 | skb = bf->skb; | 1601 | if (bf->skb != NULL) { |
2160 | info = IEEE80211_SKB_CB(skb); | 1602 | ds = bf->desc; |
2161 | bf->skb = NULL; | ||
2162 | 1603 | ||
2163 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, | 1604 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); |
2164 | PCI_DMA_TODEVICE); | 1605 | if (unlikely(ret == -EINPROGRESS)) |
2165 | 1606 | break; | |
2166 | ieee80211_tx_info_clear_status(info); | 1607 | else if (unlikely(ret)) { |
2167 | for (i = 0; i < 4; i++) { | 1608 | ATH5K_ERR(sc, |
2168 | struct ieee80211_tx_rate *r = | 1609 | "error %d while processing " |
2169 | &info->status.rates[i]; | 1610 | "queue %u\n", ret, txq->qnum); |
2170 | 1611 | break; | |
2171 | if (ts.ts_rate[i]) { | ||
2172 | r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); | ||
2173 | r->count = ts.ts_retry[i]; | ||
2174 | } else { | ||
2175 | r->idx = -1; | ||
2176 | r->count = 0; | ||
2177 | } | 1612 | } |
2178 | } | ||
2179 | |||
2180 | /* count the successful attempt as well */ | ||
2181 | info->status.rates[ts.ts_final_idx].count++; | ||
2182 | 1613 | ||
2183 | if (unlikely(ts.ts_status)) { | 1614 | skb = bf->skb; |
2184 | sc->stats.ack_fail++; | 1615 | bf->skb = NULL; |
2185 | if (ts.ts_status & AR5K_TXERR_FILT) { | 1616 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, |
2186 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1617 | PCI_DMA_TODEVICE); |
2187 | sc->stats.txerr_filt++; | 1618 | ath5k_tx_frame_completed(sc, skb, &ts); |
2188 | } | ||
2189 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2190 | sc->stats.txerr_retry++; | ||
2191 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2192 | sc->stats.txerr_fifo++; | ||
2193 | } else { | ||
2194 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
2195 | info->status.ack_signal = ts.ts_rssi; | ||
2196 | } | 1619 | } |
2197 | 1620 | ||
2198 | /* | 1621 | /* |
2199 | * Remove MAC header padding before giving the frame | 1622 | * It's possible that the hardware can say the buffer is |
2200 | * back to mac80211. | 1623 | * completed when it hasn't yet loaded the ds_link from |
1624 | * host memory and moved on. | ||
1625 | * Always keep the last descriptor to avoid HW races... | ||
2201 | */ | 1626 | */ |
2202 | ath5k_remove_padding(skb); | 1627 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) { |
2203 | 1628 | spin_lock(&sc->txbuflock); | |
2204 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | 1629 | list_move_tail(&bf->list, &sc->txbuf); |
2205 | sc->stats.antenna_tx[ts.ts_antenna]++; | 1630 | sc->txbuf_len++; |
2206 | else | 1631 | txq->txq_len--; |
2207 | sc->stats.antenna_tx[0]++; /* invalid */ | 1632 | spin_unlock(&sc->txbuflock); |
2208 | 1633 | } | |
2209 | ieee80211_tx_status(sc->hw, skb); | ||
2210 | |||
2211 | spin_lock(&sc->txbuflock); | ||
2212 | list_move_tail(&bf->list, &sc->txbuf); | ||
2213 | sc->txbuf_len++; | ||
2214 | spin_unlock(&sc->txbuflock); | ||
2215 | } | 1634 | } |
2216 | if (likely(list_empty(&txq->q))) | ||
2217 | txq->link = NULL; | ||
2218 | spin_unlock(&txq->lock); | 1635 | spin_unlock(&txq->lock); |
2219 | if (sc->txbuf_len > ATH_TXBUF / 5) | 1636 | if (txq->txq_len < ATH5K_TXQ_LEN_LOW) |
2220 | ieee80211_wake_queues(sc->hw); | 1637 | ieee80211_wake_queue(sc->hw, txq->qnum); |
2221 | } | 1638 | } |
2222 | 1639 | ||
2223 | static void | 1640 | static void |
@@ -2313,6 +1730,43 @@ err_unmap: | |||
2313 | } | 1730 | } |
2314 | 1731 | ||
2315 | /* | 1732 | /* |
1733 | * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, | ||
1734 | * this is called only once at config_bss time, for AP we do it every | ||
1735 | * SWBA interrupt so that the TIM will reflect buffered frames. | ||
1736 | * | ||
1737 | * Called with the beacon lock. | ||
1738 | */ | ||
1739 | static int | ||
1740 | ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
1741 | { | ||
1742 | int ret; | ||
1743 | struct ath5k_softc *sc = hw->priv; | ||
1744 | struct sk_buff *skb; | ||
1745 | |||
1746 | if (WARN_ON(!vif)) { | ||
1747 | ret = -EINVAL; | ||
1748 | goto out; | ||
1749 | } | ||
1750 | |||
1751 | skb = ieee80211_beacon_get(hw, vif); | ||
1752 | |||
1753 | if (!skb) { | ||
1754 | ret = -ENOMEM; | ||
1755 | goto out; | ||
1756 | } | ||
1757 | |||
1758 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | ||
1759 | |||
1760 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
1761 | sc->bbuf->skb = skb; | ||
1762 | ret = ath5k_beacon_setup(sc, sc->bbuf); | ||
1763 | if (ret) | ||
1764 | sc->bbuf->skb = NULL; | ||
1765 | out: | ||
1766 | return ret; | ||
1767 | } | ||
1768 | |||
1769 | /* | ||
2316 | * Transmit a beacon frame at SWBA. Dynamic updates to the | 1770 | * Transmit a beacon frame at SWBA. Dynamic updates to the |
2317 | * frame contents are done as needed and the slot time is | 1771 | * frame contents are done as needed and the slot time is |
2318 | * also adjusted based on current state. | 1772 | * also adjusted based on current state. |
@@ -2389,7 +1843,6 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2389 | sc->bsent++; | 1843 | sc->bsent++; |
2390 | } | 1844 | } |
2391 | 1845 | ||
2392 | |||
2393 | /** | 1846 | /** |
2394 | * ath5k_beacon_update_timers - update beacon timers | 1847 | * ath5k_beacon_update_timers - update beacon timers |
2395 | * | 1848 | * |
@@ -2491,7 +1944,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2491 | intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); | 1944 | intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); |
2492 | } | 1945 | } |
2493 | 1946 | ||
2494 | |||
2495 | /** | 1947 | /** |
2496 | * ath5k_beacon_config - Configure the beacon queues and interrupts | 1948 | * ath5k_beacon_config - Configure the beacon queues and interrupts |
2497 | * | 1949 | * |
@@ -2570,155 +2022,6 @@ static void ath5k_tasklet_beacon(unsigned long data) | |||
2570 | * Interrupt handling * | 2022 | * Interrupt handling * |
2571 | \********************/ | 2023 | \********************/ |
2572 | 2024 | ||
2573 | static int | ||
2574 | ath5k_init(struct ath5k_softc *sc) | ||
2575 | { | ||
2576 | struct ath5k_hw *ah = sc->ah; | ||
2577 | int ret, i; | ||
2578 | |||
2579 | mutex_lock(&sc->lock); | ||
2580 | |||
2581 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | ||
2582 | |||
2583 | /* | ||
2584 | * Stop anything previously setup. This is safe | ||
2585 | * no matter this is the first time through or not. | ||
2586 | */ | ||
2587 | ath5k_stop_locked(sc); | ||
2588 | |||
2589 | /* | ||
2590 | * The basic interface to setting the hardware in a good | ||
2591 | * state is ``reset''. On return the hardware is known to | ||
2592 | * be powered up and with interrupts disabled. This must | ||
2593 | * be followed by initialization of the appropriate bits | ||
2594 | * and then setup of the interrupt mask. | ||
2595 | */ | ||
2596 | sc->curchan = sc->hw->conf.channel; | ||
2597 | sc->curband = &sc->sbands[sc->curchan->band]; | ||
2598 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | ||
2599 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | ||
2600 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; | ||
2601 | |||
2602 | ret = ath5k_reset(sc, NULL); | ||
2603 | if (ret) | ||
2604 | goto done; | ||
2605 | |||
2606 | ath5k_rfkill_hw_start(ah); | ||
2607 | |||
2608 | /* | ||
2609 | * Reset the key cache since some parts do not reset the | ||
2610 | * contents on initial power up or resume from suspend. | ||
2611 | */ | ||
2612 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | ||
2613 | ath5k_hw_reset_key(ah, i); | ||
2614 | |||
2615 | ath5k_hw_set_ack_bitrate_high(ah, true); | ||
2616 | ret = 0; | ||
2617 | done: | ||
2618 | mmiowb(); | ||
2619 | mutex_unlock(&sc->lock); | ||
2620 | return ret; | ||
2621 | } | ||
2622 | |||
2623 | static int | ||
2624 | ath5k_stop_locked(struct ath5k_softc *sc) | ||
2625 | { | ||
2626 | struct ath5k_hw *ah = sc->ah; | ||
2627 | |||
2628 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", | ||
2629 | test_bit(ATH_STAT_INVALID, sc->status)); | ||
2630 | |||
2631 | /* | ||
2632 | * Shutdown the hardware and driver: | ||
2633 | * stop output from above | ||
2634 | * disable interrupts | ||
2635 | * turn off timers | ||
2636 | * turn off the radio | ||
2637 | * clear transmit machinery | ||
2638 | * clear receive machinery | ||
2639 | * drain and release tx queues | ||
2640 | * reclaim beacon resources | ||
2641 | * power down hardware | ||
2642 | * | ||
2643 | * Note that some of this work is not possible if the | ||
2644 | * hardware is gone (invalid). | ||
2645 | */ | ||
2646 | ieee80211_stop_queues(sc->hw); | ||
2647 | |||
2648 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2649 | ath5k_led_off(sc); | ||
2650 | ath5k_hw_set_imr(ah, 0); | ||
2651 | synchronize_irq(sc->pdev->irq); | ||
2652 | } | ||
2653 | ath5k_txq_cleanup(sc); | ||
2654 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2655 | ath5k_rx_stop(sc); | ||
2656 | ath5k_hw_phy_disable(ah); | ||
2657 | } | ||
2658 | |||
2659 | return 0; | ||
2660 | } | ||
2661 | |||
2662 | static void stop_tasklets(struct ath5k_softc *sc) | ||
2663 | { | ||
2664 | tasklet_kill(&sc->rxtq); | ||
2665 | tasklet_kill(&sc->txtq); | ||
2666 | tasklet_kill(&sc->calib); | ||
2667 | tasklet_kill(&sc->beacontq); | ||
2668 | tasklet_kill(&sc->ani_tasklet); | ||
2669 | } | ||
2670 | |||
2671 | /* | ||
2672 | * Stop the device, grabbing the top-level lock to protect | ||
2673 | * against concurrent entry through ath5k_init (which can happen | ||
2674 | * if another thread does a system call and the thread doing the | ||
2675 | * stop is preempted). | ||
2676 | */ | ||
2677 | static int | ||
2678 | ath5k_stop_hw(struct ath5k_softc *sc) | ||
2679 | { | ||
2680 | int ret; | ||
2681 | |||
2682 | mutex_lock(&sc->lock); | ||
2683 | ret = ath5k_stop_locked(sc); | ||
2684 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2685 | /* | ||
2686 | * Don't set the card in full sleep mode! | ||
2687 | * | ||
2688 | * a) When the device is in this state it must be carefully | ||
2689 | * woken up or references to registers in the PCI clock | ||
2690 | * domain may freeze the bus (and system). This varies | ||
2691 | * by chip and is mostly an issue with newer parts | ||
2692 | * (madwifi sources mentioned srev >= 0x78) that go to | ||
2693 | * sleep more quickly. | ||
2694 | * | ||
2695 | * b) On older chips full sleep results a weird behaviour | ||
2696 | * during wakeup. I tested various cards with srev < 0x78 | ||
2697 | * and they don't wake up after module reload, a second | ||
2698 | * module reload is needed to bring the card up again. | ||
2699 | * | ||
2700 | * Until we figure out what's going on don't enable | ||
2701 | * full chip reset on any chip (this is what Legacy HAL | ||
2702 | * and Sam's HAL do anyway). Instead Perform a full reset | ||
2703 | * on the device (same as initial state after attach) and | ||
2704 | * leave it idle (keep MAC/BB on warm reset) */ | ||
2705 | ret = ath5k_hw_on_hold(sc->ah); | ||
2706 | |||
2707 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2708 | "putting device to sleep\n"); | ||
2709 | } | ||
2710 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
2711 | |||
2712 | mmiowb(); | ||
2713 | mutex_unlock(&sc->lock); | ||
2714 | |||
2715 | stop_tasklets(sc); | ||
2716 | |||
2717 | ath5k_rfkill_hw_stop(sc->ah); | ||
2718 | |||
2719 | return ret; | ||
2720 | } | ||
2721 | |||
2722 | static void | 2025 | static void |
2723 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | 2026 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) |
2724 | { | 2027 | { |
@@ -2855,14 +2158,13 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2855 | sc->curchan->center_freq)); | 2158 | sc->curchan->center_freq)); |
2856 | 2159 | ||
2857 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration | 2160 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration |
2858 | * doesn't. We stop the queues so that calibration doesn't interfere | 2161 | * doesn't. |
2859 | * with TX and don't run it as often */ | 2162 | * TODO: We should stop TX here, so that it doesn't interfere. |
2163 | * Note that stopping the queues is not enough to stop TX! */ | ||
2860 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { | 2164 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { |
2861 | ah->ah_cal_next_nf = jiffies + | 2165 | ah->ah_cal_next_nf = jiffies + |
2862 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); | 2166 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); |
2863 | ieee80211_stop_queues(sc->hw); | ||
2864 | ath5k_hw_update_noise_floor(ah); | 2167 | ath5k_hw_update_noise_floor(ah); |
2865 | ieee80211_wake_queues(sc->hw); | ||
2866 | } | 2168 | } |
2867 | 2169 | ||
2868 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | 2170 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; |
@@ -2881,68 +2183,205 @@ ath5k_tasklet_ani(unsigned long data) | |||
2881 | } | 2183 | } |
2882 | 2184 | ||
2883 | 2185 | ||
2884 | /********************\ | 2186 | static void |
2885 | * Mac80211 functions * | 2187 | ath5k_tx_complete_poll_work(struct work_struct *work) |
2886 | \********************/ | 2188 | { |
2189 | struct ath5k_softc *sc = container_of(work, struct ath5k_softc, | ||
2190 | tx_complete_work.work); | ||
2191 | struct ath5k_txq *txq; | ||
2192 | int i; | ||
2193 | bool needreset = false; | ||
2194 | |||
2195 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { | ||
2196 | if (sc->txqs[i].setup) { | ||
2197 | txq = &sc->txqs[i]; | ||
2198 | spin_lock_bh(&txq->lock); | ||
2199 | if (txq->txq_len > 1) { | ||
2200 | if (txq->txq_poll_mark) { | ||
2201 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, | ||
2202 | "TX queue stuck %d\n", | ||
2203 | txq->qnum); | ||
2204 | needreset = true; | ||
2205 | txq->txq_stuck++; | ||
2206 | spin_unlock_bh(&txq->lock); | ||
2207 | break; | ||
2208 | } else { | ||
2209 | txq->txq_poll_mark = true; | ||
2210 | } | ||
2211 | } | ||
2212 | spin_unlock_bh(&txq->lock); | ||
2213 | } | ||
2214 | } | ||
2215 | |||
2216 | if (needreset) { | ||
2217 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2218 | "TX queues stuck, resetting\n"); | ||
2219 | ath5k_reset(sc, sc->curchan); | ||
2220 | } | ||
2221 | |||
2222 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | ||
2223 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); | ||
2224 | } | ||
2225 | |||
2226 | |||
2227 | /*************************\ | ||
2228 | * Initialization routines * | ||
2229 | \*************************/ | ||
2887 | 2230 | ||
2888 | static int | 2231 | static int |
2889 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 2232 | ath5k_stop_locked(struct ath5k_softc *sc) |
2890 | { | 2233 | { |
2891 | struct ath5k_softc *sc = hw->priv; | 2234 | struct ath5k_hw *ah = sc->ah; |
2235 | |||
2236 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", | ||
2237 | test_bit(ATH_STAT_INVALID, sc->status)); | ||
2238 | |||
2239 | /* | ||
2240 | * Shutdown the hardware and driver: | ||
2241 | * stop output from above | ||
2242 | * disable interrupts | ||
2243 | * turn off timers | ||
2244 | * turn off the radio | ||
2245 | * clear transmit machinery | ||
2246 | * clear receive machinery | ||
2247 | * drain and release tx queues | ||
2248 | * reclaim beacon resources | ||
2249 | * power down hardware | ||
2250 | * | ||
2251 | * Note that some of this work is not possible if the | ||
2252 | * hardware is gone (invalid). | ||
2253 | */ | ||
2254 | ieee80211_stop_queues(sc->hw); | ||
2255 | |||
2256 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2257 | ath5k_led_off(sc); | ||
2258 | ath5k_hw_set_imr(ah, 0); | ||
2259 | synchronize_irq(sc->pdev->irq); | ||
2260 | } | ||
2261 | ath5k_txq_cleanup(sc); | ||
2262 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2263 | ath5k_rx_stop(sc); | ||
2264 | ath5k_hw_phy_disable(ah); | ||
2265 | } | ||
2892 | 2266 | ||
2893 | return ath5k_tx_queue(hw, skb, sc->txq); | 2267 | return 0; |
2894 | } | 2268 | } |
2895 | 2269 | ||
2896 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | 2270 | static int |
2897 | struct ath5k_txq *txq) | 2271 | ath5k_init(struct ath5k_softc *sc) |
2898 | { | 2272 | { |
2899 | struct ath5k_softc *sc = hw->priv; | 2273 | struct ath5k_hw *ah = sc->ah; |
2900 | struct ath5k_buf *bf; | 2274 | struct ath_common *common = ath5k_hw_common(ah); |
2901 | unsigned long flags; | 2275 | int ret, i; |
2902 | int padsize; | ||
2903 | 2276 | ||
2904 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2277 | mutex_lock(&sc->lock); |
2278 | |||
2279 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | ||
2905 | 2280 | ||
2906 | /* | 2281 | /* |
2907 | * The hardware expects the header padded to 4 byte boundaries. | 2282 | * Stop anything previously setup. This is safe |
2908 | * If this is not the case, we add the padding after the header. | 2283 | * no matter this is the first time through or not. |
2909 | */ | 2284 | */ |
2910 | padsize = ath5k_add_padding(skb); | 2285 | ath5k_stop_locked(sc); |
2911 | if (padsize < 0) { | ||
2912 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" | ||
2913 | " headroom to pad"); | ||
2914 | goto drop_packet; | ||
2915 | } | ||
2916 | 2286 | ||
2917 | spin_lock_irqsave(&sc->txbuflock, flags); | 2287 | /* |
2918 | if (list_empty(&sc->txbuf)) { | 2288 | * The basic interface to setting the hardware in a good |
2919 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | 2289 | * state is ``reset''. On return the hardware is known to |
2920 | spin_unlock_irqrestore(&sc->txbuflock, flags); | 2290 | * be powered up and with interrupts disabled. This must |
2921 | ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); | 2291 | * be followed by initialization of the appropriate bits |
2922 | goto drop_packet; | 2292 | * and then setup of the interrupt mask. |
2923 | } | 2293 | */ |
2924 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | 2294 | sc->curchan = sc->hw->conf.channel; |
2925 | list_del(&bf->list); | 2295 | sc->curband = &sc->sbands[sc->curchan->band]; |
2926 | sc->txbuf_len--; | 2296 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2927 | if (list_empty(&sc->txbuf)) | 2297 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2928 | ieee80211_stop_queues(hw); | 2298 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2929 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2930 | 2299 | ||
2931 | bf->skb = skb; | 2300 | ret = ath5k_reset(sc, NULL); |
2301 | if (ret) | ||
2302 | goto done; | ||
2932 | 2303 | ||
2933 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { | 2304 | ath5k_rfkill_hw_start(ah); |
2934 | bf->skb = NULL; | 2305 | |
2935 | spin_lock_irqsave(&sc->txbuflock, flags); | 2306 | /* |
2936 | list_add_tail(&bf->list, &sc->txbuf); | 2307 | * Reset the key cache since some parts do not reset the |
2937 | sc->txbuf_len++; | 2308 | * contents on initial power up or resume from suspend. |
2938 | spin_unlock_irqrestore(&sc->txbuflock, flags); | 2309 | */ |
2939 | goto drop_packet; | 2310 | for (i = 0; i < common->keymax; i++) |
2311 | ath_hw_keyreset(common, (u16) i); | ||
2312 | |||
2313 | ath5k_hw_set_ack_bitrate_high(ah, true); | ||
2314 | ret = 0; | ||
2315 | done: | ||
2316 | mmiowb(); | ||
2317 | mutex_unlock(&sc->lock); | ||
2318 | |||
2319 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | ||
2320 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); | ||
2321 | |||
2322 | return ret; | ||
2323 | } | ||
2324 | |||
2325 | static void stop_tasklets(struct ath5k_softc *sc) | ||
2326 | { | ||
2327 | tasklet_kill(&sc->rxtq); | ||
2328 | tasklet_kill(&sc->txtq); | ||
2329 | tasklet_kill(&sc->calib); | ||
2330 | tasklet_kill(&sc->beacontq); | ||
2331 | tasklet_kill(&sc->ani_tasklet); | ||
2332 | } | ||
2333 | |||
2334 | /* | ||
2335 | * Stop the device, grabbing the top-level lock to protect | ||
2336 | * against concurrent entry through ath5k_init (which can happen | ||
2337 | * if another thread does a system call and the thread doing the | ||
2338 | * stop is preempted). | ||
2339 | */ | ||
2340 | static int | ||
2341 | ath5k_stop_hw(struct ath5k_softc *sc) | ||
2342 | { | ||
2343 | int ret; | ||
2344 | |||
2345 | mutex_lock(&sc->lock); | ||
2346 | ret = ath5k_stop_locked(sc); | ||
2347 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2348 | /* | ||
2349 | * Don't set the card in full sleep mode! | ||
2350 | * | ||
2351 | * a) When the device is in this state it must be carefully | ||
2352 | * woken up or references to registers in the PCI clock | ||
2353 | * domain may freeze the bus (and system). This varies | ||
2354 | * by chip and is mostly an issue with newer parts | ||
2355 | * (madwifi sources mentioned srev >= 0x78) that go to | ||
2356 | * sleep more quickly. | ||
2357 | * | ||
2358 | * b) On older chips full sleep results a weird behaviour | ||
2359 | * during wakeup. I tested various cards with srev < 0x78 | ||
2360 | * and they don't wake up after module reload, a second | ||
2361 | * module reload is needed to bring the card up again. | ||
2362 | * | ||
2363 | * Until we figure out what's going on don't enable | ||
2364 | * full chip reset on any chip (this is what Legacy HAL | ||
2365 | * and Sam's HAL do anyway). Instead Perform a full reset | ||
2366 | * on the device (same as initial state after attach) and | ||
2367 | * leave it idle (keep MAC/BB on warm reset) */ | ||
2368 | ret = ath5k_hw_on_hold(sc->ah); | ||
2369 | |||
2370 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2371 | "putting device to sleep\n"); | ||
2940 | } | 2372 | } |
2941 | return NETDEV_TX_OK; | 2373 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
2942 | 2374 | ||
2943 | drop_packet: | 2375 | mmiowb(); |
2944 | dev_kfree_skb_any(skb); | 2376 | mutex_unlock(&sc->lock); |
2945 | return NETDEV_TX_OK; | 2377 | |
2378 | stop_tasklets(sc); | ||
2379 | |||
2380 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
2381 | |||
2382 | ath5k_rfkill_hw_stop(sc->ah); | ||
2383 | |||
2384 | return ret; | ||
2946 | } | 2385 | } |
2947 | 2386 | ||
2948 | /* | 2387 | /* |
@@ -3019,6 +2458,208 @@ static void ath5k_reset_work(struct work_struct *work) | |||
3019 | mutex_unlock(&sc->lock); | 2458 | mutex_unlock(&sc->lock); |
3020 | } | 2459 | } |
3021 | 2460 | ||
2461 | static int | ||
2462 | ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
2463 | { | ||
2464 | struct ath5k_softc *sc = hw->priv; | ||
2465 | struct ath5k_hw *ah = sc->ah; | ||
2466 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); | ||
2467 | struct ath5k_txq *txq; | ||
2468 | u8 mac[ETH_ALEN] = {}; | ||
2469 | int ret; | ||
2470 | |||
2471 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); | ||
2472 | |||
2473 | /* | ||
2474 | * Check if the MAC has multi-rate retry support. | ||
2475 | * We do this by trying to setup a fake extended | ||
2476 | * descriptor. MACs that don't have support will | ||
2477 | * return false w/o doing anything. MACs that do | ||
2478 | * support it will return true w/o doing anything. | ||
2479 | */ | ||
2480 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | ||
2481 | |||
2482 | if (ret < 0) | ||
2483 | goto err; | ||
2484 | if (ret > 0) | ||
2485 | __set_bit(ATH_STAT_MRRETRY, sc->status); | ||
2486 | |||
2487 | /* | ||
2488 | * Collect the channel list. The 802.11 layer | ||
2489 | * is resposible for filtering this list based | ||
2490 | * on settings like the phy mode and regulatory | ||
2491 | * domain restrictions. | ||
2492 | */ | ||
2493 | ret = ath5k_setup_bands(hw); | ||
2494 | if (ret) { | ||
2495 | ATH5K_ERR(sc, "can't get channels\n"); | ||
2496 | goto err; | ||
2497 | } | ||
2498 | |||
2499 | /* NB: setup here so ath5k_rate_update is happy */ | ||
2500 | if (test_bit(AR5K_MODE_11A, ah->ah_modes)) | ||
2501 | ath5k_setcurmode(sc, AR5K_MODE_11A); | ||
2502 | else | ||
2503 | ath5k_setcurmode(sc, AR5K_MODE_11B); | ||
2504 | |||
2505 | /* | ||
2506 | * Allocate tx+rx descriptors and populate the lists. | ||
2507 | */ | ||
2508 | ret = ath5k_desc_alloc(sc, pdev); | ||
2509 | if (ret) { | ||
2510 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
2511 | goto err; | ||
2512 | } | ||
2513 | |||
2514 | /* | ||
2515 | * Allocate hardware transmit queues: one queue for | ||
2516 | * beacon frames and one data queue for each QoS | ||
2517 | * priority. Note that hw functions handle resetting | ||
2518 | * these queues at the needed time. | ||
2519 | */ | ||
2520 | ret = ath5k_beaconq_setup(ah); | ||
2521 | if (ret < 0) { | ||
2522 | ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); | ||
2523 | goto err_desc; | ||
2524 | } | ||
2525 | sc->bhalq = ret; | ||
2526 | sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); | ||
2527 | if (IS_ERR(sc->cabq)) { | ||
2528 | ATH5K_ERR(sc, "can't setup cab queue\n"); | ||
2529 | ret = PTR_ERR(sc->cabq); | ||
2530 | goto err_bhal; | ||
2531 | } | ||
2532 | |||
2533 | /* This order matches mac80211's queue priority, so we can | ||
2534 | * directly use the mac80211 queue number without any mapping */ | ||
2535 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); | ||
2536 | if (IS_ERR(txq)) { | ||
2537 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2538 | ret = PTR_ERR(txq); | ||
2539 | goto err_queues; | ||
2540 | } | ||
2541 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); | ||
2542 | if (IS_ERR(txq)) { | ||
2543 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2544 | ret = PTR_ERR(txq); | ||
2545 | goto err_queues; | ||
2546 | } | ||
2547 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); | ||
2548 | if (IS_ERR(txq)) { | ||
2549 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2550 | ret = PTR_ERR(txq); | ||
2551 | goto err_queues; | ||
2552 | } | ||
2553 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); | ||
2554 | if (IS_ERR(txq)) { | ||
2555 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2556 | ret = PTR_ERR(txq); | ||
2557 | goto err_queues; | ||
2558 | } | ||
2559 | hw->queues = 4; | ||
2560 | |||
2561 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | ||
2562 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | ||
2563 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | ||
2564 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | ||
2565 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
2566 | |||
2567 | INIT_WORK(&sc->reset_work, ath5k_reset_work); | ||
2568 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); | ||
2569 | |||
2570 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
2571 | if (ret) { | ||
2572 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
2573 | sc->pdev->device); | ||
2574 | goto err_queues; | ||
2575 | } | ||
2576 | |||
2577 | SET_IEEE80211_PERM_ADDR(hw, mac); | ||
2578 | /* All MAC address bits matter for ACKs */ | ||
2579 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
2580 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
2581 | |||
2582 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | ||
2583 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); | ||
2584 | if (ret) { | ||
2585 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); | ||
2586 | goto err_queues; | ||
2587 | } | ||
2588 | |||
2589 | ret = ieee80211_register_hw(hw); | ||
2590 | if (ret) { | ||
2591 | ATH5K_ERR(sc, "can't register ieee80211 hw\n"); | ||
2592 | goto err_queues; | ||
2593 | } | ||
2594 | |||
2595 | if (!ath_is_world_regd(regulatory)) | ||
2596 | regulatory_hint(hw->wiphy, regulatory->alpha2); | ||
2597 | |||
2598 | ath5k_init_leds(sc); | ||
2599 | |||
2600 | ath5k_sysfs_register(sc); | ||
2601 | |||
2602 | return 0; | ||
2603 | err_queues: | ||
2604 | ath5k_txq_release(sc); | ||
2605 | err_bhal: | ||
2606 | ath5k_hw_release_tx_queue(ah, sc->bhalq); | ||
2607 | err_desc: | ||
2608 | ath5k_desc_free(sc, pdev); | ||
2609 | err: | ||
2610 | return ret; | ||
2611 | } | ||
2612 | |||
2613 | static void | ||
2614 | ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
2615 | { | ||
2616 | struct ath5k_softc *sc = hw->priv; | ||
2617 | |||
2618 | /* | ||
2619 | * NB: the order of these is important: | ||
2620 | * o call the 802.11 layer before detaching ath5k_hw to | ||
2621 | * ensure callbacks into the driver to delete global | ||
2622 | * key cache entries can be handled | ||
2623 | * o reclaim the tx queue data structures after calling | ||
2624 | * the 802.11 layer as we'll get called back to reclaim | ||
2625 | * node state and potentially want to use them | ||
2626 | * o to cleanup the tx queues the hal is called, so detach | ||
2627 | * it last | ||
2628 | * XXX: ??? detach ath5k_hw ??? | ||
2629 | * Other than that, it's straightforward... | ||
2630 | */ | ||
2631 | ieee80211_unregister_hw(hw); | ||
2632 | ath5k_desc_free(sc, pdev); | ||
2633 | ath5k_txq_release(sc); | ||
2634 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | ||
2635 | ath5k_unregister_leds(sc); | ||
2636 | |||
2637 | ath5k_sysfs_unregister(sc); | ||
2638 | /* | ||
2639 | * NB: can't reclaim these until after ieee80211_ifdetach | ||
2640 | * returns because we'll get called back to reclaim node | ||
2641 | * state and potentially want to use them. | ||
2642 | */ | ||
2643 | } | ||
2644 | |||
2645 | /********************\ | ||
2646 | * Mac80211 functions * | ||
2647 | \********************/ | ||
2648 | |||
2649 | static int | ||
2650 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
2651 | { | ||
2652 | struct ath5k_softc *sc = hw->priv; | ||
2653 | u16 qnum = skb_get_queue_mapping(skb); | ||
2654 | |||
2655 | if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { | ||
2656 | dev_kfree_skb_any(skb); | ||
2657 | return 0; | ||
2658 | } | ||
2659 | |||
2660 | return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); | ||
2661 | } | ||
2662 | |||
3022 | static int ath5k_start(struct ieee80211_hw *hw) | 2663 | static int ath5k_start(struct ieee80211_hw *hw) |
3023 | { | 2664 | { |
3024 | return ath5k_init(hw->priv); | 2665 | return ath5k_init(hw->priv); |
@@ -3291,18 +2932,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3291 | if (modparam_nohwcrypt) | 2932 | if (modparam_nohwcrypt) |
3292 | return -EOPNOTSUPP; | 2933 | return -EOPNOTSUPP; |
3293 | 2934 | ||
3294 | if (sc->opmode == NL80211_IFTYPE_AP) | ||
3295 | return -EOPNOTSUPP; | ||
3296 | |||
3297 | switch (key->cipher) { | 2935 | switch (key->cipher) { |
3298 | case WLAN_CIPHER_SUITE_WEP40: | 2936 | case WLAN_CIPHER_SUITE_WEP40: |
3299 | case WLAN_CIPHER_SUITE_WEP104: | 2937 | case WLAN_CIPHER_SUITE_WEP104: |
3300 | case WLAN_CIPHER_SUITE_TKIP: | 2938 | case WLAN_CIPHER_SUITE_TKIP: |
3301 | break; | 2939 | break; |
3302 | case WLAN_CIPHER_SUITE_CCMP: | 2940 | case WLAN_CIPHER_SUITE_CCMP: |
3303 | if (sc->ah->ah_aes_support) | 2941 | if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) |
3304 | break; | 2942 | break; |
3305 | |||
3306 | return -EOPNOTSUPP; | 2943 | return -EOPNOTSUPP; |
3307 | default: | 2944 | default: |
3308 | WARN_ON(1); | 2945 | WARN_ON(1); |
@@ -3313,27 +2950,25 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3313 | 2950 | ||
3314 | switch (cmd) { | 2951 | switch (cmd) { |
3315 | case SET_KEY: | 2952 | case SET_KEY: |
3316 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, | 2953 | ret = ath_key_config(common, vif, sta, key); |
3317 | sta ? sta->addr : NULL); | 2954 | if (ret >= 0) { |
3318 | if (ret) { | 2955 | key->hw_key_idx = ret; |
3319 | ATH5K_ERR(sc, "can't set the key\n"); | 2956 | /* push IV and Michael MIC generation to stack */ |
3320 | goto unlock; | 2957 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
2958 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
2959 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
2960 | if (key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
2961 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | ||
2962 | ret = 0; | ||
3321 | } | 2963 | } |
3322 | __set_bit(key->keyidx, common->keymap); | ||
3323 | key->hw_key_idx = key->keyidx; | ||
3324 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | | ||
3325 | IEEE80211_KEY_FLAG_GENERATE_MMIC); | ||
3326 | break; | 2964 | break; |
3327 | case DISABLE_KEY: | 2965 | case DISABLE_KEY: |
3328 | ath5k_hw_reset_key(sc->ah, key->keyidx); | 2966 | ath_key_delete(common, key); |
3329 | __clear_bit(key->keyidx, common->keymap); | ||
3330 | break; | 2967 | break; |
3331 | default: | 2968 | default: |
3332 | ret = -EINVAL; | 2969 | ret = -EINVAL; |
3333 | goto unlock; | ||
3334 | } | 2970 | } |
3335 | 2971 | ||
3336 | unlock: | ||
3337 | mmiowb(); | 2972 | mmiowb(); |
3338 | mutex_unlock(&sc->lock); | 2973 | mutex_unlock(&sc->lock); |
3339 | return ret; | 2974 | return ret; |
@@ -3403,43 +3038,6 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) | |||
3403 | ath5k_hw_reset_tsf(sc->ah); | 3038 | ath5k_hw_reset_tsf(sc->ah); |
3404 | } | 3039 | } |
3405 | 3040 | ||
3406 | /* | ||
3407 | * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, | ||
3408 | * this is called only once at config_bss time, for AP we do it every | ||
3409 | * SWBA interrupt so that the TIM will reflect buffered frames. | ||
3410 | * | ||
3411 | * Called with the beacon lock. | ||
3412 | */ | ||
3413 | static int | ||
3414 | ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
3415 | { | ||
3416 | int ret; | ||
3417 | struct ath5k_softc *sc = hw->priv; | ||
3418 | struct sk_buff *skb; | ||
3419 | |||
3420 | if (WARN_ON(!vif)) { | ||
3421 | ret = -EINVAL; | ||
3422 | goto out; | ||
3423 | } | ||
3424 | |||
3425 | skb = ieee80211_beacon_get(hw, vif); | ||
3426 | |||
3427 | if (!skb) { | ||
3428 | ret = -ENOMEM; | ||
3429 | goto out; | ||
3430 | } | ||
3431 | |||
3432 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | ||
3433 | |||
3434 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
3435 | sc->bbuf->skb = skb; | ||
3436 | ret = ath5k_beacon_setup(sc, sc->bbuf); | ||
3437 | if (ret) | ||
3438 | sc->bbuf->skb = NULL; | ||
3439 | out: | ||
3440 | return ret; | ||
3441 | } | ||
3442 | |||
3443 | static void | 3041 | static void |
3444 | set_beacon_filter(struct ieee80211_hw *hw, bool enable) | 3042 | set_beacon_filter(struct ieee80211_hw *hw, bool enable) |
3445 | { | 3043 | { |
@@ -3545,3 +3143,402 @@ static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | |||
3545 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | 3143 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); |
3546 | mutex_unlock(&sc->lock); | 3144 | mutex_unlock(&sc->lock); |
3547 | } | 3145 | } |
3146 | |||
3147 | static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
3148 | const struct ieee80211_tx_queue_params *params) | ||
3149 | { | ||
3150 | struct ath5k_softc *sc = hw->priv; | ||
3151 | struct ath5k_hw *ah = sc->ah; | ||
3152 | struct ath5k_txq_info qi; | ||
3153 | int ret = 0; | ||
3154 | |||
3155 | if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) | ||
3156 | return 0; | ||
3157 | |||
3158 | mutex_lock(&sc->lock); | ||
3159 | |||
3160 | ath5k_hw_get_tx_queueprops(ah, queue, &qi); | ||
3161 | |||
3162 | qi.tqi_aifs = params->aifs; | ||
3163 | qi.tqi_cw_min = params->cw_min; | ||
3164 | qi.tqi_cw_max = params->cw_max; | ||
3165 | qi.tqi_burst_time = params->txop; | ||
3166 | |||
3167 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
3168 | "Configure tx [queue %d], " | ||
3169 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | ||
3170 | queue, params->aifs, params->cw_min, | ||
3171 | params->cw_max, params->txop); | ||
3172 | |||
3173 | if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { | ||
3174 | ATH5K_ERR(sc, | ||
3175 | "Unable to update hardware queue %u!\n", queue); | ||
3176 | ret = -EIO; | ||
3177 | } else | ||
3178 | ath5k_hw_reset_tx_queue(ah, queue); | ||
3179 | |||
3180 | mutex_unlock(&sc->lock); | ||
3181 | |||
3182 | return ret; | ||
3183 | } | ||
3184 | |||
3185 | static const struct ieee80211_ops ath5k_hw_ops = { | ||
3186 | .tx = ath5k_tx, | ||
3187 | .start = ath5k_start, | ||
3188 | .stop = ath5k_stop, | ||
3189 | .add_interface = ath5k_add_interface, | ||
3190 | .remove_interface = ath5k_remove_interface, | ||
3191 | .config = ath5k_config, | ||
3192 | .prepare_multicast = ath5k_prepare_multicast, | ||
3193 | .configure_filter = ath5k_configure_filter, | ||
3194 | .set_key = ath5k_set_key, | ||
3195 | .get_stats = ath5k_get_stats, | ||
3196 | .get_survey = ath5k_get_survey, | ||
3197 | .conf_tx = ath5k_conf_tx, | ||
3198 | .get_tsf = ath5k_get_tsf, | ||
3199 | .set_tsf = ath5k_set_tsf, | ||
3200 | .reset_tsf = ath5k_reset_tsf, | ||
3201 | .bss_info_changed = ath5k_bss_info_changed, | ||
3202 | .sw_scan_start = ath5k_sw_scan_start, | ||
3203 | .sw_scan_complete = ath5k_sw_scan_complete, | ||
3204 | .set_coverage_class = ath5k_set_coverage_class, | ||
3205 | }; | ||
3206 | |||
3207 | /********************\ | ||
3208 | * PCI Initialization * | ||
3209 | \********************/ | ||
3210 | |||
3211 | static int __devinit | ||
3212 | ath5k_pci_probe(struct pci_dev *pdev, | ||
3213 | const struct pci_device_id *id) | ||
3214 | { | ||
3215 | void __iomem *mem; | ||
3216 | struct ath5k_softc *sc; | ||
3217 | struct ath_common *common; | ||
3218 | struct ieee80211_hw *hw; | ||
3219 | int ret; | ||
3220 | u8 csz; | ||
3221 | |||
3222 | /* | ||
3223 | * L0s needs to be disabled on all ath5k cards. | ||
3224 | * | ||
3225 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
3226 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
3227 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
3228 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
3229 | * though but cannot currently undue the effect of a blacklist, for | ||
3230 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
3231 | * the device link capability. | ||
3232 | * | ||
3233 | * It may be possible in the future to implement some PCI API to allow | ||
3234 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
3235 | * best to accept that both L0s and L1 will be disabled completely for | ||
3236 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
3237 | * issue present. Motivation for adding this new API will be to help | ||
3238 | * with power consumption for some of these devices. | ||
3239 | */ | ||
3240 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
3241 | |||
3242 | ret = pci_enable_device(pdev); | ||
3243 | if (ret) { | ||
3244 | dev_err(&pdev->dev, "can't enable device\n"); | ||
3245 | goto err; | ||
3246 | } | ||
3247 | |||
3248 | /* XXX 32-bit addressing only */ | ||
3249 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
3250 | if (ret) { | ||
3251 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
3252 | goto err_dis; | ||
3253 | } | ||
3254 | |||
3255 | /* | ||
3256 | * Cache line size is used to size and align various | ||
3257 | * structures used to communicate with the hardware. | ||
3258 | */ | ||
3259 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
3260 | if (csz == 0) { | ||
3261 | /* | ||
3262 | * Linux 2.4.18 (at least) writes the cache line size | ||
3263 | * register as a 16-bit wide register which is wrong. | ||
3264 | * We must have this setup properly for rx buffer | ||
3265 | * DMA to work so force a reasonable value here if it | ||
3266 | * comes up zero. | ||
3267 | */ | ||
3268 | csz = L1_CACHE_BYTES >> 2; | ||
3269 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
3270 | } | ||
3271 | /* | ||
3272 | * The default setting of latency timer yields poor results, | ||
3273 | * set it to the value used by other systems. It may be worth | ||
3274 | * tweaking this setting more. | ||
3275 | */ | ||
3276 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
3277 | |||
3278 | /* Enable bus mastering */ | ||
3279 | pci_set_master(pdev); | ||
3280 | |||
3281 | /* | ||
3282 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
3283 | * PCI Tx retries from interfering with C3 CPU state. | ||
3284 | */ | ||
3285 | pci_write_config_byte(pdev, 0x41, 0); | ||
3286 | |||
3287 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
3288 | if (ret) { | ||
3289 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
3290 | goto err_dis; | ||
3291 | } | ||
3292 | |||
3293 | mem = pci_iomap(pdev, 0, 0); | ||
3294 | if (!mem) { | ||
3295 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
3296 | ret = -EIO; | ||
3297 | goto err_reg; | ||
3298 | } | ||
3299 | |||
3300 | /* | ||
3301 | * Allocate hw (mac80211 main struct) | ||
3302 | * and hw->priv (driver private data) | ||
3303 | */ | ||
3304 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
3305 | if (hw == NULL) { | ||
3306 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
3307 | ret = -ENOMEM; | ||
3308 | goto err_map; | ||
3309 | } | ||
3310 | |||
3311 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
3312 | |||
3313 | /* Initialize driver private data */ | ||
3314 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3315 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
3316 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
3317 | IEEE80211_HW_SIGNAL_DBM; | ||
3318 | |||
3319 | hw->wiphy->interface_modes = | ||
3320 | BIT(NL80211_IFTYPE_AP) | | ||
3321 | BIT(NL80211_IFTYPE_STATION) | | ||
3322 | BIT(NL80211_IFTYPE_ADHOC) | | ||
3323 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
3324 | |||
3325 | hw->extra_tx_headroom = 2; | ||
3326 | hw->channel_change_time = 5000; | ||
3327 | sc = hw->priv; | ||
3328 | sc->hw = hw; | ||
3329 | sc->pdev = pdev; | ||
3330 | |||
3331 | ath5k_debug_init_device(sc); | ||
3332 | |||
3333 | /* | ||
3334 | * Mark the device as detached to avoid processing | ||
3335 | * interrupts until setup is complete. | ||
3336 | */ | ||
3337 | __set_bit(ATH_STAT_INVALID, sc->status); | ||
3338 | |||
3339 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
3340 | sc->opmode = NL80211_IFTYPE_STATION; | ||
3341 | sc->bintval = 1000; | ||
3342 | mutex_init(&sc->lock); | ||
3343 | spin_lock_init(&sc->rxbuflock); | ||
3344 | spin_lock_init(&sc->txbuflock); | ||
3345 | spin_lock_init(&sc->block); | ||
3346 | |||
3347 | /* Set private data */ | ||
3348 | pci_set_drvdata(pdev, sc); | ||
3349 | |||
3350 | /* Setup interrupt handler */ | ||
3351 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | ||
3352 | if (ret) { | ||
3353 | ATH5K_ERR(sc, "request_irq failed\n"); | ||
3354 | goto err_free; | ||
3355 | } | ||
3356 | |||
3357 | /* If we passed the test, malloc an ath5k_hw struct */ | ||
3358 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
3359 | if (!sc->ah) { | ||
3360 | ret = -ENOMEM; | ||
3361 | ATH5K_ERR(sc, "out of memory\n"); | ||
3362 | goto err_irq; | ||
3363 | } | ||
3364 | |||
3365 | sc->ah->ah_sc = sc; | ||
3366 | sc->ah->ah_iobase = sc->iobase; | ||
3367 | common = ath5k_hw_common(sc->ah); | ||
3368 | common->ops = &ath5k_common_ops; | ||
3369 | common->ah = sc->ah; | ||
3370 | common->hw = hw; | ||
3371 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
3372 | |||
3373 | /* Initialize device */ | ||
3374 | ret = ath5k_hw_attach(sc); | ||
3375 | if (ret) { | ||
3376 | goto err_free_ah; | ||
3377 | } | ||
3378 | |||
3379 | /* set up multi-rate retry capabilities */ | ||
3380 | if (sc->ah->ah_version == AR5K_AR5212) { | ||
3381 | hw->max_rates = 4; | ||
3382 | hw->max_rate_tries = 11; | ||
3383 | } | ||
3384 | |||
3385 | /* Finish private driver data initialization */ | ||
3386 | ret = ath5k_attach(pdev, hw); | ||
3387 | if (ret) | ||
3388 | goto err_ah; | ||
3389 | |||
3390 | ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", | ||
3391 | ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), | ||
3392 | sc->ah->ah_mac_srev, | ||
3393 | sc->ah->ah_phy_revision); | ||
3394 | |||
3395 | if (!sc->ah->ah_single_chip) { | ||
3396 | /* Single chip radio (!RF5111) */ | ||
3397 | if (sc->ah->ah_radio_5ghz_revision && | ||
3398 | !sc->ah->ah_radio_2ghz_revision) { | ||
3399 | /* No 5GHz support -> report 2GHz radio */ | ||
3400 | if (!test_bit(AR5K_MODE_11A, | ||
3401 | sc->ah->ah_capabilities.cap_mode)) { | ||
3402 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
3403 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
3404 | sc->ah->ah_radio_5ghz_revision), | ||
3405 | sc->ah->ah_radio_5ghz_revision); | ||
3406 | /* No 2GHz support (5110 and some | ||
3407 | * 5Ghz only cards) -> report 5Ghz radio */ | ||
3408 | } else if (!test_bit(AR5K_MODE_11B, | ||
3409 | sc->ah->ah_capabilities.cap_mode)) { | ||
3410 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
3411 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
3412 | sc->ah->ah_radio_5ghz_revision), | ||
3413 | sc->ah->ah_radio_5ghz_revision); | ||
3414 | /* Multiband radio */ | ||
3415 | } else { | ||
3416 | ATH5K_INFO(sc, "RF%s multiband radio found" | ||
3417 | " (0x%x)\n", | ||
3418 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
3419 | sc->ah->ah_radio_5ghz_revision), | ||
3420 | sc->ah->ah_radio_5ghz_revision); | ||
3421 | } | ||
3422 | } | ||
3423 | /* Multi chip radio (RF5111 - RF2111) -> | ||
3424 | * report both 2GHz/5GHz radios */ | ||
3425 | else if (sc->ah->ah_radio_5ghz_revision && | ||
3426 | sc->ah->ah_radio_2ghz_revision){ | ||
3427 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
3428 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
3429 | sc->ah->ah_radio_5ghz_revision), | ||
3430 | sc->ah->ah_radio_5ghz_revision); | ||
3431 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
3432 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
3433 | sc->ah->ah_radio_2ghz_revision), | ||
3434 | sc->ah->ah_radio_2ghz_revision); | ||
3435 | } | ||
3436 | } | ||
3437 | |||
3438 | |||
3439 | /* ready to process interrupts */ | ||
3440 | __clear_bit(ATH_STAT_INVALID, sc->status); | ||
3441 | |||
3442 | return 0; | ||
3443 | err_ah: | ||
3444 | ath5k_hw_detach(sc->ah); | ||
3445 | err_free_ah: | ||
3446 | kfree(sc->ah); | ||
3447 | err_irq: | ||
3448 | free_irq(pdev->irq, sc); | ||
3449 | err_free: | ||
3450 | ieee80211_free_hw(hw); | ||
3451 | err_map: | ||
3452 | pci_iounmap(pdev, mem); | ||
3453 | err_reg: | ||
3454 | pci_release_region(pdev, 0); | ||
3455 | err_dis: | ||
3456 | pci_disable_device(pdev); | ||
3457 | err: | ||
3458 | return ret; | ||
3459 | } | ||
3460 | |||
3461 | static void __devexit | ||
3462 | ath5k_pci_remove(struct pci_dev *pdev) | ||
3463 | { | ||
3464 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
3465 | |||
3466 | ath5k_debug_finish_device(sc); | ||
3467 | ath5k_detach(pdev, sc->hw); | ||
3468 | ath5k_hw_detach(sc->ah); | ||
3469 | kfree(sc->ah); | ||
3470 | free_irq(pdev->irq, sc); | ||
3471 | pci_iounmap(pdev, sc->iobase); | ||
3472 | pci_release_region(pdev, 0); | ||
3473 | pci_disable_device(pdev); | ||
3474 | ieee80211_free_hw(sc->hw); | ||
3475 | } | ||
3476 | |||
3477 | #ifdef CONFIG_PM_SLEEP | ||
3478 | static int ath5k_pci_suspend(struct device *dev) | ||
3479 | { | ||
3480 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); | ||
3481 | |||
3482 | ath5k_led_off(sc); | ||
3483 | return 0; | ||
3484 | } | ||
3485 | |||
3486 | static int ath5k_pci_resume(struct device *dev) | ||
3487 | { | ||
3488 | struct pci_dev *pdev = to_pci_dev(dev); | ||
3489 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
3490 | |||
3491 | /* | ||
3492 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
3493 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
3494 | * PCI Tx retries from interfering with C3 CPU state | ||
3495 | */ | ||
3496 | pci_write_config_byte(pdev, 0x41, 0); | ||
3497 | |||
3498 | ath5k_led_enable(sc); | ||
3499 | return 0; | ||
3500 | } | ||
3501 | |||
3502 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
3503 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
3504 | #else | ||
3505 | #define ATH5K_PM_OPS NULL | ||
3506 | #endif /* CONFIG_PM_SLEEP */ | ||
3507 | |||
3508 | static struct pci_driver ath5k_pci_driver = { | ||
3509 | .name = KBUILD_MODNAME, | ||
3510 | .id_table = ath5k_pci_id_table, | ||
3511 | .probe = ath5k_pci_probe, | ||
3512 | .remove = __devexit_p(ath5k_pci_remove), | ||
3513 | .driver.pm = ATH5K_PM_OPS, | ||
3514 | }; | ||
3515 | |||
3516 | /* | ||
3517 | * Module init/exit functions | ||
3518 | */ | ||
3519 | static int __init | ||
3520 | init_ath5k_pci(void) | ||
3521 | { | ||
3522 | int ret; | ||
3523 | |||
3524 | ath5k_debug_init(); | ||
3525 | |||
3526 | ret = pci_register_driver(&ath5k_pci_driver); | ||
3527 | if (ret) { | ||
3528 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
3529 | return ret; | ||
3530 | } | ||
3531 | |||
3532 | return 0; | ||
3533 | } | ||
3534 | |||
3535 | static void __exit | ||
3536 | exit_ath5k_pci(void) | ||
3537 | { | ||
3538 | pci_unregister_driver(&ath5k_pci_driver); | ||
3539 | |||
3540 | ath5k_debug_finish(); | ||
3541 | } | ||
3542 | |||
3543 | module_init(init_ath5k_pci); | ||
3544 | module_exit(exit_ath5k_pci); | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index dc1241f9c4e8..7f9d0d3018e8 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -60,6 +60,9 @@ | |||
60 | #define ATH_TXBUF 200 /* number of TX buffers */ | 60 | #define ATH_TXBUF 200 /* number of TX buffers */ |
61 | #define ATH_BCBUF 1 /* number of beacon buffers */ | 61 | #define ATH_BCBUF 1 /* number of beacon buffers */ |
62 | 62 | ||
63 | #define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ | ||
64 | #define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ | ||
65 | |||
63 | struct ath5k_buf { | 66 | struct ath5k_buf { |
64 | struct list_head list; | 67 | struct list_head list; |
65 | struct ath5k_desc *desc; /* virtual addr of desc */ | 68 | struct ath5k_desc *desc; /* virtual addr of desc */ |
@@ -83,6 +86,9 @@ struct ath5k_txq { | |||
83 | struct list_head q; /* transmit queue */ | 86 | struct list_head q; /* transmit queue */ |
84 | spinlock_t lock; /* lock on q and link */ | 87 | spinlock_t lock; /* lock on q and link */ |
85 | bool setup; | 88 | bool setup; |
89 | int txq_len; /* number of queued buffers */ | ||
90 | bool txq_poll_mark; | ||
91 | unsigned int txq_stuck; /* informational counter */ | ||
86 | }; | 92 | }; |
87 | 93 | ||
88 | #define ATH5K_LED_MAX_NAME_LEN 31 | 94 | #define ATH5K_LED_MAX_NAME_LEN 31 |
@@ -204,7 +210,6 @@ struct ath5k_softc { | |||
204 | spinlock_t txbuflock; | 210 | spinlock_t txbuflock; |
205 | unsigned int txbuf_len; /* buf count in txbuf list */ | 211 | unsigned int txbuf_len; /* buf count in txbuf list */ |
206 | struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ | 212 | struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ |
207 | struct ath5k_txq *txq; /* main tx queue */ | ||
208 | struct tasklet_struct txtq; /* tx intr tasklet */ | 213 | struct tasklet_struct txtq; /* tx intr tasklet */ |
209 | struct ath5k_led tx_led; /* tx led */ | 214 | struct ath5k_led tx_led; /* tx led */ |
210 | 215 | ||
@@ -230,6 +235,8 @@ struct ath5k_softc { | |||
230 | 235 | ||
231 | struct ath5k_ani_state ani_state; | 236 | struct ath5k_ani_state ani_state; |
232 | struct tasklet_struct ani_tasklet; /* ANI calibration */ | 237 | struct tasklet_struct ani_tasklet; /* ANI calibration */ |
238 | |||
239 | struct delayed_work tx_complete_work; | ||
233 | }; | 240 | }; |
234 | 241 | ||
235 | #define ath5k_hw_hasbssidmask(_ah) \ | 242 | #define ath5k_hw_hasbssidmask(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 1b7c6d7fde93..6583a82a0783 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -763,7 +763,7 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, | |||
763 | 763 | ||
764 | struct ath5k_txq *txq; | 764 | struct ath5k_txq *txq; |
765 | struct ath5k_buf *bf, *bf0; | 765 | struct ath5k_buf *bf, *bf0; |
766 | int i, n = 0; | 766 | int i, n; |
767 | 767 | ||
768 | len += snprintf(buf+len, sizeof(buf)-len, | 768 | len += snprintf(buf+len, sizeof(buf)-len, |
769 | "available txbuffers: %d\n", sc->txbuf_len); | 769 | "available txbuffers: %d\n", sc->txbuf_len); |
@@ -777,9 +777,16 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, | |||
777 | if (!txq->setup) | 777 | if (!txq->setup) |
778 | continue; | 778 | continue; |
779 | 779 | ||
780 | n = 0; | ||
781 | spin_lock_bh(&txq->lock); | ||
780 | list_for_each_entry_safe(bf, bf0, &txq->q, list) | 782 | list_for_each_entry_safe(bf, bf0, &txq->q, list) |
781 | n++; | 783 | n++; |
782 | len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n); | 784 | spin_unlock_bh(&txq->lock); |
785 | |||
786 | len += snprintf(buf+len, sizeof(buf)-len, | ||
787 | " len: %d bufs: %d\n", txq->txq_len, n); | ||
788 | len += snprintf(buf+len, sizeof(buf)-len, | ||
789 | " stuck: %d\n", txq->txq_stuck); | ||
783 | } | 790 | } |
784 | 791 | ||
785 | if (len > sizeof(buf)) | 792 | if (len > sizeof(buf)) |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index bb2e21553d1b..6a891c4484a0 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -640,197 +640,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
640 | 640 | ||
641 | } | 641 | } |
642 | 642 | ||
643 | |||
644 | /*********************\ | ||
645 | * Key table functions * | ||
646 | \*********************/ | ||
647 | |||
648 | /* | ||
649 | * Reset a key entry on the table | ||
650 | */ | ||
651 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | ||
652 | { | ||
653 | unsigned int i, type; | ||
654 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | ||
655 | |||
656 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
657 | |||
658 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); | ||
659 | |||
660 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | ||
661 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | ||
662 | |||
663 | /* Reset associated MIC entry if TKIP | ||
664 | * is enabled located at offset (entry + 64) */ | ||
665 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | ||
666 | AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); | ||
667 | for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) | ||
668 | ath5k_hw_reg_write(ah, 0, | ||
669 | AR5K_KEYTABLE_OFF(micentry, i)); | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * Set NULL encryption on AR5212+ | ||
674 | * | ||
675 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | ||
676 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | ||
677 | * | ||
678 | * Note2: Windows driver (ndiswrapper) sets this to | ||
679 | * 0x00000714 instead of 0x00000007 | ||
680 | */ | ||
681 | if (ah->ah_version >= AR5K_AR5211) { | ||
682 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
683 | AR5K_KEYTABLE_TYPE(entry)); | ||
684 | |||
685 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | ||
686 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
687 | AR5K_KEYTABLE_TYPE(micentry)); | ||
688 | } | ||
689 | } | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static | ||
695 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | ||
696 | { | ||
697 | switch (key->cipher) { | ||
698 | case WLAN_CIPHER_SUITE_TKIP: | ||
699 | return AR5K_KEYTABLE_TYPE_TKIP; | ||
700 | case WLAN_CIPHER_SUITE_CCMP: | ||
701 | return AR5K_KEYTABLE_TYPE_CCM; | ||
702 | case WLAN_CIPHER_SUITE_WEP40: | ||
703 | return AR5K_KEYTABLE_TYPE_40; | ||
704 | case WLAN_CIPHER_SUITE_WEP104: | ||
705 | return AR5K_KEYTABLE_TYPE_104; | ||
706 | default: | ||
707 | return -EINVAL; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | /* | ||
712 | * Set a key entry on the table | ||
713 | */ | ||
714 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
715 | const struct ieee80211_key_conf *key, const u8 *mac) | ||
716 | { | ||
717 | unsigned int i; | ||
718 | int keylen; | ||
719 | __le32 key_v[5] = {}; | ||
720 | __le32 key0 = 0, key1 = 0; | ||
721 | __le32 *rxmic, *txmic; | ||
722 | int keytype; | ||
723 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | ||
724 | bool is_tkip; | ||
725 | const u8 *key_ptr; | ||
726 | |||
727 | is_tkip = (key->cipher == WLAN_CIPHER_SUITE_TKIP); | ||
728 | |||
729 | /* | ||
730 | * key->keylen comes in from mac80211 in bytes. | ||
731 | * TKIP is 128 bit + 128 bit mic | ||
732 | */ | ||
733 | keylen = (is_tkip) ? (128 / 8) : key->keylen; | ||
734 | |||
735 | if (entry > AR5K_KEYTABLE_SIZE || | ||
736 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) | ||
737 | return -EOPNOTSUPP; | ||
738 | |||
739 | if (unlikely(keylen > 16)) | ||
740 | return -EOPNOTSUPP; | ||
741 | |||
742 | keytype = ath5k_keycache_type(key); | ||
743 | if (keytype < 0) | ||
744 | return keytype; | ||
745 | |||
746 | /* | ||
747 | * each key block is 6 bytes wide, written as pairs of | ||
748 | * alternating 32 and 16 bit le values. | ||
749 | */ | ||
750 | key_ptr = key->key; | ||
751 | for (i = 0; keylen >= 6; keylen -= 6) { | ||
752 | memcpy(&key_v[i], key_ptr, 6); | ||
753 | i += 2; | ||
754 | key_ptr += 6; | ||
755 | } | ||
756 | if (keylen) | ||
757 | memcpy(&key_v[i], key_ptr, keylen); | ||
758 | |||
759 | /* intentionally corrupt key until mic is installed */ | ||
760 | if (is_tkip) { | ||
761 | key0 = key_v[0] = ~key_v[0]; | ||
762 | key1 = key_v[1] = ~key_v[1]; | ||
763 | } | ||
764 | |||
765 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
766 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
767 | AR5K_KEYTABLE_OFF(entry, i)); | ||
768 | |||
769 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | ||
770 | |||
771 | if (is_tkip) { | ||
772 | /* Install rx/tx MIC */ | ||
773 | rxmic = (__le32 *) &key->key[16]; | ||
774 | txmic = (__le32 *) &key->key[24]; | ||
775 | |||
776 | if (ah->ah_combined_mic) { | ||
777 | key_v[0] = rxmic[0]; | ||
778 | key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); | ||
779 | key_v[2] = rxmic[1]; | ||
780 | key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); | ||
781 | key_v[4] = txmic[1]; | ||
782 | } else { | ||
783 | key_v[0] = rxmic[0]; | ||
784 | key_v[1] = 0; | ||
785 | key_v[2] = rxmic[1]; | ||
786 | key_v[3] = 0; | ||
787 | key_v[4] = 0; | ||
788 | } | ||
789 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
790 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
791 | AR5K_KEYTABLE_OFF(micentry, i)); | ||
792 | |||
793 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
794 | AR5K_KEYTABLE_TYPE(micentry)); | ||
795 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); | ||
796 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); | ||
797 | |||
798 | /* restore first 2 words of key */ | ||
799 | ath5k_hw_reg_write(ah, le32_to_cpu(~key0), | ||
800 | AR5K_KEYTABLE_OFF(entry, 0)); | ||
801 | ath5k_hw_reg_write(ah, le32_to_cpu(~key1), | ||
802 | AR5K_KEYTABLE_OFF(entry, 1)); | ||
803 | } | ||
804 | |||
805 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | ||
806 | } | ||
807 | |||
808 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | ||
809 | { | ||
810 | u32 low_id, high_id; | ||
811 | |||
812 | /* Invalid entry (key table overflow) */ | ||
813 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
814 | |||
815 | /* | ||
816 | * MAC may be NULL if it's a broadcast key. In this case no need to | ||
817 | * to compute get_unaligned_le32 and get_unaligned_le16 as we | ||
818 | * already know it. | ||
819 | */ | ||
820 | if (!mac) { | ||
821 | low_id = 0xffffffff; | ||
822 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | ||
823 | } else { | ||
824 | low_id = get_unaligned_le32(mac); | ||
825 | high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID; | ||
826 | } | ||
827 | |||
828 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | ||
829 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | ||
830 | |||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | /** | 643 | /** |
835 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | 644 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class |
836 | * | 645 | * |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 984ba92c7df3..4932bf2f35eb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1377,7 +1377,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1377 | 1377 | ||
1378 | /* protect against divide by 0 and loss of sign bits */ | 1378 | /* protect against divide by 0 and loss of sign bits */ |
1379 | if (i_coffd == 0 || q_coffd < 2) | 1379 | if (i_coffd == 0 || q_coffd < 2) |
1380 | return -1; | 1380 | return 0; |
1381 | 1381 | ||
1382 | i_coff = (-iq_corr) / i_coffd; | 1382 | i_coff = (-iq_corr) / i_coffd; |
1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 4186ff4c6e9c..84c717ded1c5 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -36,24 +36,58 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
36 | } | 36 | } |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Make sure cw is a power of 2 minus 1 and smaller than 1024 | ||
40 | */ | ||
41 | static u16 ath5k_cw_validate(u16 cw_req) | ||
42 | { | ||
43 | u32 cw = 1; | ||
44 | cw_req = min(cw_req, (u16)1023); | ||
45 | |||
46 | while (cw < cw_req) | ||
47 | cw = (cw << 1) | 1; | ||
48 | |||
49 | return cw; | ||
50 | } | ||
51 | |||
52 | /* | ||
39 | * Set properties for a transmit queue | 53 | * Set properties for a transmit queue |
40 | */ | 54 | */ |
41 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 55 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
42 | const struct ath5k_txq_info *queue_info) | 56 | const struct ath5k_txq_info *qinfo) |
43 | { | 57 | { |
58 | struct ath5k_txq_info *qi; | ||
59 | |||
44 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 60 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
45 | 61 | ||
46 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 62 | qi = &ah->ah_txq[queue]; |
63 | |||
64 | if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
47 | return -EIO; | 65 | return -EIO; |
48 | 66 | ||
49 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | 67 | /* copy and validate values */ |
68 | qi->tqi_type = qinfo->tqi_type; | ||
69 | qi->tqi_subtype = qinfo->tqi_subtype; | ||
70 | qi->tqi_flags = qinfo->tqi_flags; | ||
71 | /* | ||
72 | * According to the docs: Although the AIFS field is 8 bit wide, | ||
73 | * the maximum supported value is 0xFC. Setting it higher than that | ||
74 | * will cause the DCU to hang. | ||
75 | */ | ||
76 | qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC); | ||
77 | qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min); | ||
78 | qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max); | ||
79 | qi->tqi_cbr_period = qinfo->tqi_cbr_period; | ||
80 | qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit; | ||
81 | qi->tqi_burst_time = qinfo->tqi_burst_time; | ||
82 | qi->tqi_ready_time = qinfo->tqi_ready_time; | ||
50 | 83 | ||
51 | /*XXX: Is this supported on 5210 ?*/ | 84 | /*XXX: Is this supported on 5210 ?*/ |
52 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | 85 | /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/ |
53 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | 86 | if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA && |
54 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | 87 | ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || |
55 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | 88 | (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || |
56 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | 89 | qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) |
90 | qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
57 | 91 | ||
58 | return 0; | 92 | return 0; |
59 | } | 93 | } |
@@ -186,7 +220,7 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
186 | */ | 220 | */ |
187 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 221 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) |
188 | { | 222 | { |
189 | u32 cw_min, cw_max, retry_lg, retry_sh; | 223 | u32 retry_lg, retry_sh; |
190 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 224 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
191 | 225 | ||
192 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 226 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
@@ -217,14 +251,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
217 | /* Set IFS0 */ | 251 | /* Set IFS0 */ |
218 | if (ah->ah_turbo) { | 252 | if (ah->ah_turbo) { |
219 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | 253 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + |
220 | (ah->ah_aifs + tq->tqi_aifs) * | 254 | tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) << |
221 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
222 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | 255 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, |
223 | AR5K_IFS0); | 256 | AR5K_IFS0); |
224 | } else { | 257 | } else { |
225 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | 258 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + |
226 | (ah->ah_aifs + tq->tqi_aifs) * | 259 | tq->tqi_aifs * AR5K_INIT_SLOT_TIME) << |
227 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | 260 | AR5K_IFS0_DIFS_S) | |
228 | AR5K_INIT_SIFS, AR5K_IFS0); | 261 | AR5K_INIT_SIFS, AR5K_IFS0); |
229 | } | 262 | } |
230 | 263 | ||
@@ -248,35 +281,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
248 | } | 281 | } |
249 | 282 | ||
250 | /* | 283 | /* |
251 | * Calculate cwmin/max by channel mode | ||
252 | */ | ||
253 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
254 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | ||
255 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
256 | /*XR is only supported on 5212*/ | ||
257 | if (IS_CHAN_XR(ah->ah_current_channel) && | ||
258 | ah->ah_version == AR5K_AR5212) { | ||
259 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
260 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
261 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
262 | /*B mode is not supported on 5210*/ | ||
263 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
264 | ah->ah_version != AR5K_AR5210) { | ||
265 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
266 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
267 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
268 | } | ||
269 | |||
270 | cw_min = 1; | ||
271 | while (cw_min < ah->ah_cw_min) | ||
272 | cw_min = (cw_min << 1) | 1; | ||
273 | |||
274 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
275 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
276 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
277 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
278 | |||
279 | /* | ||
280 | * Calculate and set retry limits | 284 | * Calculate and set retry limits |
281 | */ | 285 | */ |
282 | if (ah->ah_software_retry) { | 286 | if (ah->ah_software_retry) { |
@@ -292,7 +296,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
292 | /*No QCU/DCU [5210]*/ | 296 | /*No QCU/DCU [5210]*/ |
293 | if (ah->ah_version == AR5K_AR5210) { | 297 | if (ah->ah_version == AR5K_AR5210) { |
294 | ath5k_hw_reg_write(ah, | 298 | ath5k_hw_reg_write(ah, |
295 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | 299 | (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) |
296 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | 300 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, |
297 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | 301 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) |
298 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | 302 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, |
@@ -314,14 +318,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
314 | /*===Rest is also for QCU/DCU only [5211+]===*/ | 318 | /*===Rest is also for QCU/DCU only [5211+]===*/ |
315 | 319 | ||
316 | /* | 320 | /* |
317 | * Set initial content window (cw_min/cw_max) | 321 | * Set contention window (cw_min/cw_max) |
318 | * and arbitrated interframe space (aifs)... | 322 | * and arbitrated interframe space (aifs)... |
319 | */ | 323 | */ |
320 | ath5k_hw_reg_write(ah, | 324 | ath5k_hw_reg_write(ah, |
321 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | 325 | AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | |
322 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | 326 | AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | |
323 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | 327 | AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), |
324 | AR5K_DCU_LCL_IFS_AIFS), | ||
325 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | 328 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); |
326 | 329 | ||
327 | /* | 330 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 05ef587ad2b4..67d63081705a 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -1822,50 +1822,8 @@ | |||
1822 | 1822 | ||
1823 | /*===5212 end===*/ | 1823 | /*===5212 end===*/ |
1824 | 1824 | ||
1825 | /* | ||
1826 | * Key table (WEP) register | ||
1827 | */ | ||
1828 | #define AR5K_KEYTABLE_0_5210 0x9000 | ||
1829 | #define AR5K_KEYTABLE_0_5211 0x8800 | ||
1830 | #define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) | ||
1831 | #define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) | ||
1832 | #define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ | ||
1833 | AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) | ||
1834 | #define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) | ||
1835 | #define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) | ||
1836 | #define AR5K_KEYTABLE_TYPE_40 0x00000000 | ||
1837 | #define AR5K_KEYTABLE_TYPE_104 0x00000001 | ||
1838 | #define AR5K_KEYTABLE_TYPE_128 0x00000003 | ||
1839 | #define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ | ||
1840 | #define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ | ||
1841 | #define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ | ||
1842 | #define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ | ||
1843 | #define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ | ||
1844 | #define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) | ||
1845 | #define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) | ||
1846 | #define AR5K_KEYTABLE_VALID 0x00008000 | ||
1847 | |||
1848 | /* If key type is TKIP and MIC is enabled | ||
1849 | * MIC key goes in offset entry + 64 */ | ||
1850 | #define AR5K_KEYTABLE_MIC_OFFSET 64 | ||
1851 | |||
1852 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit | ||
1853 | * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit | ||
1854 | * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit | ||
1855 | * | ||
1856 | * Some vendors have introduced bigger WEP keys to address | ||
1857 | * security vulnerabilities in WEP. This includes: | ||
1858 | * | ||
1859 | * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit | ||
1860 | * | ||
1861 | * We can expand this if we find ar5k Atheros cards with a larger | ||
1862 | * key table size. | ||
1863 | */ | ||
1864 | #define AR5K_KEYTABLE_SIZE_5210 64 | 1825 | #define AR5K_KEYTABLE_SIZE_5210 64 |
1865 | #define AR5K_KEYTABLE_SIZE_5211 128 | 1826 | #define AR5K_KEYTABLE_SIZE_5211 128 |
1866 | #define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ | ||
1867 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) | ||
1868 | |||
1869 | 1827 | ||
1870 | /*===PHY REGISTERS===*/ | 1828 | /*===PHY REGISTERS===*/ |
1871 | 1829 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 35f23bdc442f..ad57a6d23110 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -32,6 +32,14 @@ config ATH9K_DEBUGFS | |||
32 | 32 | ||
33 | Also required for changing debug message flags at run time. | 33 | Also required for changing debug message flags at run time. |
34 | 34 | ||
35 | config ATH9K_RATE_CONTROL | ||
36 | bool "Atheros ath9k rate control" | ||
37 | depends on ATH9K | ||
38 | default y | ||
39 | ---help--- | ||
40 | Say Y, if you want to use the ath9k specific rate control | ||
41 | module instead of minstrel_ht. | ||
42 | |||
35 | config ATH9K_HTC | 43 | config ATH9K_HTC |
36 | tristate "Atheros HTC based wireless cards support" | 44 | tristate "Atheros HTC based wireless cards support" |
37 | depends on USB && MAC80211 | 45 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4555e9983903..aca01621c205 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -5,8 +5,8 @@ ath9k-y += beacon.o \ | |||
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | virtual.o \ | 7 | virtual.o \ |
8 | rc.o | ||
9 | 8 | ||
9 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | ||
10 | ath9k-$(CONFIG_PCI) += pci.o | 10 | ath9k-$(CONFIG_PCI) += pci.o |
11 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o | 11 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cc648b6ae31c..0496f965314f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "hw-ops.h" | 19 | #include "hw-ops.h" |
19 | 20 | ||
@@ -48,7 +49,7 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = { | |||
48 | { 7, 8, 0 } /* lvl 9 */ | 49 | { 7, 8, 0 } /* lvl 9 */ |
49 | }; | 50 | }; |
50 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | 51 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ |
51 | (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) | 52 | ARRAY_SIZE(ofdm_level_table) |
52 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ | 53 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ |
53 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) | 54 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) |
54 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ | 55 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ |
@@ -94,7 +95,7 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
94 | }; | 95 | }; |
95 | 96 | ||
96 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | 97 | #define ATH9K_ANI_CCK_NUM_LEVEL \ |
97 | (sizeof(cck_level_table)/sizeof(cck_level_table[0])) | 98 | ARRAY_SIZE(cck_level_table) |
98 | #define ATH9K_ANI_CCK_MAX_LEVEL \ | 99 | #define ATH9K_ANI_CCK_MAX_LEVEL \ |
99 | (ATH9K_ANI_CCK_NUM_LEVEL-1) | 100 | (ATH9K_ANI_CCK_NUM_LEVEL-1) |
100 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ | 101 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 303c63da5ea3..94392daebaa0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -580,3 +580,53 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
580 | else | 580 | else |
581 | ath9k_hw_attach_ani_ops_old(ah); | 581 | ath9k_hw_attach_ani_ops_old(ah); |
582 | } | 582 | } |
583 | |||
584 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | ||
585 | { | ||
586 | u32 modesIndex; | ||
587 | int i; | ||
588 | |||
589 | switch (chan->chanmode) { | ||
590 | case CHANNEL_A: | ||
591 | case CHANNEL_A_HT20: | ||
592 | modesIndex = 1; | ||
593 | break; | ||
594 | case CHANNEL_A_HT40PLUS: | ||
595 | case CHANNEL_A_HT40MINUS: | ||
596 | modesIndex = 2; | ||
597 | break; | ||
598 | case CHANNEL_G: | ||
599 | case CHANNEL_G_HT20: | ||
600 | case CHANNEL_B: | ||
601 | modesIndex = 4; | ||
602 | break; | ||
603 | case CHANNEL_G_HT40PLUS: | ||
604 | case CHANNEL_G_HT40MINUS: | ||
605 | modesIndex = 3; | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | return; | ||
610 | } | ||
611 | |||
612 | ENABLE_REGWRITE_BUFFER(ah); | ||
613 | |||
614 | for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { | ||
615 | u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); | ||
616 | u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); | ||
617 | u32 val_orig; | ||
618 | |||
619 | if (reg == AR_PHY_CCK_DETECT) { | ||
620 | val_orig = REG_READ(ah, reg); | ||
621 | val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
622 | val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
623 | |||
624 | REG_WRITE(ah, reg, val|val_orig); | ||
625 | } else | ||
626 | REG_WRITE(ah, reg, val); | ||
627 | } | ||
628 | |||
629 | REGWRITE_BUFFER_FLUSH(ah); | ||
630 | DISABLE_REGWRITE_BUFFER(ah); | ||
631 | |||
632 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index adbf031fbc5a..cd56c8692705 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -530,3 +530,38 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
530 | 530 | ||
531 | ar9002_hw_set_nf_limits(ah); | 531 | ar9002_hw_set_nf_limits(ah); |
532 | } | 532 | } |
533 | |||
534 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
535 | struct ath_hw_antcomb_conf *antconf) | ||
536 | { | ||
537 | u32 regval; | ||
538 | |||
539 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
540 | antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >> | ||
541 | AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S; | ||
542 | antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >> | ||
543 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; | ||
544 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> | ||
545 | AR_PHY_9285_FAST_DIV_BIAS_S; | ||
546 | } | ||
547 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get); | ||
548 | |||
549 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
550 | struct ath_hw_antcomb_conf *antconf) | ||
551 | { | ||
552 | u32 regval; | ||
553 | |||
554 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
555 | regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | | ||
556 | AR_PHY_9285_ANT_DIV_ALT_LNACONF | | ||
557 | AR_PHY_9285_FAST_DIV_BIAS); | ||
558 | regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S) | ||
559 | & AR_PHY_9285_ANT_DIV_MAIN_LNACONF); | ||
560 | regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S) | ||
561 | & AR_PHY_9285_ANT_DIV_ALT_LNACONF); | ||
562 | regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S) | ||
563 | & AR_PHY_9285_FAST_DIV_BIAS); | ||
564 | |||
565 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | ||
566 | } | ||
567 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index c5151a4dd10b..37663dbbcf57 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -302,6 +302,8 @@ | |||
302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | 302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 |
303 | 303 | ||
304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | 304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac |
305 | #define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00 | ||
306 | #define AR_PHY_9285_FAST_DIV_BIAS_S 9 | ||
305 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | 307 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 |
306 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 | 308 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 |
307 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 | 309 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 057fb69ddf7f..c4182359bee4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -968,7 +968,7 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) | |||
968 | } | 968 | } |
969 | 969 | ||
970 | static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, | 970 | static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, |
971 | enum ieee80211_band freq_band) | 971 | enum ath9k_hal_freq_band freq_band) |
972 | { | 972 | { |
973 | return 1; | 973 | return 1; |
974 | } | 974 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index a462da23e87e..3b424ca1ba84 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -616,7 +616,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
616 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | 616 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; |
617 | } else if (rxsp->status11 & AR_MichaelErr) { | 617 | } else if (rxsp->status11 & AR_MichaelErr) { |
618 | rxs->rs_status |= ATH9K_RXERR_MIC; | 618 | rxs->rs_status |= ATH9K_RXERR_MIC; |
619 | } | 619 | } else if (rxsp->status11 & AR_KeyMiss) |
620 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
620 | } | 621 | } |
621 | 622 | ||
622 | return 0; | 623 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f0197a6046ab..9f8e542ef47e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -254,7 +254,7 @@ struct ath_atx_tid { | |||
254 | struct list_head buf_q; | 254 | struct list_head buf_q; |
255 | struct ath_node *an; | 255 | struct ath_node *an; |
256 | struct ath_atx_ac *ac; | 256 | struct ath_atx_ac *ac; |
257 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; | 257 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
258 | u16 seq_start; | 258 | u16 seq_start; |
259 | u16 seq_next; | 259 | u16 seq_next; |
260 | u16 baw_size; | 260 | u16 baw_size; |
@@ -345,9 +345,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
345 | void ath_tx_tasklet(struct ath_softc *sc); | 345 | void ath_tx_tasklet(struct ath_softc *sc); |
346 | void ath_tx_edma_tasklet(struct ath_softc *sc); | 346 | void ath_tx_edma_tasklet(struct ath_softc *sc); |
347 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); | 347 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); |
348 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); | 348 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
349 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 349 | u16 tid, u16 *ssn); |
350 | u16 tid, u16 *ssn); | ||
351 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 350 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
352 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 351 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
353 | void ath9k_enable_ps(struct ath_softc *sc); | 352 | void ath9k_enable_ps(struct ath_softc *sc); |
@@ -481,6 +480,60 @@ struct ath_led { | |||
481 | void ath_init_leds(struct ath_softc *sc); | 480 | void ath_init_leds(struct ath_softc *sc); |
482 | void ath_deinit_leds(struct ath_softc *sc); | 481 | void ath_deinit_leds(struct ath_softc *sc); |
483 | 482 | ||
483 | /* Antenna diversity/combining */ | ||
484 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | ||
485 | #define ATH_ANT_RX_MAIN_SHIFT 2 | ||
486 | #define ATH_ANT_RX_MASK 0x3 | ||
487 | |||
488 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50 | ||
489 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100 | ||
490 | #define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200 | ||
491 | #define ATH_ANT_DIV_COMB_INIT_COUNT 95 | ||
492 | #define ATH_ANT_DIV_COMB_MAX_COUNT 100 | ||
493 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 | ||
494 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 | ||
495 | |||
496 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3 | ||
497 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | ||
498 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | ||
499 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | ||
500 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 | ||
501 | |||
502 | enum ath9k_ant_div_comb_lna_conf { | ||
503 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, | ||
504 | ATH_ANT_DIV_COMB_LNA2, | ||
505 | ATH_ANT_DIV_COMB_LNA1, | ||
506 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, | ||
507 | }; | ||
508 | |||
509 | struct ath_ant_comb { | ||
510 | u16 count; | ||
511 | u16 total_pkt_count; | ||
512 | bool scan; | ||
513 | bool scan_not_start; | ||
514 | int main_total_rssi; | ||
515 | int alt_total_rssi; | ||
516 | int alt_recv_cnt; | ||
517 | int main_recv_cnt; | ||
518 | int rssi_lna1; | ||
519 | int rssi_lna2; | ||
520 | int rssi_add; | ||
521 | int rssi_sub; | ||
522 | int rssi_first; | ||
523 | int rssi_second; | ||
524 | int rssi_third; | ||
525 | bool alt_good; | ||
526 | int quick_scan_cnt; | ||
527 | int main_conf; | ||
528 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; | ||
529 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; | ||
530 | int first_bias; | ||
531 | int second_bias; | ||
532 | bool first_ratio; | ||
533 | bool second_ratio; | ||
534 | unsigned long scan_start_time; | ||
535 | }; | ||
536 | |||
484 | /********************/ | 537 | /********************/ |
485 | /* Main driver core */ | 538 | /* Main driver core */ |
486 | /********************/ | 539 | /********************/ |
@@ -509,7 +562,6 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
509 | #define SC_OP_RXFLUSH BIT(7) | 562 | #define SC_OP_RXFLUSH BIT(7) |
510 | #define SC_OP_LED_ASSOCIATED BIT(8) | 563 | #define SC_OP_LED_ASSOCIATED BIT(8) |
511 | #define SC_OP_LED_ON BIT(9) | 564 | #define SC_OP_LED_ON BIT(9) |
512 | #define SC_OP_SCANNING BIT(10) | ||
513 | #define SC_OP_TSF_RESET BIT(11) | 565 | #define SC_OP_TSF_RESET BIT(11) |
514 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) | 566 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
515 | #define SC_OP_BT_SCAN BIT(13) | 567 | #define SC_OP_BT_SCAN BIT(13) |
@@ -597,6 +649,8 @@ struct ath_softc { | |||
597 | struct ath_btcoex btcoex; | 649 | struct ath_btcoex btcoex; |
598 | 650 | ||
599 | struct ath_descdma txsdma; | 651 | struct ath_descdma txsdma; |
652 | |||
653 | struct ath_ant_comb ant_comb; | ||
600 | }; | 654 | }; |
601 | 655 | ||
602 | struct ath_wiphy { | 656 | struct ath_wiphy { |
@@ -663,7 +717,7 @@ static inline void ath_ahb_exit(void) {}; | |||
663 | void ath9k_ps_wakeup(struct ath_softc *sc); | 717 | void ath9k_ps_wakeup(struct ath_softc *sc); |
664 | void ath9k_ps_restore(struct ath_softc *sc); | 718 | void ath9k_ps_restore(struct ath_softc *sc); |
665 | 719 | ||
666 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw); | 720 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
667 | int ath9k_wiphy_add(struct ath_softc *sc); | 721 | int ath9k_wiphy_add(struct ath_softc *sc); |
668 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | 722 | int ath9k_wiphy_del(struct ath_wiphy *aphy); |
669 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); | 723 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 2dab64bb23a8..f43a2d98421c 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -148,276 +148,6 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | |||
148 | } | 148 | } |
149 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | 149 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); |
150 | 150 | ||
151 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
152 | struct ath9k_keyval *hk, const u8 *addr, | ||
153 | bool authenticator) | ||
154 | { | ||
155 | struct ath_hw *ah = common->ah; | ||
156 | const u8 *key_rxmic; | ||
157 | const u8 *key_txmic; | ||
158 | |||
159 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
160 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
161 | |||
162 | if (addr == NULL) { | ||
163 | /* | ||
164 | * Group key installation - only two key cache entries are used | ||
165 | * regardless of splitmic capability since group key is only | ||
166 | * used either for TX or RX. | ||
167 | */ | ||
168 | if (authenticator) { | ||
169 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
170 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
171 | } else { | ||
172 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
173 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
174 | } | ||
175 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
176 | } | ||
177 | if (!common->splitmic) { | ||
178 | /* TX and RX keys share the same key cache entry. */ | ||
179 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
180 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
181 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
182 | } | ||
183 | |||
184 | /* Separate key cache entries for TX and RX */ | ||
185 | |||
186 | /* TX key goes at first index, RX key at +32. */ | ||
187 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
188 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
189 | /* TX MIC entry failed. No need to proceed further */ | ||
190 | ath_print(common, ATH_DBG_FATAL, | ||
191 | "Setting TX MIC Key Failed\n"); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
196 | /* XXX delete tx key on failure? */ | ||
197 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
198 | } | ||
199 | |||
200 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
201 | { | ||
202 | int i; | ||
203 | |||
204 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
205 | if (test_bit(i, common->keymap) || | ||
206 | test_bit(i + 64, common->keymap)) | ||
207 | continue; /* At least one part of TKIP key allocated */ | ||
208 | if (common->splitmic && | ||
209 | (test_bit(i + 32, common->keymap) || | ||
210 | test_bit(i + 64 + 32, common->keymap))) | ||
211 | continue; /* At least one part of TKIP key allocated */ | ||
212 | |||
213 | /* Found a free slot for a TKIP key */ | ||
214 | return i; | ||
215 | } | ||
216 | return -1; | ||
217 | } | ||
218 | |||
219 | static int ath_reserve_key_cache_slot(struct ath_common *common, | ||
220 | u32 cipher) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | if (cipher == WLAN_CIPHER_SUITE_TKIP) | ||
225 | return ath_reserve_key_cache_slot_tkip(common); | ||
226 | |||
227 | /* First, try to find slots that would not be available for TKIP. */ | ||
228 | if (common->splitmic) { | ||
229 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
230 | if (!test_bit(i, common->keymap) && | ||
231 | (test_bit(i + 32, common->keymap) || | ||
232 | test_bit(i + 64, common->keymap) || | ||
233 | test_bit(i + 64 + 32, common->keymap))) | ||
234 | return i; | ||
235 | if (!test_bit(i + 32, common->keymap) && | ||
236 | (test_bit(i, common->keymap) || | ||
237 | test_bit(i + 64, common->keymap) || | ||
238 | test_bit(i + 64 + 32, common->keymap))) | ||
239 | return i + 32; | ||
240 | if (!test_bit(i + 64, common->keymap) && | ||
241 | (test_bit(i , common->keymap) || | ||
242 | test_bit(i + 32, common->keymap) || | ||
243 | test_bit(i + 64 + 32, common->keymap))) | ||
244 | return i + 64; | ||
245 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
246 | (test_bit(i, common->keymap) || | ||
247 | test_bit(i + 32, common->keymap) || | ||
248 | test_bit(i + 64, common->keymap))) | ||
249 | return i + 64 + 32; | ||
250 | } | ||
251 | } else { | ||
252 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
253 | if (!test_bit(i, common->keymap) && | ||
254 | test_bit(i + 64, common->keymap)) | ||
255 | return i; | ||
256 | if (test_bit(i, common->keymap) && | ||
257 | !test_bit(i + 64, common->keymap)) | ||
258 | return i + 64; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* No partially used TKIP slots, pick any available slot */ | ||
263 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
264 | /* Do not allow slots that could be needed for TKIP group keys | ||
265 | * to be used. This limitation could be removed if we know that | ||
266 | * TKIP will not be used. */ | ||
267 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
268 | continue; | ||
269 | if (common->splitmic) { | ||
270 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
271 | continue; | ||
272 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
273 | continue; | ||
274 | } | ||
275 | |||
276 | if (!test_bit(i, common->keymap)) | ||
277 | return i; /* Found a free slot for a key */ | ||
278 | } | ||
279 | |||
280 | /* No free slot found */ | ||
281 | return -1; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Configure encryption in the HW. | ||
286 | */ | ||
287 | int ath9k_cmn_key_config(struct ath_common *common, | ||
288 | struct ieee80211_vif *vif, | ||
289 | struct ieee80211_sta *sta, | ||
290 | struct ieee80211_key_conf *key) | ||
291 | { | ||
292 | struct ath_hw *ah = common->ah; | ||
293 | struct ath9k_keyval hk; | ||
294 | const u8 *mac = NULL; | ||
295 | u8 gmac[ETH_ALEN]; | ||
296 | int ret = 0; | ||
297 | int idx; | ||
298 | |||
299 | memset(&hk, 0, sizeof(hk)); | ||
300 | |||
301 | switch (key->cipher) { | ||
302 | case WLAN_CIPHER_SUITE_WEP40: | ||
303 | case WLAN_CIPHER_SUITE_WEP104: | ||
304 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
305 | break; | ||
306 | case WLAN_CIPHER_SUITE_TKIP: | ||
307 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
308 | break; | ||
309 | case WLAN_CIPHER_SUITE_CCMP: | ||
310 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
311 | break; | ||
312 | default: | ||
313 | return -EOPNOTSUPP; | ||
314 | } | ||
315 | |||
316 | hk.kv_len = key->keylen; | ||
317 | memcpy(hk.kv_val, key->key, key->keylen); | ||
318 | |||
319 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
320 | switch (vif->type) { | ||
321 | case NL80211_IFTYPE_AP: | ||
322 | memcpy(gmac, vif->addr, ETH_ALEN); | ||
323 | gmac[0] |= 0x01; | ||
324 | mac = gmac; | ||
325 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
326 | break; | ||
327 | case NL80211_IFTYPE_ADHOC: | ||
328 | if (!sta) { | ||
329 | idx = key->keyidx; | ||
330 | break; | ||
331 | } | ||
332 | memcpy(gmac, sta->addr, ETH_ALEN); | ||
333 | gmac[0] |= 0x01; | ||
334 | mac = gmac; | ||
335 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
336 | break; | ||
337 | default: | ||
338 | idx = key->keyidx; | ||
339 | break; | ||
340 | } | ||
341 | } else if (key->keyidx) { | ||
342 | if (WARN_ON(!sta)) | ||
343 | return -EOPNOTSUPP; | ||
344 | mac = sta->addr; | ||
345 | |||
346 | if (vif->type != NL80211_IFTYPE_AP) { | ||
347 | /* Only keyidx 0 should be used with unicast key, but | ||
348 | * allow this for client mode for now. */ | ||
349 | idx = key->keyidx; | ||
350 | } else | ||
351 | return -EIO; | ||
352 | } else { | ||
353 | if (WARN_ON(!sta)) | ||
354 | return -EOPNOTSUPP; | ||
355 | mac = sta->addr; | ||
356 | |||
357 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
358 | } | ||
359 | |||
360 | if (idx < 0) | ||
361 | return -ENOSPC; /* no free key cache entries */ | ||
362 | |||
363 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
364 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
365 | vif->type == NL80211_IFTYPE_AP); | ||
366 | else | ||
367 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
368 | |||
369 | if (!ret) | ||
370 | return -EIO; | ||
371 | |||
372 | set_bit(idx, common->keymap); | ||
373 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
374 | set_bit(idx + 64, common->keymap); | ||
375 | set_bit(idx, common->tkip_keymap); | ||
376 | set_bit(idx + 64, common->tkip_keymap); | ||
377 | if (common->splitmic) { | ||
378 | set_bit(idx + 32, common->keymap); | ||
379 | set_bit(idx + 64 + 32, common->keymap); | ||
380 | set_bit(idx + 32, common->tkip_keymap); | ||
381 | set_bit(idx + 64 + 32, common->tkip_keymap); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | return idx; | ||
386 | } | ||
387 | EXPORT_SYMBOL(ath9k_cmn_key_config); | ||
388 | |||
389 | /* | ||
390 | * Delete Key. | ||
391 | */ | ||
392 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
393 | struct ieee80211_key_conf *key) | ||
394 | { | ||
395 | struct ath_hw *ah = common->ah; | ||
396 | |||
397 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
398 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
399 | return; | ||
400 | |||
401 | clear_bit(key->hw_key_idx, common->keymap); | ||
402 | if (key->cipher != WLAN_CIPHER_SUITE_TKIP) | ||
403 | return; | ||
404 | |||
405 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
406 | |||
407 | clear_bit(key->hw_key_idx, common->tkip_keymap); | ||
408 | clear_bit(key->hw_key_idx + 64, common->tkip_keymap); | ||
409 | |||
410 | if (common->splitmic) { | ||
411 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
412 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
413 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
414 | |||
415 | clear_bit(key->hw_key_idx + 32, common->tkip_keymap); | ||
416 | clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); | ||
417 | } | ||
418 | } | ||
419 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | ||
420 | |||
421 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | 151 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
422 | { | 152 | { |
423 | int streams = 0; | 153 | int streams = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 4aa4e7dbe4d2..fea3b3315391 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -66,12 +66,6 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | |||
66 | struct ath9k_channel *ichan); | 66 | struct ath9k_channel *ichan); |
67 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 67 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, |
68 | struct ath_hw *ah); | 68 | struct ath_hw *ah); |
69 | int ath9k_cmn_key_config(struct ath_common *common, | ||
70 | struct ieee80211_vif *vif, | ||
71 | struct ieee80211_sta *sta, | ||
72 | struct ieee80211_key_conf *key); | ||
73 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
74 | struct ieee80211_key_conf *key); | ||
75 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 69 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
76 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | 70 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, |
77 | enum ath_stomp_type stomp_type); | 71 | enum ath_stomp_type stomp_type); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 54aae931424e..d65a896a421d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -492,12 +492,55 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
492 | unsigned int len = 0; | 492 | unsigned int len = 0; |
493 | int i; | 493 | int i; |
494 | u8 addr[ETH_ALEN]; | 494 | u8 addr[ETH_ALEN]; |
495 | u32 tmp; | ||
495 | 496 | ||
496 | len += snprintf(buf + len, sizeof(buf) - len, | 497 | len += snprintf(buf + len, sizeof(buf) - len, |
497 | "primary: %s (%s chan=%d ht=%d)\n", | 498 | "primary: %s (%s chan=%d ht=%d)\n", |
498 | wiphy_name(sc->pri_wiphy->hw->wiphy), | 499 | wiphy_name(sc->pri_wiphy->hw->wiphy), |
499 | ath_wiphy_state_str(sc->pri_wiphy->state), | 500 | ath_wiphy_state_str(sc->pri_wiphy->state), |
500 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); | 501 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); |
502 | |||
503 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | ||
504 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | ||
505 | len += snprintf(buf + len, sizeof(buf) - len, | ||
506 | "addr: %pM\n", addr); | ||
507 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); | ||
508 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | ||
509 | len += snprintf(buf + len, sizeof(buf) - len, | ||
510 | "addrmask: %pM\n", addr); | ||
511 | tmp = ath9k_hw_getrxfilter(sc->sc_ah); | ||
512 | len += snprintf(buf + len, sizeof(buf) - len, | ||
513 | "rfilt: 0x%x", tmp); | ||
514 | if (tmp & ATH9K_RX_FILTER_UCAST) | ||
515 | len += snprintf(buf + len, sizeof(buf) - len, " UCAST"); | ||
516 | if (tmp & ATH9K_RX_FILTER_MCAST) | ||
517 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST"); | ||
518 | if (tmp & ATH9K_RX_FILTER_BCAST) | ||
519 | len += snprintf(buf + len, sizeof(buf) - len, " BCAST"); | ||
520 | if (tmp & ATH9K_RX_FILTER_CONTROL) | ||
521 | len += snprintf(buf + len, sizeof(buf) - len, " CONTROL"); | ||
522 | if (tmp & ATH9K_RX_FILTER_BEACON) | ||
523 | len += snprintf(buf + len, sizeof(buf) - len, " BEACON"); | ||
524 | if (tmp & ATH9K_RX_FILTER_PROM) | ||
525 | len += snprintf(buf + len, sizeof(buf) - len, " PROM"); | ||
526 | if (tmp & ATH9K_RX_FILTER_PROBEREQ) | ||
527 | len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); | ||
528 | if (tmp & ATH9K_RX_FILTER_PHYERR) | ||
529 | len += snprintf(buf + len, sizeof(buf) - len, " PHYERR"); | ||
530 | if (tmp & ATH9K_RX_FILTER_MYBEACON) | ||
531 | len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON"); | ||
532 | if (tmp & ATH9K_RX_FILTER_COMP_BAR) | ||
533 | len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR"); | ||
534 | if (tmp & ATH9K_RX_FILTER_PSPOLL) | ||
535 | len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL"); | ||
536 | if (tmp & ATH9K_RX_FILTER_PHYRADAR) | ||
537 | len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR"); | ||
538 | if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL) | ||
539 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n"); | ||
540 | else | ||
541 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
542 | |||
543 | /* Put variable-length stuff down here, and check for overflows. */ | ||
501 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 544 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
502 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 545 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
503 | if (aphy == NULL) | 546 | if (aphy == NULL) |
@@ -508,16 +551,6 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
508 | ath_wiphy_state_str(aphy->state), | 551 | ath_wiphy_state_str(aphy->state), |
509 | aphy->chan_idx, aphy->chan_is_ht); | 552 | aphy->chan_idx, aphy->chan_is_ht); |
510 | } | 553 | } |
511 | |||
512 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | ||
513 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | ||
514 | len += snprintf(buf + len, sizeof(buf) - len, | ||
515 | "addr: %pM\n", addr); | ||
516 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); | ||
517 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | ||
518 | len += snprintf(buf + len, sizeof(buf) - len, | ||
519 | "addrmask: %pM\n", addr); | ||
520 | |||
521 | if (len > sizeof(buf)) | 554 | if (len > sizeof(buf)) |
522 | len = sizeof(buf); | 555 | len = sizeof(buf); |
523 | 556 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 0b09db0f8e7d..3030564a0f21 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -266,6 +266,8 @@ enum eeprom_param { | |||
266 | EEP_INTERNAL_REGULATOR, | 266 | EEP_INTERNAL_REGULATOR, |
267 | EEP_SWREG, | 267 | EEP_SWREG, |
268 | EEP_PAPRD, | 268 | EEP_PAPRD, |
269 | EEP_MODAL_VER, | ||
270 | EEP_ANT_DIV_CTL1, | ||
269 | }; | 271 | }; |
270 | 272 | ||
271 | enum ar5416_rates { | 273 | enum ar5416_rates { |
@@ -670,7 +672,8 @@ struct eeprom_ops { | |||
670 | bool (*fill_eeprom)(struct ath_hw *hw); | 672 | bool (*fill_eeprom)(struct ath_hw *hw); |
671 | int (*get_eeprom_ver)(struct ath_hw *hw); | 673 | int (*get_eeprom_ver)(struct ath_hw *hw); |
672 | int (*get_eeprom_rev)(struct ath_hw *hw); | 674 | int (*get_eeprom_rev)(struct ath_hw *hw); |
673 | u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); | 675 | u8 (*get_num_ant_config)(struct ath_hw *hw, |
676 | enum ath9k_hal_freq_band band); | ||
674 | u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, | 677 | u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, |
675 | struct ath9k_channel *chan); | 678 | struct ath9k_channel *chan); |
676 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); | 679 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 9cccd12e8f21..ead8b0dd3b53 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -213,6 +213,10 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
213 | return 0; | 213 | return 0; |
214 | case EEP_PWR_TABLE_OFFSET: | 214 | case EEP_PWR_TABLE_OFFSET: |
215 | return AR5416_PWR_TABLE_OFFSET_DB; | 215 | return AR5416_PWR_TABLE_OFFSET_DB; |
216 | case EEP_MODAL_VER: | ||
217 | return pModal->version; | ||
218 | case EEP_ANT_DIV_CTL1: | ||
219 | return pModal->antdiv_ctl1; | ||
216 | default: | 220 | default: |
217 | return 0; | 221 | return 0; |
218 | } | 222 | } |
@@ -1157,7 +1161,7 @@ static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | |||
1157 | } | 1161 | } |
1158 | 1162 | ||
1159 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | 1163 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, |
1160 | enum ieee80211_band freq_band) | 1164 | enum ath9k_hal_freq_band freq_band) |
1161 | { | 1165 | { |
1162 | return 1; | 1166 | return 1; |
1163 | } | 1167 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index dff2da777312..e6186515d05b 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -1126,7 +1126,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, | 1128 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, |
1129 | enum ieee80211_band freq_band) | 1129 | enum ath9k_hal_freq_band freq_band) |
1130 | { | 1130 | { |
1131 | return 1; | 1131 | return 1; |
1132 | } | 1132 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index afa2b73ddbdd..23f480d4c770 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -1418,11 +1418,11 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | 1420 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, |
1421 | enum ieee80211_band freq_band) | 1421 | enum ath9k_hal_freq_band freq_band) |
1422 | { | 1422 | { |
1423 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 1423 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
1424 | struct modal_eep_header *pModal = | 1424 | struct modal_eep_header *pModal = |
1425 | &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); | 1425 | &(eep->modalHeader[freq_band]); |
1426 | struct base_eep_header *pBase = &eep->baseEepHeader; | 1426 | struct base_eep_header *pBase = &eep->baseEepHeader; |
1427 | u8 num_ant_config; | 1427 | u8 num_ant_config; |
1428 | 1428 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 495f18950ac9..728d904c74d7 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -92,10 +92,10 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
92 | cmd->skb = skb; | 92 | cmd->skb = skb; |
93 | cmd->hif_dev = hif_dev; | 93 | cmd->hif_dev = hif_dev; |
94 | 94 | ||
95 | usb_fill_int_urb(urb, hif_dev->udev, | 95 | usb_fill_bulk_urb(urb, hif_dev->udev, |
96 | usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), | 96 | usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE), |
97 | skb->data, skb->len, | 97 | skb->data, skb->len, |
98 | hif_usb_regout_cb, cmd, 1); | 98 | hif_usb_regout_cb, cmd); |
99 | 99 | ||
100 | usb_anchor_urb(urb, &hif_dev->regout_submitted); | 100 | usb_anchor_urb(urb, &hif_dev->regout_submitted); |
101 | ret = usb_submit_urb(urb, GFP_KERNEL); | 101 | ret = usb_submit_urb(urb, GFP_KERNEL); |
@@ -541,7 +541,8 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
541 | } | 541 | } |
542 | 542 | ||
543 | usb_fill_int_urb(urb, hif_dev->udev, | 543 | usb_fill_int_urb(urb, hif_dev->udev, |
544 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 544 | usb_rcvbulkpipe(hif_dev->udev, |
545 | USB_REG_IN_PIPE), | ||
545 | nskb->data, MAX_REG_IN_BUF_SIZE, | 546 | nskb->data, MAX_REG_IN_BUF_SIZE, |
546 | ath9k_hif_usb_reg_in_cb, nskb, 1); | 547 | ath9k_hif_usb_reg_in_cb, nskb, 1); |
547 | 548 | ||
@@ -720,7 +721,8 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | |||
720 | goto err; | 721 | goto err; |
721 | 722 | ||
722 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, | 723 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, |
723 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 724 | usb_rcvbulkpipe(hif_dev->udev, |
725 | USB_REG_IN_PIPE), | ||
724 | skb->data, MAX_REG_IN_BUF_SIZE, | 726 | skb->data, MAX_REG_IN_BUF_SIZE, |
725 | ath9k_hif_usb_reg_in_cb, skb, 1); | 727 | ath9k_hif_usb_reg_in_cb, skb, 1); |
726 | 728 | ||
@@ -822,7 +824,9 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
822 | 824 | ||
823 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | 825 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) |
824 | { | 826 | { |
825 | int ret; | 827 | int ret, idx; |
828 | struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; | ||
829 | struct usb_endpoint_descriptor *endp; | ||
826 | 830 | ||
827 | /* Request firmware */ | 831 | /* Request firmware */ |
828 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, | 832 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, |
@@ -850,6 +854,22 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | |||
850 | goto err_fw_download; | 854 | goto err_fw_download; |
851 | } | 855 | } |
852 | 856 | ||
857 | /* On downloading the firmware to the target, the USB descriptor of EP4 | ||
858 | * is 'patched' to change the type of the endpoint to Bulk. This will | ||
859 | * bring down CPU usage during the scan period. | ||
860 | */ | ||
861 | for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) { | ||
862 | endp = &alt->endpoint[idx].desc; | ||
863 | if (((endp->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) | ||
864 | == 0x04) && | ||
865 | ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
866 | == USB_ENDPOINT_XFER_INT)) { | ||
867 | endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK; | ||
868 | endp->bmAttributes |= USB_ENDPOINT_XFER_BULK; | ||
869 | endp->bInterval = 0; | ||
870 | } | ||
871 | } | ||
872 | |||
853 | return 0; | 873 | return 0; |
854 | 874 | ||
855 | err_fw_download: | 875 | err_fw_download: |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 695e2b088d10..33850c952314 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -566,7 +566,7 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | |||
566 | * reset the contents on initial power up. | 566 | * reset the contents on initial power up. |
567 | */ | 567 | */ |
568 | for (i = 0; i < common->keymax; i++) | 568 | for (i = 0; i < common->keymax; i++) |
569 | ath9k_hw_keyreset(priv->ah, (u16) i); | 569 | ath_hw_keyreset(common, (u16) i); |
570 | } | 570 | } |
571 | 571 | ||
572 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | 572 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) |
@@ -601,8 +601,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
601 | common->tx_chainmask = priv->ah->caps.tx_chainmask; | 601 | common->tx_chainmask = priv->ah->caps.tx_chainmask; |
602 | common->rx_chainmask = priv->ah->caps.rx_chainmask; | 602 | common->rx_chainmask = priv->ah->caps.rx_chainmask; |
603 | 603 | ||
604 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 604 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
605 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
606 | 605 | ||
607 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 606 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
608 | } | 607 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f4672073ac0a..5124d04b240b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -137,8 +137,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
137 | if (priv->op_flags & OP_FULL_RESET) | 137 | if (priv->op_flags & OP_FULL_RESET) |
138 | fastcc = false; | 138 | fastcc = false; |
139 | 139 | ||
140 | /* Fiddle around with fastcc later on, for now just use full reset */ | ||
141 | fastcc = false; | ||
142 | ath9k_htc_ps_wakeup(priv); | 140 | ath9k_htc_ps_wakeup(priv); |
143 | htc_stop(priv->htc); | 141 | htc_stop(priv->htc); |
144 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 142 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
@@ -146,9 +144,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
146 | WMI_CMD(WMI_STOP_RECV_CMDID); | 144 | WMI_CMD(WMI_STOP_RECV_CMDID); |
147 | 145 | ||
148 | ath_print(common, ATH_DBG_CONFIG, | 146 | ath_print(common, ATH_DBG_CONFIG, |
149 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", | 147 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", |
150 | priv->ah->curchan->channel, | 148 | priv->ah->curchan->channel, |
151 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | 149 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), |
150 | fastcc); | ||
152 | 151 | ||
153 | caldata = &priv->caldata[channel->hw_value]; | 152 | caldata = &priv->caldata[channel->hw_value]; |
154 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 153 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
@@ -1591,7 +1590,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1591 | 1590 | ||
1592 | switch (cmd) { | 1591 | switch (cmd) { |
1593 | case SET_KEY: | 1592 | case SET_KEY: |
1594 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1593 | ret = ath_key_config(common, vif, sta, key); |
1595 | if (ret >= 0) { | 1594 | if (ret >= 0) { |
1596 | key->hw_key_idx = ret; | 1595 | key->hw_key_idx = ret; |
1597 | /* push IV and Michael MIC generation to stack */ | 1596 | /* push IV and Michael MIC generation to stack */ |
@@ -1605,7 +1604,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1605 | } | 1604 | } |
1606 | break; | 1605 | break; |
1607 | case DISABLE_KEY: | 1606 | case DISABLE_KEY: |
1608 | ath9k_cmn_key_delete(common, key); | 1607 | ath_key_delete(common, key); |
1609 | break; | 1608 | break; |
1610 | default: | 1609 | default: |
1611 | ret = -EINVAL; | 1610 | ret = -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2a6e45a293a9..c99600aff76d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -415,8 +415,7 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | |||
415 | ath9k_hw_setrxfilter(ah, rfilt); | 415 | ath9k_hw_setrxfilter(ah, rfilt); |
416 | 416 | ||
417 | /* configure bssid mask */ | 417 | /* configure bssid mask */ |
418 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 418 | ath_hw_setbssidmask(common); |
419 | ath_hw_setbssidmask(common); | ||
420 | 419 | ||
421 | /* configure operational mode */ | 420 | /* configure operational mode */ |
422 | ath9k_hw_setopmode(ah); | 421 | ath9k_hw_setopmode(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3384ca164562..0b2ff98b6f33 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1258,11 +1258,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1258 | (chan->channel != ah->curchan->channel) && | 1258 | (chan->channel != ah->curchan->channel) && |
1259 | ((chan->channelFlags & CHANNEL_ALL) == | 1259 | ((chan->channelFlags & CHANNEL_ALL) == |
1260 | (ah->curchan->channelFlags & CHANNEL_ALL)) && | 1260 | (ah->curchan->channelFlags & CHANNEL_ALL)) && |
1261 | !AR_SREV_9280(ah)) { | 1261 | (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) { |
1262 | 1262 | ||
1263 | if (ath9k_hw_channel_change(ah, chan)) { | 1263 | if (ath9k_hw_channel_change(ah, chan)) { |
1264 | ath9k_hw_loadnf(ah, ah->curchan); | 1264 | ath9k_hw_loadnf(ah, ah->curchan); |
1265 | ath9k_hw_start_nfcal(ah, true); | 1265 | ath9k_hw_start_nfcal(ah, true); |
1266 | if (AR_SREV_9271(ah)) | ||
1267 | ar9002_hw_load_ani_reg(ah, chan); | ||
1266 | return 0; | 1268 | return 0; |
1267 | } | 1269 | } |
1268 | } | 1270 | } |
@@ -1474,283 +1476,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1474 | } | 1476 | } |
1475 | EXPORT_SYMBOL(ath9k_hw_reset); | 1477 | EXPORT_SYMBOL(ath9k_hw_reset); |
1476 | 1478 | ||
1477 | /************************/ | ||
1478 | /* Key Cache Management */ | ||
1479 | /************************/ | ||
1480 | |||
1481 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | ||
1482 | { | ||
1483 | u32 keyType; | ||
1484 | |||
1485 | if (entry >= ah->caps.keycache_size) { | ||
1486 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1487 | "keychache entry %u out of range\n", entry); | ||
1488 | return false; | ||
1489 | } | ||
1490 | |||
1491 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | ||
1492 | |||
1493 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | ||
1494 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
1495 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
1496 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
1497 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
1498 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
1499 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
1500 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
1501 | |||
1502 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1503 | u16 micentry = entry + 64; | ||
1504 | |||
1505 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
1506 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1507 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
1508 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1509 | |||
1510 | } | ||
1511 | |||
1512 | return true; | ||
1513 | } | ||
1514 | EXPORT_SYMBOL(ath9k_hw_keyreset); | ||
1515 | |||
1516 | static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | ||
1517 | { | ||
1518 | u32 macHi, macLo; | ||
1519 | u32 unicast_flag = AR_KEYTABLE_VALID; | ||
1520 | |||
1521 | if (entry >= ah->caps.keycache_size) { | ||
1522 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1523 | "keychache entry %u out of range\n", entry); | ||
1524 | return false; | ||
1525 | } | ||
1526 | |||
1527 | if (mac != NULL) { | ||
1528 | /* | ||
1529 | * AR_KEYTABLE_VALID indicates that the address is a unicast | ||
1530 | * address, which must match the transmitter address for | ||
1531 | * decrypting frames. | ||
1532 | * Not setting this bit allows the hardware to use the key | ||
1533 | * for multicast frame decryption. | ||
1534 | */ | ||
1535 | if (mac[0] & 0x01) | ||
1536 | unicast_flag = 0; | ||
1537 | |||
1538 | macHi = (mac[5] << 8) | mac[4]; | ||
1539 | macLo = (mac[3] << 24) | | ||
1540 | (mac[2] << 16) | | ||
1541 | (mac[1] << 8) | | ||
1542 | mac[0]; | ||
1543 | macLo >>= 1; | ||
1544 | macLo |= (macHi & 1) << 31; | ||
1545 | macHi >>= 1; | ||
1546 | } else { | ||
1547 | macLo = macHi = 0; | ||
1548 | } | ||
1549 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
1550 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); | ||
1551 | |||
1552 | return true; | ||
1553 | } | ||
1554 | |||
1555 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
1556 | const struct ath9k_keyval *k, | ||
1557 | const u8 *mac) | ||
1558 | { | ||
1559 | const struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1560 | struct ath_common *common = ath9k_hw_common(ah); | ||
1561 | u32 key0, key1, key2, key3, key4; | ||
1562 | u32 keyType; | ||
1563 | |||
1564 | if (entry >= pCap->keycache_size) { | ||
1565 | ath_print(common, ATH_DBG_FATAL, | ||
1566 | "keycache entry %u out of range\n", entry); | ||
1567 | return false; | ||
1568 | } | ||
1569 | |||
1570 | switch (k->kv_type) { | ||
1571 | case ATH9K_CIPHER_AES_OCB: | ||
1572 | keyType = AR_KEYTABLE_TYPE_AES; | ||
1573 | break; | ||
1574 | case ATH9K_CIPHER_AES_CCM: | ||
1575 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { | ||
1576 | ath_print(common, ATH_DBG_ANY, | ||
1577 | "AES-CCM not supported by mac rev 0x%x\n", | ||
1578 | ah->hw_version.macRev); | ||
1579 | return false; | ||
1580 | } | ||
1581 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
1582 | break; | ||
1583 | case ATH9K_CIPHER_TKIP: | ||
1584 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
1585 | if (ATH9K_IS_MIC_ENABLED(ah) | ||
1586 | && entry + 64 >= pCap->keycache_size) { | ||
1587 | ath_print(common, ATH_DBG_ANY, | ||
1588 | "entry %u inappropriate for TKIP\n", entry); | ||
1589 | return false; | ||
1590 | } | ||
1591 | break; | ||
1592 | case ATH9K_CIPHER_WEP: | ||
1593 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { | ||
1594 | ath_print(common, ATH_DBG_ANY, | ||
1595 | "WEP key length %u too small\n", k->kv_len); | ||
1596 | return false; | ||
1597 | } | ||
1598 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) | ||
1599 | keyType = AR_KEYTABLE_TYPE_40; | ||
1600 | else if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1601 | keyType = AR_KEYTABLE_TYPE_104; | ||
1602 | else | ||
1603 | keyType = AR_KEYTABLE_TYPE_128; | ||
1604 | break; | ||
1605 | case ATH9K_CIPHER_CLR: | ||
1606 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
1607 | break; | ||
1608 | default: | ||
1609 | ath_print(common, ATH_DBG_FATAL, | ||
1610 | "cipher %u not supported\n", k->kv_type); | ||
1611 | return false; | ||
1612 | } | ||
1613 | |||
1614 | key0 = get_unaligned_le32(k->kv_val + 0); | ||
1615 | key1 = get_unaligned_le16(k->kv_val + 4); | ||
1616 | key2 = get_unaligned_le32(k->kv_val + 6); | ||
1617 | key3 = get_unaligned_le16(k->kv_val + 10); | ||
1618 | key4 = get_unaligned_le32(k->kv_val + 12); | ||
1619 | if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1620 | key4 &= 0xff; | ||
1621 | |||
1622 | /* | ||
1623 | * Note: Key cache registers access special memory area that requires | ||
1624 | * two 32-bit writes to actually update the values in the internal | ||
1625 | * memory. Consequently, the exact order and pairs used here must be | ||
1626 | * maintained. | ||
1627 | */ | ||
1628 | |||
1629 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1630 | u16 micentry = entry + 64; | ||
1631 | |||
1632 | /* | ||
1633 | * Write inverted key[47:0] first to avoid Michael MIC errors | ||
1634 | * on frames that could be sent or received at the same time. | ||
1635 | * The correct key will be written in the end once everything | ||
1636 | * else is ready. | ||
1637 | */ | ||
1638 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
1639 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
1640 | |||
1641 | /* Write key[95:48] */ | ||
1642 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1643 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1644 | |||
1645 | /* Write key[127:96] and key type */ | ||
1646 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1647 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1648 | |||
1649 | /* Write MAC address for the entry */ | ||
1650 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1651 | |||
1652 | if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { | ||
1653 | /* | ||
1654 | * TKIP uses two key cache entries: | ||
1655 | * Michael MIC TX/RX keys in the same key cache entry | ||
1656 | * (idx = main index + 64): | ||
1657 | * key0 [31:0] = RX key [31:0] | ||
1658 | * key1 [15:0] = TX key [31:16] | ||
1659 | * key1 [31:16] = reserved | ||
1660 | * key2 [31:0] = RX key [63:32] | ||
1661 | * key3 [15:0] = TX key [15:0] | ||
1662 | * key3 [31:16] = reserved | ||
1663 | * key4 [31:0] = TX key [63:32] | ||
1664 | */ | ||
1665 | u32 mic0, mic1, mic2, mic3, mic4; | ||
1666 | |||
1667 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1668 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1669 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
1670 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
1671 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
1672 | |||
1673 | /* Write RX[31:0] and TX[31:16] */ | ||
1674 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1675 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
1676 | |||
1677 | /* Write RX[63:32] and TX[15:0] */ | ||
1678 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1679 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
1680 | |||
1681 | /* Write TX[63:32] and keyType(reserved) */ | ||
1682 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
1683 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1684 | AR_KEYTABLE_TYPE_CLR); | ||
1685 | |||
1686 | } else { | ||
1687 | /* | ||
1688 | * TKIP uses four key cache entries (two for group | ||
1689 | * keys): | ||
1690 | * Michael MIC TX/RX keys are in different key cache | ||
1691 | * entries (idx = main index + 64 for TX and | ||
1692 | * main index + 32 + 96 for RX): | ||
1693 | * key0 [31:0] = TX/RX MIC key [31:0] | ||
1694 | * key1 [31:0] = reserved | ||
1695 | * key2 [31:0] = TX/RX MIC key [63:32] | ||
1696 | * key3 [31:0] = reserved | ||
1697 | * key4 [31:0] = reserved | ||
1698 | * | ||
1699 | * Upper layer code will call this function separately | ||
1700 | * for TX and RX keys when these registers offsets are | ||
1701 | * used. | ||
1702 | */ | ||
1703 | u32 mic0, mic2; | ||
1704 | |||
1705 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1706 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1707 | |||
1708 | /* Write MIC key[31:0] */ | ||
1709 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1710 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1711 | |||
1712 | /* Write MIC key[63:32] */ | ||
1713 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1714 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1715 | |||
1716 | /* Write TX[63:32] and keyType(reserved) */ | ||
1717 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
1718 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1719 | AR_KEYTABLE_TYPE_CLR); | ||
1720 | } | ||
1721 | |||
1722 | /* MAC address registers are reserved for the MIC entry */ | ||
1723 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
1724 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
1725 | |||
1726 | /* | ||
1727 | * Write the correct (un-inverted) key[47:0] last to enable | ||
1728 | * TKIP now that all other registers are set with correct | ||
1729 | * values. | ||
1730 | */ | ||
1731 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1732 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1733 | } else { | ||
1734 | /* Write key[47:0] */ | ||
1735 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1736 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1737 | |||
1738 | /* Write key[95:48] */ | ||
1739 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1740 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1741 | |||
1742 | /* Write key[127:96] and key type */ | ||
1743 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1744 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1745 | |||
1746 | /* Write MAC address for the entry */ | ||
1747 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1748 | } | ||
1749 | |||
1750 | return true; | ||
1751 | } | ||
1752 | EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); | ||
1753 | |||
1754 | /******************************/ | 1479 | /******************************/ |
1755 | /* Power Management (Chipset) */ | 1480 | /* Power Management (Chipset) */ |
1756 | /******************************/ | 1481 | /******************************/ |
@@ -2056,6 +1781,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2056 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 1781 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
2057 | 1782 | ||
2058 | u16 capField = 0, eeval; | 1783 | u16 capField = 0, eeval; |
1784 | u8 ant_div_ctl1; | ||
2059 | 1785 | ||
2060 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); | 1786 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); |
2061 | regulatory->current_rd = eeval; | 1787 | regulatory->current_rd = eeval; |
@@ -2140,24 +1866,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2140 | pCap->low_5ghz_chan = 4920; | 1866 | pCap->low_5ghz_chan = 4920; |
2141 | pCap->high_5ghz_chan = 6100; | 1867 | pCap->high_5ghz_chan = 6100; |
2142 | 1868 | ||
2143 | pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; | 1869 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; |
2144 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; | ||
2145 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; | ||
2146 | |||
2147 | pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; | ||
2148 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; | ||
2149 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; | ||
2150 | 1870 | ||
2151 | if (ah->config.ht_enable) | 1871 | if (ah->config.ht_enable) |
2152 | pCap->hw_caps |= ATH9K_HW_CAP_HT; | 1872 | pCap->hw_caps |= ATH9K_HW_CAP_HT; |
2153 | else | 1873 | else |
2154 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; | 1874 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; |
2155 | 1875 | ||
2156 | pCap->hw_caps |= ATH9K_HW_CAP_GTT; | ||
2157 | pCap->hw_caps |= ATH9K_HW_CAP_VEOL; | ||
2158 | pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; | ||
2159 | pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; | ||
2160 | |||
2161 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) | 1876 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) |
2162 | pCap->total_queues = | 1877 | pCap->total_queues = |
2163 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); | 1878 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); |
@@ -2170,8 +1885,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2170 | else | 1885 | else |
2171 | pCap->keycache_size = AR_KEYTABLE_SIZE; | 1886 | pCap->keycache_size = AR_KEYTABLE_SIZE; |
2172 | 1887 | ||
2173 | pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; | ||
2174 | |||
2175 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 1888 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
2176 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; | 1889 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; |
2177 | else | 1890 | else |
@@ -2280,6 +1993,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2280 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) | 1993 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) |
2281 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; | 1994 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; |
2282 | 1995 | ||
1996 | if (AR_SREV_9285(ah)) | ||
1997 | if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { | ||
1998 | ant_div_ctl1 = | ||
1999 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
2000 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | ||
2001 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | ||
2002 | } | ||
2003 | |||
2283 | return 0; | 2004 | return 0; |
2284 | } | 2005 | } |
2285 | 2006 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 1601dd439890..df47f792cf4e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -181,29 +181,19 @@ enum wireless_mode { | |||
181 | }; | 181 | }; |
182 | 182 | ||
183 | enum ath9k_hw_caps { | 183 | enum ath9k_hw_caps { |
184 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), | 184 | ATH9K_HW_CAP_HT = BIT(0), |
185 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), | 185 | ATH9K_HW_CAP_RFSILENT = BIT(1), |
186 | ATH9K_HW_CAP_MIC_TKIP = BIT(2), | 186 | ATH9K_HW_CAP_CST = BIT(2), |
187 | ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), | 187 | ATH9K_HW_CAP_ENHANCEDPM = BIT(3), |
188 | ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), | 188 | ATH9K_HW_CAP_AUTOSLEEP = BIT(4), |
189 | ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), | 189 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), |
190 | ATH9K_HW_CAP_VEOL = BIT(6), | 190 | ATH9K_HW_CAP_EDMA = BIT(6), |
191 | ATH9K_HW_CAP_BSSIDMASK = BIT(7), | 191 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7), |
192 | ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), | 192 | ATH9K_HW_CAP_LDPC = BIT(8), |
193 | ATH9K_HW_CAP_HT = BIT(9), | 193 | ATH9K_HW_CAP_FASTCLOCK = BIT(9), |
194 | ATH9K_HW_CAP_GTT = BIT(10), | 194 | ATH9K_HW_CAP_SGI_20 = BIT(10), |
195 | ATH9K_HW_CAP_FASTCC = BIT(11), | 195 | ATH9K_HW_CAP_PAPRD = BIT(11), |
196 | ATH9K_HW_CAP_RFSILENT = BIT(12), | 196 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), |
197 | ATH9K_HW_CAP_CST = BIT(13), | ||
198 | ATH9K_HW_CAP_ENHANCEDPM = BIT(14), | ||
199 | ATH9K_HW_CAP_AUTOSLEEP = BIT(15), | ||
200 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), | ||
201 | ATH9K_HW_CAP_EDMA = BIT(17), | ||
202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), | ||
203 | ATH9K_HW_CAP_LDPC = BIT(19), | ||
204 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), | ||
205 | ATH9K_HW_CAP_SGI_20 = BIT(21), | ||
206 | ATH9K_HW_CAP_PAPRD = BIT(22), | ||
207 | }; | 197 | }; |
208 | 198 | ||
209 | struct ath9k_hw_capabilities { | 199 | struct ath9k_hw_capabilities { |
@@ -495,6 +485,12 @@ struct ath_gen_timer_table { | |||
495 | } timer_mask; | 485 | } timer_mask; |
496 | }; | 486 | }; |
497 | 487 | ||
488 | struct ath_hw_antcomb_conf { | ||
489 | u8 main_lna_conf; | ||
490 | u8 alt_lna_conf; | ||
491 | u8 fast_div_bias; | ||
492 | }; | ||
493 | |||
498 | /** | 494 | /** |
499 | * struct ath_hw_private_ops - callbacks used internally by hardware code | 495 | * struct ath_hw_private_ops - callbacks used internally by hardware code |
500 | * | 496 | * |
@@ -874,12 +870,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
874 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 870 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
875 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 871 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
876 | 872 | ||
877 | /* Key Cache Management */ | ||
878 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); | ||
879 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
880 | const struct ath9k_keyval *k, | ||
881 | const u8 *mac); | ||
882 | |||
883 | /* GPIO / RFKILL / Antennae */ | 873 | /* GPIO / RFKILL / Antennae */ |
884 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); | 874 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); |
885 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); | 875 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); |
@@ -888,6 +878,10 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | |||
888 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); | 878 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); |
889 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); | 879 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); |
890 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | 880 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); |
881 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
882 | struct ath_hw_antcomb_conf *antconf); | ||
883 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
884 | struct ath_hw_antcomb_conf *antconf); | ||
891 | 885 | ||
892 | /* General Operation */ | 886 | /* General Operation */ |
893 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 887 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
@@ -985,6 +979,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | |||
985 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 979 | void ar9002_hw_attach_ops(struct ath_hw *ah); |
986 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 980 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
987 | 981 | ||
982 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | ||
988 | /* | 983 | /* |
989 | * ANI work can be shared between all families but a next | 984 | * ANI work can be shared between all families but a next |
990 | * generation implementation of ANI will be used only for AR9003 only | 985 | * generation implementation of ANI will be used only for AR9003 only |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 3dbff8d07766..573899e27b3d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -381,7 +381,7 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
381 | * reset the contents on initial power up. | 381 | * reset the contents on initial power up. |
382 | */ | 382 | */ |
383 | for (i = 0; i < common->keymax; i++) | 383 | for (i = 0; i < common->keymax; i++) |
384 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | 384 | ath_hw_keyreset(common, (u16) i); |
385 | 385 | ||
386 | /* | 386 | /* |
387 | * Check whether the separate key cache entries | 387 | * Check whether the separate key cache entries |
@@ -389,8 +389,8 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
389 | * With split mic keys the number of stations is limited | 389 | * With split mic keys the number of stations is limited |
390 | * to 27 otherwise 59. | 390 | * to 27 otherwise 59. |
391 | */ | 391 | */ |
392 | if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) | 392 | if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) |
393 | common->splitmic = 1; | 393 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
394 | } | 394 | } |
395 | 395 | ||
396 | static int ath9k_init_btcoex(struct ath_softc *sc) | 396 | static int ath9k_init_btcoex(struct ath_softc *sc) |
@@ -522,8 +522,7 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
522 | ath9k_hw_set_diversity(sc->sc_ah, true); | 522 | ath9k_hw_set_diversity(sc->sc_ah, true); |
523 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | 523 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
524 | 524 | ||
525 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 525 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
526 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
527 | 526 | ||
528 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 527 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
529 | 528 | ||
@@ -531,6 +530,9 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
531 | sc->beacon.bslot[i] = NULL; | 530 | sc->beacon.bslot[i] = NULL; |
532 | sc->beacon.bslot_aphy[i] = NULL; | 531 | sc->beacon.bslot_aphy[i] = NULL; |
533 | } | 532 | } |
533 | |||
534 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | ||
535 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | ||
534 | } | 536 | } |
535 | 537 | ||
536 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | 538 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, |
@@ -641,7 +643,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
641 | BIT(NL80211_IFTYPE_ADHOC) | | 643 | BIT(NL80211_IFTYPE_ADHOC) | |
642 | BIT(NL80211_IFTYPE_MESH_POINT); | 644 | BIT(NL80211_IFTYPE_MESH_POINT); |
643 | 645 | ||
644 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 646 | if (AR_SREV_5416(sc->sc_ah)) |
647 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
645 | 648 | ||
646 | hw->queues = 4; | 649 | hw->queues = 4; |
647 | hw->max_rates = 4; | 650 | hw->max_rates = 4; |
@@ -651,7 +654,9 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
651 | hw->sta_data_size = sizeof(struct ath_node); | 654 | hw->sta_data_size = sizeof(struct ath_node); |
652 | hw->vif_data_size = sizeof(struct ath_vif); | 655 | hw->vif_data_size = sizeof(struct ath_vif); |
653 | 656 | ||
657 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
654 | hw->rate_control_algorithm = "ath9k_rate_control"; | 658 | hw->rate_control_algorithm = "ath9k_rate_control"; |
659 | #endif | ||
655 | 660 | ||
656 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | 661 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) |
657 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 662 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0b7d1253f0c0..3efda8a8a3c1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -714,6 +714,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
714 | else if ((ads.ds_rxstatus8 & AR_MichaelErr) && | 714 | else if ((ads.ds_rxstatus8 & AR_MichaelErr) && |
715 | rs->rs_keyix != ATH9K_RXKEYIX_INVALID) | 715 | rs->rs_keyix != ATH9K_RXKEYIX_INVALID) |
716 | rs->rs_status |= ATH9K_RXERR_MIC; | 716 | rs->rs_status |= ATH9K_RXERR_MIC; |
717 | else if (ads.ds_rxstatus8 & AR_KeyMiss) | ||
718 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
717 | } | 719 | } |
718 | 720 | ||
719 | return 0; | 721 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 2633896d3998..7c1a34d64f6d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -660,17 +660,6 @@ struct ath9k_11n_rate_series { | |||
660 | u32 RateFlags; | 660 | u32 RateFlags; |
661 | }; | 661 | }; |
662 | 662 | ||
663 | struct ath9k_keyval { | ||
664 | u8 kv_type; | ||
665 | u8 kv_pad; | ||
666 | u16 kv_len; | ||
667 | u8 kv_val[16]; /* TK */ | ||
668 | u8 kv_mic[8]; /* Michael MIC key */ | ||
669 | u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware | ||
670 | * supports both MIC keys in the same key cache entry; | ||
671 | * in that case, kv_mic is the RX key) */ | ||
672 | }; | ||
673 | |||
674 | enum ath9k_key_type { | 663 | enum ath9k_key_type { |
675 | ATH9K_KEY_TYPE_CLEAR, | 664 | ATH9K_KEY_TYPE_CLEAR, |
676 | ATH9K_KEY_TYPE_WEP, | 665 | ATH9K_KEY_TYPE_WEP, |
@@ -678,16 +667,6 @@ enum ath9k_key_type { | |||
678 | ATH9K_KEY_TYPE_TKIP, | 667 | ATH9K_KEY_TYPE_TKIP, |
679 | }; | 668 | }; |
680 | 669 | ||
681 | enum ath9k_cipher { | ||
682 | ATH9K_CIPHER_WEP = 0, | ||
683 | ATH9K_CIPHER_AES_OCB = 1, | ||
684 | ATH9K_CIPHER_AES_CCM = 2, | ||
685 | ATH9K_CIPHER_CKIP = 3, | ||
686 | ATH9K_CIPHER_TKIP = 4, | ||
687 | ATH9K_CIPHER_CLR = 5, | ||
688 | ATH9K_CIPHER_MIC = 127 | ||
689 | }; | ||
690 | |||
691 | struct ath_hw; | 670 | struct ath_hw; |
692 | struct ath9k_channel; | 671 | struct ath9k_channel; |
693 | 672 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1165f909ef04..8b327bcad695 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -255,10 +255,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
255 | ath_update_txpow(sc); | 255 | ath_update_txpow(sc); |
256 | ath9k_hw_set_interrupts(ah, ah->imask); | 256 | ath9k_hw_set_interrupts(ah, ah->imask); |
257 | 257 | ||
258 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { | 258 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { |
259 | ath_start_ani(common); | ||
260 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
261 | ath_beacon_config(sc, NULL); | 259 | ath_beacon_config(sc, NULL); |
260 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
261 | ath_start_ani(common); | ||
262 | } | 262 | } |
263 | 263 | ||
264 | ps_restore: | 264 | ps_restore: |
@@ -957,7 +957,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
957 | 957 | ||
958 | ath_update_txpow(sc); | 958 | ath_update_txpow(sc); |
959 | 959 | ||
960 | if (sc->sc_flags & SC_OP_BEACONS) | 960 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) |
961 | ath_beacon_config(sc, NULL); /* restart beacons */ | 961 | ath_beacon_config(sc, NULL); /* restart beacons */ |
962 | 962 | ||
963 | ath9k_hw_set_interrupts(ah, ah->imask); | 963 | ath9k_hw_set_interrupts(ah, ah->imask); |
@@ -1156,8 +1156,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1156 | else | 1156 | else |
1157 | ah->imask |= ATH9K_INT_RX; | 1157 | ah->imask |= ATH9K_INT_RX; |
1158 | 1158 | ||
1159 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 1159 | ah->imask |= ATH9K_INT_GTT; |
1160 | ah->imask |= ATH9K_INT_GTT; | ||
1161 | 1160 | ||
1162 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1161 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1163 | ah->imask |= ATH9K_INT_CST; | 1162 | ah->imask |= ATH9K_INT_CST; |
@@ -1379,12 +1378,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1379 | 1378 | ||
1380 | mutex_lock(&sc->mutex); | 1379 | mutex_lock(&sc->mutex); |
1381 | 1380 | ||
1382 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && | ||
1383 | sc->nvifs > 0) { | ||
1384 | ret = -ENOBUFS; | ||
1385 | goto out; | ||
1386 | } | ||
1387 | |||
1388 | switch (vif->type) { | 1381 | switch (vif->type) { |
1389 | case NL80211_IFTYPE_STATION: | 1382 | case NL80211_IFTYPE_STATION: |
1390 | ic_opmode = NL80211_IFTYPE_STATION; | 1383 | ic_opmode = NL80211_IFTYPE_STATION; |
@@ -1414,8 +1407,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1414 | 1407 | ||
1415 | sc->nvifs++; | 1408 | sc->nvifs++; |
1416 | 1409 | ||
1417 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1410 | ath9k_set_bssid_mask(hw, vif); |
1418 | ath9k_set_bssid_mask(hw); | ||
1419 | 1411 | ||
1420 | if (sc->nvifs > 1) | 1412 | if (sc->nvifs > 1) |
1421 | goto out; /* skip global settings for secondary vif */ | 1413 | goto out; /* skip global settings for secondary vif */ |
@@ -1562,6 +1554,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1562 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. | 1554 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. |
1563 | */ | 1555 | */ |
1564 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1556 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1557 | unsigned long flags; | ||
1558 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1565 | if (conf->flags & IEEE80211_CONF_PS) { | 1559 | if (conf->flags & IEEE80211_CONF_PS) { |
1566 | sc->ps_flags |= PS_ENABLED; | 1560 | sc->ps_flags |= PS_ENABLED; |
1567 | /* | 1561 | /* |
@@ -1576,7 +1570,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1576 | sc->ps_enabled = false; | 1570 | sc->ps_enabled = false; |
1577 | sc->ps_flags &= ~(PS_ENABLED | | 1571 | sc->ps_flags &= ~(PS_ENABLED | |
1578 | PS_NULLFUNC_COMPLETED); | 1572 | PS_NULLFUNC_COMPLETED); |
1579 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 1573 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); |
1580 | if (!(ah->caps.hw_caps & | 1574 | if (!(ah->caps.hw_caps & |
1581 | ATH9K_HW_CAP_AUTOSLEEP)) { | 1575 | ATH9K_HW_CAP_AUTOSLEEP)) { |
1582 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 1576 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
@@ -1591,6 +1585,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1591 | } | 1585 | } |
1592 | } | 1586 | } |
1593 | } | 1587 | } |
1588 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1594 | } | 1589 | } |
1595 | 1590 | ||
1596 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1591 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
@@ -1777,7 +1772,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1777 | 1772 | ||
1778 | switch (cmd) { | 1773 | switch (cmd) { |
1779 | case SET_KEY: | 1774 | case SET_KEY: |
1780 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1775 | ret = ath_key_config(common, vif, sta, key); |
1781 | if (ret >= 0) { | 1776 | if (ret >= 0) { |
1782 | key->hw_key_idx = ret; | 1777 | key->hw_key_idx = ret; |
1783 | /* push IV and Michael MIC generation to stack */ | 1778 | /* push IV and Michael MIC generation to stack */ |
@@ -1791,7 +1786,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1791 | } | 1786 | } |
1792 | break; | 1787 | break; |
1793 | case DISABLE_KEY: | 1788 | case DISABLE_KEY: |
1794 | ath9k_cmn_key_delete(common, key); | 1789 | ath_key_delete(common, key); |
1795 | break; | 1790 | break; |
1796 | default: | 1791 | default: |
1797 | ret = -EINVAL; | 1792 | ret = -EINVAL; |
@@ -1975,8 +1970,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1975 | break; | 1970 | break; |
1976 | case IEEE80211_AMPDU_TX_START: | 1971 | case IEEE80211_AMPDU_TX_START: |
1977 | ath9k_ps_wakeup(sc); | 1972 | ath9k_ps_wakeup(sc); |
1978 | ath_tx_aggr_start(sc, sta, tid, ssn); | 1973 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
1979 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1974 | if (!ret) |
1975 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1980 | ath9k_ps_restore(sc); | 1976 | ath9k_ps_restore(sc); |
1981 | break; | 1977 | break; |
1982 | case IEEE80211_AMPDU_TX_STOP: | 1978 | case IEEE80211_AMPDU_TX_STOP: |
@@ -2039,7 +2035,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2039 | 2035 | ||
2040 | aphy->state = ATH_WIPHY_SCAN; | 2036 | aphy->state = ATH_WIPHY_SCAN; |
2041 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2037 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2042 | sc->sc_flags |= SC_OP_SCANNING; | ||
2043 | mutex_unlock(&sc->mutex); | 2038 | mutex_unlock(&sc->mutex); |
2044 | } | 2039 | } |
2045 | 2040 | ||
@@ -2054,7 +2049,6 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2054 | 2049 | ||
2055 | mutex_lock(&sc->mutex); | 2050 | mutex_lock(&sc->mutex); |
2056 | aphy->state = ATH_WIPHY_ACTIVE; | 2051 | aphy->state = ATH_WIPHY_ACTIVE; |
2057 | sc->sc_flags &= ~SC_OP_SCANNING; | ||
2058 | mutex_unlock(&sc->mutex); | 2052 | mutex_unlock(&sc->mutex); |
2059 | } | 2053 | } |
2060 | 2054 | ||
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e724c2c1ae2a..17969af842f6 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -45,9 +45,6 @@ | |||
45 | } \ | 45 | } \ |
46 | } while (0) | 46 | } while (0) |
47 | 47 | ||
48 | #define ATH9K_IS_MIC_ENABLED(ah) \ | ||
49 | ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) | ||
50 | |||
51 | #define ANTSWAP_AB 0x0001 | 48 | #define ANTSWAP_AB 0x0001 |
52 | #define REDUCE_CHAIN_0 0x00000050 | 49 | #define REDUCE_CHAIN_0 0x00000050 |
53 | #define REDUCE_CHAIN_1 0x00000051 | 50 | #define REDUCE_CHAIN_1 0x00000051 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e49be733d546..ce1cd6d85847 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1320,6 +1320,22 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1320 | return caps; | 1320 | return caps; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, | ||
1324 | u8 tidno) | ||
1325 | { | ||
1326 | struct ath_atx_tid *txtid; | ||
1327 | |||
1328 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
1329 | return false; | ||
1330 | |||
1331 | txtid = ATH_AN_2_TID(an, tidno); | ||
1332 | |||
1333 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
1334 | return true; | ||
1335 | return false; | ||
1336 | } | ||
1337 | |||
1338 | |||
1323 | /***********************************/ | 1339 | /***********************************/ |
1324 | /* mac80211 Rate Control callbacks */ | 1340 | /* mac80211 Rate Control callbacks */ |
1325 | /***********************************/ | 1341 | /***********************************/ |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index dc1082654501..268072fd3c1c 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -224,7 +224,18 @@ enum ath9k_internal_frame_type { | |||
224 | ATH9K_IFT_UNPAUSE | 224 | ATH9K_IFT_UNPAUSE |
225 | }; | 225 | }; |
226 | 226 | ||
227 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
227 | int ath_rate_control_register(void); | 228 | int ath_rate_control_register(void); |
228 | void ath_rate_control_unregister(void); | 229 | void ath_rate_control_unregister(void); |
230 | #else | ||
231 | static inline int ath_rate_control_register(void) | ||
232 | { | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static inline void ath_rate_control_unregister(void) | ||
237 | { | ||
238 | } | ||
239 | #endif | ||
229 | 240 | ||
230 | #endif /* RC_H */ | 241 | #endif /* RC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 534a91bcc1d9..c5e7af4f51ab 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -19,6 +19,15 @@ | |||
19 | 19 | ||
20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
21 | 21 | ||
22 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | ||
23 | int mindelta, int main_rssi_avg, | ||
24 | int alt_rssi_avg, int pkt_count) | ||
25 | { | ||
26 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
27 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | ||
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
29 | } | ||
30 | |||
22 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 31 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
23 | { | 32 | { |
24 | return sc->ps_enabled && | 33 | return sc->ps_enabled && |
@@ -110,8 +119,7 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
110 | ath9k_hw_setrxfilter(ah, rfilt); | 119 | ath9k_hw_setrxfilter(ah, rfilt); |
111 | 120 | ||
112 | /* configure bssid mask */ | 121 | /* configure bssid mask */ |
113 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 122 | ath_hw_setbssidmask(common); |
114 | ath_hw_setbssidmask(common); | ||
115 | 123 | ||
116 | /* configure operational mode */ | 124 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 125 | ath9k_hw_setopmode(ah); |
@@ -292,7 +300,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
292 | 300 | ||
293 | ath_opmode_init(sc); | 301 | ath_opmode_init(sc); |
294 | 302 | ||
295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); | 303 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
296 | } | 304 | } |
297 | 305 | ||
298 | static void ath_edma_stop_recv(struct ath_softc *sc) | 306 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -440,6 +448,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
440 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 448 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
441 | 449 | ||
442 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | 450 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && |
451 | (sc->nvifs <= 1) && | ||
443 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) | 452 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) |
444 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | 453 | rfilt |= ATH9K_RX_FILTER_MYBEACON; |
445 | else | 454 | else |
@@ -454,9 +463,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
454 | if (conf_is_ht(&sc->hw->conf)) | 463 | if (conf_is_ht(&sc->hw->conf)) |
455 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 464 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
456 | 465 | ||
457 | if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { | 466 | if (sc->sec_wiphy || (sc->nvifs > 1) || |
458 | /* TODO: only needed if more than one BSSID is in use in | 467 | (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
459 | * station/adhoc mode */ | ||
460 | /* The following may also be needed for other older chips */ | 468 | /* The following may also be needed for other older chips */ |
461 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 469 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
462 | rfilt |= ATH9K_RX_FILTER_PROM; | 470 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -498,7 +506,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
498 | start_recv: | 506 | start_recv: |
499 | spin_unlock_bh(&sc->rx.rxbuflock); | 507 | spin_unlock_bh(&sc->rx.rxbuflock); |
500 | ath_opmode_init(sc); | 508 | ath_opmode_init(sc); |
501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); | 509 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
502 | 510 | ||
503 | return 0; | 511 | return 0; |
504 | } | 512 | } |
@@ -631,7 +639,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
631 | * No more broadcast/multicast frames to be received at this | 639 | * No more broadcast/multicast frames to be received at this |
632 | * point. | 640 | * point. |
633 | */ | 641 | */ |
634 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 642 | sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); |
635 | ath_print(common, ATH_DBG_PS, | 643 | ath_print(common, ATH_DBG_PS, |
636 | "All PS CAB frames received, back to sleep\n"); | 644 | "All PS CAB frames received, back to sleep\n"); |
637 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && | 645 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && |
@@ -1076,6 +1084,539 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1076 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1084 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1077 | } | 1085 | } |
1078 | 1086 | ||
1087 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
1088 | struct ath_hw_antcomb_conf ant_conf, | ||
1089 | int main_rssi_avg) | ||
1090 | { | ||
1091 | antcomb->quick_scan_cnt = 0; | ||
1092 | |||
1093 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1094 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1095 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1096 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1097 | |||
1098 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
1099 | case (0x10): /* LNA2 A-B */ | ||
1100 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1101 | antcomb->first_quick_scan_conf = | ||
1102 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1103 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1104 | break; | ||
1105 | case (0x20): /* LNA1 A-B */ | ||
1106 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1107 | antcomb->first_quick_scan_conf = | ||
1108 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1109 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1110 | break; | ||
1111 | case (0x21): /* LNA1 LNA2 */ | ||
1112 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1113 | antcomb->first_quick_scan_conf = | ||
1114 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1115 | antcomb->second_quick_scan_conf = | ||
1116 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1117 | break; | ||
1118 | case (0x12): /* LNA2 LNA1 */ | ||
1119 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1120 | antcomb->first_quick_scan_conf = | ||
1121 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1122 | antcomb->second_quick_scan_conf = | ||
1123 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1124 | break; | ||
1125 | case (0x13): /* LNA2 A+B */ | ||
1126 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1127 | antcomb->first_quick_scan_conf = | ||
1128 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1129 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1130 | break; | ||
1131 | case (0x23): /* LNA1 A+B */ | ||
1132 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1133 | antcomb->first_quick_scan_conf = | ||
1134 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1135 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1136 | break; | ||
1137 | default: | ||
1138 | break; | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
1143 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
1144 | int main_rssi_avg, int alt_rssi_avg, | ||
1145 | int alt_ratio) | ||
1146 | { | ||
1147 | /* alt_good */ | ||
1148 | switch (antcomb->quick_scan_cnt) { | ||
1149 | case 0: | ||
1150 | /* set alt to main, and alt to first conf */ | ||
1151 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1152 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
1153 | break; | ||
1154 | case 1: | ||
1155 | /* set alt to main, and alt to first conf */ | ||
1156 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1157 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
1158 | antcomb->rssi_first = main_rssi_avg; | ||
1159 | antcomb->rssi_second = alt_rssi_avg; | ||
1160 | |||
1161 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1162 | /* main is LNA1 */ | ||
1163 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1164 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1165 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1166 | main_rssi_avg, alt_rssi_avg, | ||
1167 | antcomb->total_pkt_count)) | ||
1168 | antcomb->first_ratio = true; | ||
1169 | else | ||
1170 | antcomb->first_ratio = false; | ||
1171 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1172 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1173 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1174 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1175 | main_rssi_avg, alt_rssi_avg, | ||
1176 | antcomb->total_pkt_count)) | ||
1177 | antcomb->first_ratio = true; | ||
1178 | else | ||
1179 | antcomb->first_ratio = false; | ||
1180 | } else { | ||
1181 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1182 | (alt_rssi_avg > main_rssi_avg + | ||
1183 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1184 | (alt_rssi_avg > main_rssi_avg)) && | ||
1185 | (antcomb->total_pkt_count > 50)) | ||
1186 | antcomb->first_ratio = true; | ||
1187 | else | ||
1188 | antcomb->first_ratio = false; | ||
1189 | } | ||
1190 | break; | ||
1191 | case 2: | ||
1192 | antcomb->alt_good = false; | ||
1193 | antcomb->scan_not_start = false; | ||
1194 | antcomb->scan = false; | ||
1195 | antcomb->rssi_first = main_rssi_avg; | ||
1196 | antcomb->rssi_third = alt_rssi_avg; | ||
1197 | |||
1198 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1199 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1200 | else if (antcomb->second_quick_scan_conf == | ||
1201 | ATH_ANT_DIV_COMB_LNA2) | ||
1202 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1203 | else if (antcomb->second_quick_scan_conf == | ||
1204 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
1205 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1206 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1207 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1208 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1209 | } | ||
1210 | |||
1211 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
1212 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
1213 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1214 | else | ||
1215 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1216 | |||
1217 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1218 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1219 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1220 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1221 | main_rssi_avg, alt_rssi_avg, | ||
1222 | antcomb->total_pkt_count)) | ||
1223 | antcomb->second_ratio = true; | ||
1224 | else | ||
1225 | antcomb->second_ratio = false; | ||
1226 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1227 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1228 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1229 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1230 | main_rssi_avg, alt_rssi_avg, | ||
1231 | antcomb->total_pkt_count)) | ||
1232 | antcomb->second_ratio = true; | ||
1233 | else | ||
1234 | antcomb->second_ratio = false; | ||
1235 | } else { | ||
1236 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1237 | (alt_rssi_avg > main_rssi_avg + | ||
1238 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1239 | (alt_rssi_avg > main_rssi_avg)) && | ||
1240 | (antcomb->total_pkt_count > 50)) | ||
1241 | antcomb->second_ratio = true; | ||
1242 | else | ||
1243 | antcomb->second_ratio = false; | ||
1244 | } | ||
1245 | |||
1246 | /* set alt to the conf with maximun ratio */ | ||
1247 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
1248 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
1249 | /* first alt*/ | ||
1250 | if ((antcomb->first_quick_scan_conf == | ||
1251 | ATH_ANT_DIV_COMB_LNA1) || | ||
1252 | (antcomb->first_quick_scan_conf == | ||
1253 | ATH_ANT_DIV_COMB_LNA2)) | ||
1254 | /* Set alt LNA1 or LNA2*/ | ||
1255 | if (div_ant_conf->main_lna_conf == | ||
1256 | ATH_ANT_DIV_COMB_LNA2) | ||
1257 | div_ant_conf->alt_lna_conf = | ||
1258 | ATH_ANT_DIV_COMB_LNA1; | ||
1259 | else | ||
1260 | div_ant_conf->alt_lna_conf = | ||
1261 | ATH_ANT_DIV_COMB_LNA2; | ||
1262 | else | ||
1263 | /* Set alt to A+B or A-B */ | ||
1264 | div_ant_conf->alt_lna_conf = | ||
1265 | antcomb->first_quick_scan_conf; | ||
1266 | } else if ((antcomb->second_quick_scan_conf == | ||
1267 | ATH_ANT_DIV_COMB_LNA1) || | ||
1268 | (antcomb->second_quick_scan_conf == | ||
1269 | ATH_ANT_DIV_COMB_LNA2)) { | ||
1270 | /* Set alt LNA1 or LNA2 */ | ||
1271 | if (div_ant_conf->main_lna_conf == | ||
1272 | ATH_ANT_DIV_COMB_LNA2) | ||
1273 | div_ant_conf->alt_lna_conf = | ||
1274 | ATH_ANT_DIV_COMB_LNA1; | ||
1275 | else | ||
1276 | div_ant_conf->alt_lna_conf = | ||
1277 | ATH_ANT_DIV_COMB_LNA2; | ||
1278 | } else { | ||
1279 | /* Set alt to A+B or A-B */ | ||
1280 | div_ant_conf->alt_lna_conf = | ||
1281 | antcomb->second_quick_scan_conf; | ||
1282 | } | ||
1283 | } else if (antcomb->first_ratio) { | ||
1284 | /* first alt */ | ||
1285 | if ((antcomb->first_quick_scan_conf == | ||
1286 | ATH_ANT_DIV_COMB_LNA1) || | ||
1287 | (antcomb->first_quick_scan_conf == | ||
1288 | ATH_ANT_DIV_COMB_LNA2)) | ||
1289 | /* Set alt LNA1 or LNA2 */ | ||
1290 | if (div_ant_conf->main_lna_conf == | ||
1291 | ATH_ANT_DIV_COMB_LNA2) | ||
1292 | div_ant_conf->alt_lna_conf = | ||
1293 | ATH_ANT_DIV_COMB_LNA1; | ||
1294 | else | ||
1295 | div_ant_conf->alt_lna_conf = | ||
1296 | ATH_ANT_DIV_COMB_LNA2; | ||
1297 | else | ||
1298 | /* Set alt to A+B or A-B */ | ||
1299 | div_ant_conf->alt_lna_conf = | ||
1300 | antcomb->first_quick_scan_conf; | ||
1301 | } else if (antcomb->second_ratio) { | ||
1302 | /* second alt */ | ||
1303 | if ((antcomb->second_quick_scan_conf == | ||
1304 | ATH_ANT_DIV_COMB_LNA1) || | ||
1305 | (antcomb->second_quick_scan_conf == | ||
1306 | ATH_ANT_DIV_COMB_LNA2)) | ||
1307 | /* Set alt LNA1 or LNA2 */ | ||
1308 | if (div_ant_conf->main_lna_conf == | ||
1309 | ATH_ANT_DIV_COMB_LNA2) | ||
1310 | div_ant_conf->alt_lna_conf = | ||
1311 | ATH_ANT_DIV_COMB_LNA1; | ||
1312 | else | ||
1313 | div_ant_conf->alt_lna_conf = | ||
1314 | ATH_ANT_DIV_COMB_LNA2; | ||
1315 | else | ||
1316 | /* Set alt to A+B or A-B */ | ||
1317 | div_ant_conf->alt_lna_conf = | ||
1318 | antcomb->second_quick_scan_conf; | ||
1319 | } else { | ||
1320 | /* main is largest */ | ||
1321 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
1322 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
1323 | /* Set alt LNA1 or LNA2 */ | ||
1324 | if (div_ant_conf->main_lna_conf == | ||
1325 | ATH_ANT_DIV_COMB_LNA2) | ||
1326 | div_ant_conf->alt_lna_conf = | ||
1327 | ATH_ANT_DIV_COMB_LNA1; | ||
1328 | else | ||
1329 | div_ant_conf->alt_lna_conf = | ||
1330 | ATH_ANT_DIV_COMB_LNA2; | ||
1331 | else | ||
1332 | /* Set alt to A+B or A-B */ | ||
1333 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
1334 | } | ||
1335 | break; | ||
1336 | default: | ||
1337 | break; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf) | ||
1342 | { | ||
1343 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
1344 | switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { | ||
1345 | case (0x01): /* A-B LNA2 */ | ||
1346 | ant_conf->fast_div_bias = 0x3b; | ||
1347 | break; | ||
1348 | case (0x02): /* A-B LNA1 */ | ||
1349 | ant_conf->fast_div_bias = 0x3d; | ||
1350 | break; | ||
1351 | case (0x03): /* A-B A+B */ | ||
1352 | ant_conf->fast_div_bias = 0x1; | ||
1353 | break; | ||
1354 | case (0x10): /* LNA2 A-B */ | ||
1355 | ant_conf->fast_div_bias = 0x7; | ||
1356 | break; | ||
1357 | case (0x12): /* LNA2 LNA1 */ | ||
1358 | ant_conf->fast_div_bias = 0x2; | ||
1359 | break; | ||
1360 | case (0x13): /* LNA2 A+B */ | ||
1361 | ant_conf->fast_div_bias = 0x7; | ||
1362 | break; | ||
1363 | case (0x20): /* LNA1 A-B */ | ||
1364 | ant_conf->fast_div_bias = 0x6; | ||
1365 | break; | ||
1366 | case (0x21): /* LNA1 LNA2 */ | ||
1367 | ant_conf->fast_div_bias = 0x0; | ||
1368 | break; | ||
1369 | case (0x23): /* LNA1 A+B */ | ||
1370 | ant_conf->fast_div_bias = 0x6; | ||
1371 | break; | ||
1372 | case (0x30): /* A+B A-B */ | ||
1373 | ant_conf->fast_div_bias = 0x1; | ||
1374 | break; | ||
1375 | case (0x31): /* A+B LNA2 */ | ||
1376 | ant_conf->fast_div_bias = 0x3b; | ||
1377 | break; | ||
1378 | case (0x32): /* A+B LNA1 */ | ||
1379 | ant_conf->fast_div_bias = 0x3d; | ||
1380 | break; | ||
1381 | default: | ||
1382 | break; | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | /* Antenna diversity and combining */ | ||
1387 | static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
1388 | { | ||
1389 | struct ath_hw_antcomb_conf div_ant_conf; | ||
1390 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
1391 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
1392 | int curr_main_set, curr_bias; | ||
1393 | int main_rssi = rs->rs_rssi_ctl0; | ||
1394 | int alt_rssi = rs->rs_rssi_ctl1; | ||
1395 | int rx_ant_conf, main_ant_conf; | ||
1396 | bool short_scan = false; | ||
1397 | |||
1398 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
1399 | ATH_ANT_RX_MASK; | ||
1400 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
1401 | ATH_ANT_RX_MASK; | ||
1402 | |||
1403 | /* Record packet only when alt_rssi is positive */ | ||
1404 | if (alt_rssi > 0) { | ||
1405 | antcomb->total_pkt_count++; | ||
1406 | antcomb->main_total_rssi += main_rssi; | ||
1407 | antcomb->alt_total_rssi += alt_rssi; | ||
1408 | if (main_ant_conf == rx_ant_conf) | ||
1409 | antcomb->main_recv_cnt++; | ||
1410 | else | ||
1411 | antcomb->alt_recv_cnt++; | ||
1412 | } | ||
1413 | |||
1414 | /* Short scan check */ | ||
1415 | if (antcomb->scan && antcomb->alt_good) { | ||
1416 | if (time_after(jiffies, antcomb->scan_start_time + | ||
1417 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
1418 | short_scan = true; | ||
1419 | else | ||
1420 | if (antcomb->total_pkt_count == | ||
1421 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
1422 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1423 | antcomb->total_pkt_count); | ||
1424 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
1425 | short_scan = true; | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
1430 | rs->rs_moreaggr) && !short_scan) | ||
1431 | return; | ||
1432 | |||
1433 | if (antcomb->total_pkt_count) { | ||
1434 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1435 | antcomb->total_pkt_count); | ||
1436 | main_rssi_avg = (antcomb->main_total_rssi / | ||
1437 | antcomb->total_pkt_count); | ||
1438 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
1439 | antcomb->total_pkt_count); | ||
1440 | } | ||
1441 | |||
1442 | |||
1443 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
1444 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
1445 | curr_main_set = div_ant_conf.main_lna_conf; | ||
1446 | curr_bias = div_ant_conf.fast_div_bias; | ||
1447 | |||
1448 | antcomb->count++; | ||
1449 | |||
1450 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
1451 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1452 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
1453 | main_rssi_avg); | ||
1454 | antcomb->alt_good = true; | ||
1455 | } else { | ||
1456 | antcomb->alt_good = false; | ||
1457 | } | ||
1458 | |||
1459 | antcomb->count = 0; | ||
1460 | antcomb->scan = true; | ||
1461 | antcomb->scan_not_start = true; | ||
1462 | } | ||
1463 | |||
1464 | if (!antcomb->scan) { | ||
1465 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1466 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1467 | /* Switch main and alt LNA */ | ||
1468 | div_ant_conf.main_lna_conf = | ||
1469 | ATH_ANT_DIV_COMB_LNA2; | ||
1470 | div_ant_conf.alt_lna_conf = | ||
1471 | ATH_ANT_DIV_COMB_LNA1; | ||
1472 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1473 | div_ant_conf.main_lna_conf = | ||
1474 | ATH_ANT_DIV_COMB_LNA1; | ||
1475 | div_ant_conf.alt_lna_conf = | ||
1476 | ATH_ANT_DIV_COMB_LNA2; | ||
1477 | } | ||
1478 | |||
1479 | goto div_comb_done; | ||
1480 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
1481 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
1482 | /* Set alt to another LNA */ | ||
1483 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
1484 | div_ant_conf.alt_lna_conf = | ||
1485 | ATH_ANT_DIV_COMB_LNA1; | ||
1486 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
1487 | div_ant_conf.alt_lna_conf = | ||
1488 | ATH_ANT_DIV_COMB_LNA2; | ||
1489 | |||
1490 | goto div_comb_done; | ||
1491 | } | ||
1492 | |||
1493 | if ((alt_rssi_avg < (main_rssi_avg + | ||
1494 | ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) | ||
1495 | goto div_comb_done; | ||
1496 | } | ||
1497 | |||
1498 | if (!antcomb->scan_not_start) { | ||
1499 | switch (curr_alt_set) { | ||
1500 | case ATH_ANT_DIV_COMB_LNA2: | ||
1501 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1502 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1503 | antcomb->scan = true; | ||
1504 | /* set to A+B */ | ||
1505 | div_ant_conf.main_lna_conf = | ||
1506 | ATH_ANT_DIV_COMB_LNA1; | ||
1507 | div_ant_conf.alt_lna_conf = | ||
1508 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1509 | break; | ||
1510 | case ATH_ANT_DIV_COMB_LNA1: | ||
1511 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1512 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1513 | antcomb->scan = true; | ||
1514 | /* set to A+B */ | ||
1515 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1516 | div_ant_conf.alt_lna_conf = | ||
1517 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1518 | break; | ||
1519 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
1520 | antcomb->rssi_add = alt_rssi_avg; | ||
1521 | antcomb->scan = true; | ||
1522 | /* set to A-B */ | ||
1523 | div_ant_conf.alt_lna_conf = | ||
1524 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1525 | break; | ||
1526 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
1527 | antcomb->rssi_sub = alt_rssi_avg; | ||
1528 | antcomb->scan = false; | ||
1529 | if (antcomb->rssi_lna2 > | ||
1530 | (antcomb->rssi_lna1 + | ||
1531 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
1532 | /* use LNA2 as main LNA */ | ||
1533 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
1534 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1535 | /* set to A+B */ | ||
1536 | div_ant_conf.main_lna_conf = | ||
1537 | ATH_ANT_DIV_COMB_LNA2; | ||
1538 | div_ant_conf.alt_lna_conf = | ||
1539 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1540 | } else if (antcomb->rssi_sub > | ||
1541 | antcomb->rssi_lna1) { | ||
1542 | /* set to A-B */ | ||
1543 | div_ant_conf.main_lna_conf = | ||
1544 | ATH_ANT_DIV_COMB_LNA2; | ||
1545 | div_ant_conf.alt_lna_conf = | ||
1546 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1547 | } else { | ||
1548 | /* set to LNA1 */ | ||
1549 | div_ant_conf.main_lna_conf = | ||
1550 | ATH_ANT_DIV_COMB_LNA2; | ||
1551 | div_ant_conf.alt_lna_conf = | ||
1552 | ATH_ANT_DIV_COMB_LNA1; | ||
1553 | } | ||
1554 | } else { | ||
1555 | /* use LNA1 as main LNA */ | ||
1556 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
1557 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1558 | /* set to A+B */ | ||
1559 | div_ant_conf.main_lna_conf = | ||
1560 | ATH_ANT_DIV_COMB_LNA1; | ||
1561 | div_ant_conf.alt_lna_conf = | ||
1562 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1563 | } else if (antcomb->rssi_sub > | ||
1564 | antcomb->rssi_lna1) { | ||
1565 | /* set to A-B */ | ||
1566 | div_ant_conf.main_lna_conf = | ||
1567 | ATH_ANT_DIV_COMB_LNA1; | ||
1568 | div_ant_conf.alt_lna_conf = | ||
1569 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1570 | } else { | ||
1571 | /* set to LNA2 */ | ||
1572 | div_ant_conf.main_lna_conf = | ||
1573 | ATH_ANT_DIV_COMB_LNA1; | ||
1574 | div_ant_conf.alt_lna_conf = | ||
1575 | ATH_ANT_DIV_COMB_LNA2; | ||
1576 | } | ||
1577 | } | ||
1578 | break; | ||
1579 | default: | ||
1580 | break; | ||
1581 | } | ||
1582 | } else { | ||
1583 | if (!antcomb->alt_good) { | ||
1584 | antcomb->scan_not_start = false; | ||
1585 | /* Set alt to another LNA */ | ||
1586 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1587 | div_ant_conf.main_lna_conf = | ||
1588 | ATH_ANT_DIV_COMB_LNA2; | ||
1589 | div_ant_conf.alt_lna_conf = | ||
1590 | ATH_ANT_DIV_COMB_LNA1; | ||
1591 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1592 | div_ant_conf.main_lna_conf = | ||
1593 | ATH_ANT_DIV_COMB_LNA1; | ||
1594 | div_ant_conf.alt_lna_conf = | ||
1595 | ATH_ANT_DIV_COMB_LNA2; | ||
1596 | } | ||
1597 | goto div_comb_done; | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
1602 | main_rssi_avg, alt_rssi_avg, | ||
1603 | alt_ratio); | ||
1604 | |||
1605 | antcomb->quick_scan_cnt++; | ||
1606 | |||
1607 | div_comb_done: | ||
1608 | ath_ant_div_conf_fast_divbias(&div_ant_conf); | ||
1609 | |||
1610 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
1611 | |||
1612 | antcomb->scan_start_time = jiffies; | ||
1613 | antcomb->total_pkt_count = 0; | ||
1614 | antcomb->main_total_rssi = 0; | ||
1615 | antcomb->alt_total_rssi = 0; | ||
1616 | antcomb->main_recv_cnt = 0; | ||
1617 | antcomb->alt_recv_cnt = 0; | ||
1618 | } | ||
1619 | |||
1079 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1620 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1080 | { | 1621 | { |
1081 | struct ath_buf *bf; | 1622 | struct ath_buf *bf; |
@@ -1099,6 +1640,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1099 | u8 rx_status_len = ah->caps.rx_status_len; | 1640 | u8 rx_status_len = ah->caps.rx_status_len; |
1100 | u64 tsf = 0; | 1641 | u64 tsf = 0; |
1101 | u32 tsf_lower = 0; | 1642 | u32 tsf_lower = 0; |
1643 | unsigned long flags; | ||
1102 | 1644 | ||
1103 | if (edma) | 1645 | if (edma) |
1104 | dma_type = DMA_BIDIRECTIONAL; | 1646 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1207,11 +1749,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1207 | sc->rx.rxotherant = 0; | 1749 | sc->rx.rxotherant = 0; |
1208 | } | 1750 | } |
1209 | 1751 | ||
1752 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1210 | if (unlikely(ath9k_check_auto_sleep(sc) || | 1753 | if (unlikely(ath9k_check_auto_sleep(sc) || |
1211 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1754 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1212 | PS_WAIT_FOR_CAB | | 1755 | PS_WAIT_FOR_CAB | |
1213 | PS_WAIT_FOR_PSPOLL_DATA)))) | 1756 | PS_WAIT_FOR_PSPOLL_DATA)))) |
1214 | ath_rx_ps(sc, skb); | 1757 | ath_rx_ps(sc, skb); |
1758 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1759 | |||
1760 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | ||
1761 | ath_ant_comb_scan(sc, &rs); | ||
1215 | 1762 | ||
1216 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1763 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
1217 | 1764 | ||
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index fd20241f57d8..ec7cf5ee56bc 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -19,45 +19,36 @@ | |||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | 20 | ||
21 | struct ath9k_vif_iter_data { | 21 | struct ath9k_vif_iter_data { |
22 | int count; | 22 | const u8 *hw_macaddr; |
23 | u8 *addr; | 23 | u8 mask[ETH_ALEN]; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
27 | { | 27 | { |
28 | struct ath9k_vif_iter_data *iter_data = data; | 28 | struct ath9k_vif_iter_data *iter_data = data; |
29 | u8 *nbuf; | 29 | int i; |
30 | |||
31 | nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, | ||
32 | GFP_ATOMIC); | ||
33 | if (nbuf == NULL) | ||
34 | return; | ||
35 | 30 | ||
36 | memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); | 31 | for (i = 0; i < ETH_ALEN; i++) |
37 | iter_data->addr = nbuf; | 32 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); |
38 | iter_data->count++; | ||
39 | } | 33 | } |
40 | 34 | ||
41 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | 35 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
42 | { | 36 | { |
43 | struct ath_wiphy *aphy = hw->priv; | 37 | struct ath_wiphy *aphy = hw->priv; |
44 | struct ath_softc *sc = aphy->sc; | 38 | struct ath_softc *sc = aphy->sc; |
45 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 39 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
46 | struct ath9k_vif_iter_data iter_data; | 40 | struct ath9k_vif_iter_data iter_data; |
47 | int i, j; | 41 | int i; |
48 | u8 mask[ETH_ALEN]; | ||
49 | 42 | ||
50 | /* | 43 | /* |
51 | * Add primary MAC address even if it is not in active use since it | 44 | * Use the hardware MAC address as reference, the hardware uses it |
52 | * will be configured to the hardware as the starting point and the | 45 | * together with the BSSID mask when matching addresses. |
53 | * BSSID mask will need to be changed if another address is active. | ||
54 | */ | 46 | */ |
55 | iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); | 47 | iter_data.hw_macaddr = common->macaddr; |
56 | if (iter_data.addr) { | 48 | memset(&iter_data.mask, 0xff, ETH_ALEN); |
57 | memcpy(iter_data.addr, common->macaddr, ETH_ALEN); | 49 | |
58 | iter_data.count = 1; | 50 | if (vif) |
59 | } else | 51 | ath9k_vif_iter(&iter_data, vif->addr, vif); |
60 | iter_data.count = 0; | ||
61 | 52 | ||
62 | /* Get list of all active MAC addresses */ | 53 | /* Get list of all active MAC addresses */ |
63 | spin_lock_bh(&sc->wiphy_lock); | 54 | spin_lock_bh(&sc->wiphy_lock); |
@@ -71,31 +62,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | |||
71 | } | 62 | } |
72 | spin_unlock_bh(&sc->wiphy_lock); | 63 | spin_unlock_bh(&sc->wiphy_lock); |
73 | 64 | ||
74 | /* Generate an address mask to cover all active addresses */ | 65 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
75 | memset(mask, 0, ETH_ALEN); | ||
76 | for (i = 0; i < iter_data.count; i++) { | ||
77 | u8 *a1 = iter_data.addr + i * ETH_ALEN; | ||
78 | for (j = i + 1; j < iter_data.count; j++) { | ||
79 | u8 *a2 = iter_data.addr + j * ETH_ALEN; | ||
80 | mask[0] |= a1[0] ^ a2[0]; | ||
81 | mask[1] |= a1[1] ^ a2[1]; | ||
82 | mask[2] |= a1[2] ^ a2[2]; | ||
83 | mask[3] |= a1[3] ^ a2[3]; | ||
84 | mask[4] |= a1[4] ^ a2[4]; | ||
85 | mask[5] |= a1[5] ^ a2[5]; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | kfree(iter_data.addr); | ||
90 | |||
91 | /* Invert the mask and configure hardware */ | ||
92 | common->bssidmask[0] = ~mask[0]; | ||
93 | common->bssidmask[1] = ~mask[1]; | ||
94 | common->bssidmask[2] = ~mask[2]; | ||
95 | common->bssidmask[3] = ~mask[3]; | ||
96 | common->bssidmask[4] = ~mask[4]; | ||
97 | common->bssidmask[5] = ~mask[5]; | ||
98 | |||
99 | ath_hw_setbssidmask(common); | 66 | ath_hw_setbssidmask(common); |
100 | } | 67 | } |
101 | 68 | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 45fe9cac7971..93a8bda09c25 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -124,55 +124,11 @@ void ath9k_wmi_tasklet(unsigned long data) | |||
124 | { | 124 | { |
125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
126 | struct ath_common *common = ath9k_hw_common(priv->ah); | 126 | struct ath_common *common = ath9k_hw_common(priv->ah); |
127 | struct wmi_cmd_hdr *hdr; | ||
128 | struct wmi_swba *swba_hdr; | ||
129 | enum wmi_event_id event; | ||
130 | struct sk_buff *skb; | ||
131 | void *wmi_event; | ||
132 | unsigned long flags; | ||
133 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
134 | __be32 txrate; | ||
135 | #endif | ||
136 | 127 | ||
137 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); | 128 | ath_print(common, ATH_DBG_WMI, "SWBA Event received\n"); |
138 | skb = priv->wmi->wmi_skb; | ||
139 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); | ||
140 | 129 | ||
141 | hdr = (struct wmi_cmd_hdr *) skb->data; | 130 | ath9k_htc_swba(priv, priv->wmi->beacon_pending); |
142 | event = be16_to_cpu(hdr->command_id); | ||
143 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
144 | 131 | ||
145 | ath_print(common, ATH_DBG_WMI, | ||
146 | "WMI Event: 0x%x\n", event); | ||
147 | |||
148 | switch (event) { | ||
149 | case WMI_TGT_RDY_EVENTID: | ||
150 | break; | ||
151 | case WMI_SWBA_EVENTID: | ||
152 | swba_hdr = (struct wmi_swba *) wmi_event; | ||
153 | ath9k_htc_swba(priv, swba_hdr->beacon_pending); | ||
154 | break; | ||
155 | case WMI_FATAL_EVENTID: | ||
156 | break; | ||
157 | case WMI_TXTO_EVENTID: | ||
158 | break; | ||
159 | case WMI_BMISS_EVENTID: | ||
160 | break; | ||
161 | case WMI_WLAN_TXCOMP_EVENTID: | ||
162 | break; | ||
163 | case WMI_DELBA_EVENTID: | ||
164 | break; | ||
165 | case WMI_TXRATE_EVENTID: | ||
166 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
167 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
168 | priv->debug.txrate = be32_to_cpu(txrate); | ||
169 | #endif | ||
170 | break; | ||
171 | default: | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | kfree_skb(skb); | ||
176 | } | 132 | } |
177 | 133 | ||
178 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) | 134 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) |
@@ -191,6 +147,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
191 | struct wmi *wmi = (struct wmi *) priv; | 147 | struct wmi *wmi = (struct wmi *) priv; |
192 | struct wmi_cmd_hdr *hdr; | 148 | struct wmi_cmd_hdr *hdr; |
193 | u16 cmd_id; | 149 | u16 cmd_id; |
150 | void *wmi_event; | ||
151 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
152 | __be32 txrate; | ||
153 | #endif | ||
194 | 154 | ||
195 | if (unlikely(wmi->stopped)) | 155 | if (unlikely(wmi->stopped)) |
196 | goto free_skb; | 156 | goto free_skb; |
@@ -199,10 +159,22 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
199 | cmd_id = be16_to_cpu(hdr->command_id); | 159 | cmd_id = be16_to_cpu(hdr->command_id); |
200 | 160 | ||
201 | if (cmd_id & 0x1000) { | 161 | if (cmd_id & 0x1000) { |
202 | spin_lock(&wmi->wmi_lock); | 162 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); |
203 | wmi->wmi_skb = skb; | 163 | switch (cmd_id) { |
204 | spin_unlock(&wmi->wmi_lock); | 164 | case WMI_SWBA_EVENTID: |
205 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | 165 | wmi->beacon_pending = *(u8 *)wmi_event; |
166 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | ||
167 | break; | ||
168 | case WMI_TXRATE_EVENTID: | ||
169 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
170 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
171 | wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); | ||
172 | #endif | ||
173 | break; | ||
174 | default: | ||
175 | break; | ||
176 | } | ||
177 | kfree_skb(skb); | ||
206 | return; | 178 | return; |
207 | } | 179 | } |
208 | 180 | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index a0bf857625df..ac61074af8ac 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -31,10 +31,6 @@ struct wmi_cmd_hdr { | |||
31 | __be16 seq_no; | 31 | __be16 seq_no; |
32 | } __packed; | 32 | } __packed; |
33 | 33 | ||
34 | struct wmi_swba { | ||
35 | u8 beacon_pending; | ||
36 | } __packed; | ||
37 | |||
38 | enum wmi_cmd_id { | 34 | enum wmi_cmd_id { |
39 | WMI_ECHO_CMDID = 0x0001, | 35 | WMI_ECHO_CMDID = 0x0001, |
40 | WMI_ACCESS_MEMORY_CMDID, | 36 | WMI_ACCESS_MEMORY_CMDID, |
@@ -104,7 +100,7 @@ struct wmi { | |||
104 | u32 cmd_rsp_len; | 100 | u32 cmd_rsp_len; |
105 | bool stopped; | 101 | bool stopped; |
106 | 102 | ||
107 | struct sk_buff *wmi_skb; | 103 | u8 beacon_pending; |
108 | spinlock_t wmi_lock; | 104 | spinlock_t wmi_lock; |
109 | 105 | ||
110 | atomic_t mwrite_cnt; | 106 | atomic_t mwrite_cnt; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 457f07692ac7..85a7323a04ef 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
61 | struct ath_tx_status *ts, int txok); | 61 | struct ath_tx_status *ts, int txok); |
62 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | 62 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
63 | int nbad, int txok, bool update_rc); | 63 | int nbad, int txok, bool update_rc); |
64 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | ||
65 | int seqno); | ||
64 | 66 | ||
65 | enum { | 67 | enum { |
66 | MCS_HT20, | 68 | MCS_HT20, |
@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
143 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 145 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; |
144 | struct ath_buf *bf; | 146 | struct ath_buf *bf; |
145 | struct list_head bf_head; | 147 | struct list_head bf_head; |
146 | INIT_LIST_HEAD(&bf_head); | 148 | struct ath_tx_status ts; |
147 | 149 | ||
148 | WARN_ON(!tid->paused); | 150 | INIT_LIST_HEAD(&bf_head); |
149 | 151 | ||
152 | memset(&ts, 0, sizeof(ts)); | ||
150 | spin_lock_bh(&txq->axq_lock); | 153 | spin_lock_bh(&txq->axq_lock); |
151 | tid->paused = false; | ||
152 | 154 | ||
153 | while (!list_empty(&tid->buf_q)) { | 155 | while (!list_empty(&tid->buf_q)) { |
154 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 156 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
155 | BUG_ON(bf_isretried(bf)); | ||
156 | list_move_tail(&bf->list, &bf_head); | 157 | list_move_tail(&bf->list, &bf_head); |
157 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | 158 | |
159 | if (bf_isretried(bf)) { | ||
160 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | ||
161 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
162 | } else { | ||
163 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | ||
164 | } | ||
158 | } | 165 | } |
159 | 166 | ||
160 | spin_unlock_bh(&txq->axq_lock); | 167 | spin_unlock_bh(&txq->axq_lock); |
@@ -168,9 +175,9 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
168 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 175 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
169 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 176 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
170 | 177 | ||
171 | tid->tx_buf[cindex] = NULL; | 178 | __clear_bit(cindex, tid->tx_buf); |
172 | 179 | ||
173 | while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { | 180 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
174 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 181 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
175 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 182 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
176 | } | 183 | } |
@@ -186,9 +193,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
186 | 193 | ||
187 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | 194 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); |
188 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 195 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
189 | 196 | __set_bit(cindex, tid->tx_buf); | |
190 | BUG_ON(tid->tx_buf[cindex] != NULL); | ||
191 | tid->tx_buf[cindex] = bf; | ||
192 | 197 | ||
193 | if (index >= ((tid->baw_tail - tid->baw_head) & | 198 | if (index >= ((tid->baw_tail - tid->baw_head) & |
194 | (ATH_TID_MAX_BUFS - 1))) { | 199 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -431,7 +436,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
431 | list_move_tail(&bf->list, &bf_head); | 436 | list_move_tail(&bf->list, &bf_head); |
432 | } | 437 | } |
433 | 438 | ||
434 | if (!txpending) { | 439 | if (!txpending || (tid->state & AGGR_CLEANUP)) { |
435 | /* | 440 | /* |
436 | * complete the acked-ones/xretried ones; update | 441 | * complete the acked-ones/xretried ones; update |
437 | * block-ack window | 442 | * block-ack window |
@@ -510,15 +515,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
510 | } | 515 | } |
511 | 516 | ||
512 | if (tid->state & AGGR_CLEANUP) { | 517 | if (tid->state & AGGR_CLEANUP) { |
518 | ath_tx_flush_tid(sc, tid); | ||
519 | |||
513 | if (tid->baw_head == tid->baw_tail) { | 520 | if (tid->baw_head == tid->baw_tail) { |
514 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 521 | tid->state &= ~AGGR_ADDBA_COMPLETE; |
515 | tid->state &= ~AGGR_CLEANUP; | 522 | tid->state &= ~AGGR_CLEANUP; |
516 | |||
517 | /* send buffered frames as singles */ | ||
518 | ath_tx_flush_tid(sc, tid); | ||
519 | } | 523 | } |
520 | rcu_read_unlock(); | ||
521 | return; | ||
522 | } | 524 | } |
523 | 525 | ||
524 | rcu_read_unlock(); | 526 | rcu_read_unlock(); |
@@ -785,17 +787,23 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
785 | status != ATH_AGGR_BAW_CLOSED); | 787 | status != ATH_AGGR_BAW_CLOSED); |
786 | } | 788 | } |
787 | 789 | ||
788 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 790 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
789 | u16 tid, u16 *ssn) | 791 | u16 tid, u16 *ssn) |
790 | { | 792 | { |
791 | struct ath_atx_tid *txtid; | 793 | struct ath_atx_tid *txtid; |
792 | struct ath_node *an; | 794 | struct ath_node *an; |
793 | 795 | ||
794 | an = (struct ath_node *)sta->drv_priv; | 796 | an = (struct ath_node *)sta->drv_priv; |
795 | txtid = ATH_AN_2_TID(an, tid); | 797 | txtid = ATH_AN_2_TID(an, tid); |
798 | |||
799 | if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) | ||
800 | return -EAGAIN; | ||
801 | |||
796 | txtid->state |= AGGR_ADDBA_PROGRESS; | 802 | txtid->state |= AGGR_ADDBA_PROGRESS; |
797 | txtid->paused = true; | 803 | txtid->paused = true; |
798 | *ssn = txtid->seq_start; | 804 | *ssn = txtid->seq_start; |
805 | |||
806 | return 0; | ||
799 | } | 807 | } |
800 | 808 | ||
801 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 809 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
@@ -803,12 +811,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
803 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 811 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
804 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 812 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
805 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; | 813 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; |
806 | struct ath_tx_status ts; | ||
807 | struct ath_buf *bf; | ||
808 | struct list_head bf_head; | ||
809 | |||
810 | memset(&ts, 0, sizeof(ts)); | ||
811 | INIT_LIST_HEAD(&bf_head); | ||
812 | 814 | ||
813 | if (txtid->state & AGGR_CLEANUP) | 815 | if (txtid->state & AGGR_CLEANUP) |
814 | return; | 816 | return; |
@@ -818,31 +820,22 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
818 | return; | 820 | return; |
819 | } | 821 | } |
820 | 822 | ||
821 | /* drop all software retried frames and mark this TID */ | ||
822 | spin_lock_bh(&txq->axq_lock); | 823 | spin_lock_bh(&txq->axq_lock); |
823 | txtid->paused = true; | 824 | txtid->paused = true; |
824 | while (!list_empty(&txtid->buf_q)) { | ||
825 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | ||
826 | if (!bf_isretried(bf)) { | ||
827 | /* | ||
828 | * NB: it's based on the assumption that | ||
829 | * software retried frame will always stay | ||
830 | * at the head of software queue. | ||
831 | */ | ||
832 | break; | ||
833 | } | ||
834 | list_move_tail(&bf->list, &bf_head); | ||
835 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | ||
836 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
837 | } | ||
838 | spin_unlock_bh(&txq->axq_lock); | ||
839 | 825 | ||
840 | if (txtid->baw_head != txtid->baw_tail) { | 826 | /* |
827 | * If frames are still being transmitted for this TID, they will be | ||
828 | * cleaned up during tx completion. To prevent race conditions, this | ||
829 | * TID can only be reused after all in-progress subframes have been | ||
830 | * completed. | ||
831 | */ | ||
832 | if (txtid->baw_head != txtid->baw_tail) | ||
841 | txtid->state |= AGGR_CLEANUP; | 833 | txtid->state |= AGGR_CLEANUP; |
842 | } else { | 834 | else |
843 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 835 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
844 | ath_tx_flush_tid(sc, txtid); | 836 | spin_unlock_bh(&txq->axq_lock); |
845 | } | 837 | |
838 | ath_tx_flush_tid(sc, txtid); | ||
846 | } | 839 | } |
847 | 840 | ||
848 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 841 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
@@ -862,20 +855,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
862 | } | 855 | } |
863 | } | 856 | } |
864 | 857 | ||
865 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) | ||
866 | { | ||
867 | struct ath_atx_tid *txtid; | ||
868 | |||
869 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
870 | return false; | ||
871 | |||
872 | txtid = ATH_AN_2_TID(an, tidno); | ||
873 | |||
874 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
875 | return true; | ||
876 | return false; | ||
877 | } | ||
878 | |||
879 | /********************/ | 858 | /********************/ |
880 | /* Queue Management */ | 859 | /* Queue Management */ |
881 | /********************/ | 860 | /********************/ |
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig new file mode 100644 index 000000000000..c5d3a3f2e55b --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/Kconfig | |||
@@ -0,0 +1,41 @@ | |||
1 | config CARL9170 | ||
2 | tristate "Linux Community AR9170 802.11n USB support" | ||
3 | depends on USB && MAC80211 && EXPERIMENTAL | ||
4 | select FW_LOADER | ||
5 | select CRC32 | ||
6 | help | ||
7 | This is another driver for the Atheros "otus" 802.11n USB devices. | ||
8 | |||
9 | This driver provides more features than the original, | ||
10 | but it needs a special firmware (carl9170-1.fw) to do that. | ||
11 | |||
12 | The firmware can be downloaded from our wiki here: | ||
13 | http://wireless.kernel.org/en/users/Drivers/carl9170 | ||
14 | |||
15 | If you choose to build a module, it'll be called carl9170. | ||
16 | |||
17 | config CARL9170_LEDS | ||
18 | bool "SoftLED Support" | ||
19 | depends on CARL9170 | ||
20 | select MAC80211_LEDS | ||
21 | select LEDS_CLASS | ||
22 | select NEW_LEDS | ||
23 | default y | ||
24 | help | ||
25 | This option is necessary, if you want your device' LEDs to blink | ||
26 | |||
27 | Say Y, unless you need the LEDs for firmware debugging. | ||
28 | |||
29 | config CARL9170_DEBUGFS | ||
30 | bool "DebugFS Support" | ||
31 | depends on CARL9170 && DEBUG_FS && MAC80211_DEBUGFS | ||
32 | default n | ||
33 | help | ||
34 | Export several driver and device internals to user space. | ||
35 | |||
36 | Say N. | ||
37 | |||
38 | config CARL9170_WPC | ||
39 | bool | ||
40 | depends on CARL9170 && (INPUT = y || INPUT = CARL9170) | ||
41 | default y | ||
diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile new file mode 100644 index 000000000000..f64ed76af8ad --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o | ||
2 | carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o | ||
3 | |||
4 | obj-$(CONFIG_CARL9170) += carl9170.o | ||
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h new file mode 100644 index 000000000000..d7c5482d74ce --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -0,0 +1,627 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Driver specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | #ifndef __CARL9170_H | ||
40 | #define __CARL9170_H | ||
41 | |||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/completion.h> | ||
45 | #include <linux/spinlock.h> | ||
46 | #include <net/cfg80211.h> | ||
47 | #include <net/mac80211.h> | ||
48 | #include <linux/usb.h> | ||
49 | #ifdef CONFIG_CARL9170_LEDS | ||
50 | #include <linux/leds.h> | ||
51 | #endif /* CONFIG_CARL170_LEDS */ | ||
52 | #ifdef CONFIG_CARL9170_WPC | ||
53 | #include <linux/input.h> | ||
54 | #endif /* CONFIG_CARL9170_WPC */ | ||
55 | #include "eeprom.h" | ||
56 | #include "wlan.h" | ||
57 | #include "hw.h" | ||
58 | #include "fwdesc.h" | ||
59 | #include "fwcmd.h" | ||
60 | #include "../regd.h" | ||
61 | |||
62 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
63 | #include "debug.h" | ||
64 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
65 | |||
66 | #define CARL9170FW_NAME "carl9170-1.fw" | ||
67 | |||
68 | #define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1) | ||
69 | |||
70 | enum carl9170_rf_init_mode { | ||
71 | CARL9170_RFI_NONE, | ||
72 | CARL9170_RFI_WARM, | ||
73 | CARL9170_RFI_COLD, | ||
74 | }; | ||
75 | |||
76 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 | ||
77 | |||
78 | enum carl9170_device_state { | ||
79 | CARL9170_UNKNOWN_STATE, | ||
80 | CARL9170_STOPPED, | ||
81 | CARL9170_IDLE, | ||
82 | CARL9170_STARTED, | ||
83 | }; | ||
84 | |||
85 | #define CARL9170_NUM_TID 16 | ||
86 | #define WME_BA_BMP_SIZE 64 | ||
87 | #define CARL9170_TX_USER_RATE_TRIES 3 | ||
88 | |||
89 | #define WME_AC_BE 2 | ||
90 | #define WME_AC_BK 3 | ||
91 | #define WME_AC_VI 1 | ||
92 | #define WME_AC_VO 0 | ||
93 | |||
94 | #define TID_TO_WME_AC(_tid) \ | ||
95 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
96 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
97 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
98 | WME_AC_VO) | ||
99 | |||
100 | #define SEQ_DIFF(_start, _seq) \ | ||
101 | (((_start) - (_seq)) & 0x0fff) | ||
102 | #define SEQ_PREV(_seq) \ | ||
103 | (((_seq) - 1) & 0x0fff) | ||
104 | #define SEQ_NEXT(_seq) \ | ||
105 | (((_seq) + 1) & 0x0fff) | ||
106 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
107 | ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) | ||
108 | |||
109 | enum carl9170_tid_state { | ||
110 | CARL9170_TID_STATE_INVALID, | ||
111 | CARL9170_TID_STATE_KILLED, | ||
112 | CARL9170_TID_STATE_SHUTDOWN, | ||
113 | CARL9170_TID_STATE_SUSPEND, | ||
114 | CARL9170_TID_STATE_PROGRESS, | ||
115 | CARL9170_TID_STATE_IDLE, | ||
116 | CARL9170_TID_STATE_XMIT, | ||
117 | }; | ||
118 | |||
119 | #define CARL9170_BAW_BITS (2 * WME_BA_BMP_SIZE) | ||
120 | #define CARL9170_BAW_SIZE (BITS_TO_LONGS(CARL9170_BAW_BITS)) | ||
121 | #define CARL9170_BAW_LEN (DIV_ROUND_UP(CARL9170_BAW_BITS, BITS_PER_BYTE)) | ||
122 | |||
123 | struct carl9170_sta_tid { | ||
124 | /* must be the first entry! */ | ||
125 | struct list_head list; | ||
126 | |||
127 | /* temporary list for RCU unlink procedure */ | ||
128 | struct list_head tmp_list; | ||
129 | |||
130 | /* lock for the following data structures */ | ||
131 | spinlock_t lock; | ||
132 | |||
133 | unsigned int counter; | ||
134 | enum carl9170_tid_state state; | ||
135 | u8 tid; /* TID number ( 0 - 15 ) */ | ||
136 | u16 max; /* max. AMPDU size */ | ||
137 | |||
138 | u16 snx; /* awaiting _next_ frame */ | ||
139 | u16 hsn; /* highest _queued_ sequence */ | ||
140 | u16 bsn; /* base of the tx/agg bitmap */ | ||
141 | unsigned long bitmap[CARL9170_BAW_SIZE]; | ||
142 | |||
143 | /* Preaggregation reorder queue */ | ||
144 | struct sk_buff_head queue; | ||
145 | }; | ||
146 | |||
147 | #define CARL9170_QUEUE_TIMEOUT 256 | ||
148 | #define CARL9170_BUMP_QUEUE 1000 | ||
149 | #define CARL9170_TX_TIMEOUT 2500 | ||
150 | #define CARL9170_JANITOR_DELAY 128 | ||
151 | #define CARL9170_QUEUE_STUCK_TIMEOUT 5500 | ||
152 | |||
153 | #define CARL9170_NUM_TX_AGG_MAX 30 | ||
154 | |||
155 | /* | ||
156 | * Tradeoff between stability/latency and speed. | ||
157 | * | ||
158 | * AR9170_TXQ_DEPTH is devised by dividing the amount of available | ||
159 | * tx buffers with the size of a full ethernet frame + overhead. | ||
160 | * | ||
161 | * Naturally: The higher the limit, the faster the device CAN send. | ||
162 | * However, even a slight over-commitment at the wrong time and the | ||
163 | * hardware is doomed to send all already-queued frames at suboptimal | ||
164 | * rates. This in turn leads to an enourmous amount of unsuccessful | ||
165 | * retries => Latency goes up, whereas the throughput goes down. CRASH! | ||
166 | */ | ||
167 | #define CARL9170_NUM_TX_LIMIT_HARD ((AR9170_TXQ_DEPTH * 3) / 2) | ||
168 | #define CARL9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH) | ||
169 | |||
170 | struct carl9170_tx_queue_stats { | ||
171 | unsigned int count; | ||
172 | unsigned int limit; | ||
173 | unsigned int len; | ||
174 | }; | ||
175 | |||
176 | struct carl9170_vif { | ||
177 | unsigned int id; | ||
178 | struct ieee80211_vif *vif; | ||
179 | }; | ||
180 | |||
181 | struct carl9170_vif_info { | ||
182 | struct list_head list; | ||
183 | bool active; | ||
184 | unsigned int id; | ||
185 | struct sk_buff *beacon; | ||
186 | bool enable_beacon; | ||
187 | }; | ||
188 | |||
189 | #define AR9170_NUM_RX_URBS 16 | ||
190 | #define AR9170_NUM_RX_URBS_MUL 2 | ||
191 | #define AR9170_NUM_TX_URBS 8 | ||
192 | #define AR9170_NUM_RX_URBS_POOL (AR9170_NUM_RX_URBS_MUL * AR9170_NUM_RX_URBS) | ||
193 | |||
194 | enum carl9170_device_features { | ||
195 | CARL9170_WPS_BUTTON = BIT(0), | ||
196 | CARL9170_ONE_LED = BIT(1), | ||
197 | }; | ||
198 | |||
199 | #ifdef CONFIG_CARL9170_LEDS | ||
200 | struct ar9170; | ||
201 | |||
202 | struct carl9170_led { | ||
203 | struct ar9170 *ar; | ||
204 | struct led_classdev l; | ||
205 | char name[32]; | ||
206 | unsigned int toggled; | ||
207 | bool last_state; | ||
208 | bool registered; | ||
209 | }; | ||
210 | #endif /* CONFIG_CARL9170_LEDS */ | ||
211 | |||
212 | enum carl9170_restart_reasons { | ||
213 | CARL9170_RR_NO_REASON = 0, | ||
214 | CARL9170_RR_FATAL_FIRMWARE_ERROR, | ||
215 | CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS, | ||
216 | CARL9170_RR_WATCHDOG, | ||
217 | CARL9170_RR_STUCK_TX, | ||
218 | CARL9170_RR_SLOW_SYSTEM, | ||
219 | CARL9170_RR_COMMAND_TIMEOUT, | ||
220 | CARL9170_RR_TOO_MANY_PHY_ERRORS, | ||
221 | CARL9170_RR_LOST_RSP, | ||
222 | CARL9170_RR_INVALID_RSP, | ||
223 | CARL9170_RR_USER_REQUEST, | ||
224 | |||
225 | __CARL9170_RR_LAST, | ||
226 | }; | ||
227 | |||
228 | enum carl9170_erp_modes { | ||
229 | CARL9170_ERP_INVALID, | ||
230 | CARL9170_ERP_AUTO, | ||
231 | CARL9170_ERP_MAC80211, | ||
232 | CARL9170_ERP_OFF, | ||
233 | CARL9170_ERP_CTS, | ||
234 | CARL9170_ERP_RTS, | ||
235 | __CARL9170_ERP_NUM, | ||
236 | }; | ||
237 | |||
238 | struct ar9170 { | ||
239 | struct ath_common common; | ||
240 | struct ieee80211_hw *hw; | ||
241 | struct mutex mutex; | ||
242 | enum carl9170_device_state state; | ||
243 | spinlock_t state_lock; | ||
244 | enum carl9170_restart_reasons last_reason; | ||
245 | bool registered; | ||
246 | |||
247 | /* USB */ | ||
248 | struct usb_device *udev; | ||
249 | struct usb_interface *intf; | ||
250 | struct usb_anchor rx_anch; | ||
251 | struct usb_anchor rx_work; | ||
252 | struct usb_anchor rx_pool; | ||
253 | struct usb_anchor tx_wait; | ||
254 | struct usb_anchor tx_anch; | ||
255 | struct usb_anchor tx_cmd; | ||
256 | struct usb_anchor tx_err; | ||
257 | struct tasklet_struct usb_tasklet; | ||
258 | atomic_t tx_cmd_urbs; | ||
259 | atomic_t tx_anch_urbs; | ||
260 | atomic_t rx_anch_urbs; | ||
261 | atomic_t rx_work_urbs; | ||
262 | atomic_t rx_pool_urbs; | ||
263 | kernel_ulong_t features; | ||
264 | |||
265 | /* firmware settings */ | ||
266 | struct completion fw_load_wait; | ||
267 | struct completion fw_boot_wait; | ||
268 | struct { | ||
269 | const struct carl9170fw_desc_head *desc; | ||
270 | const struct firmware *fw; | ||
271 | unsigned int offset; | ||
272 | unsigned int address; | ||
273 | unsigned int cmd_bufs; | ||
274 | unsigned int api_version; | ||
275 | unsigned int vif_num; | ||
276 | unsigned int err_counter; | ||
277 | unsigned int bug_counter; | ||
278 | u32 beacon_addr; | ||
279 | unsigned int beacon_max_len; | ||
280 | bool rx_stream; | ||
281 | bool tx_stream; | ||
282 | unsigned int mem_blocks; | ||
283 | unsigned int mem_block_size; | ||
284 | unsigned int rx_size; | ||
285 | } fw; | ||
286 | |||
287 | /* reset / stuck frames/queue detection */ | ||
288 | struct work_struct restart_work; | ||
289 | unsigned int restart_counter; | ||
290 | unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; | ||
291 | unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; | ||
292 | bool needs_full_reset; | ||
293 | atomic_t pending_restarts; | ||
294 | |||
295 | /* interface mode settings */ | ||
296 | struct list_head vif_list; | ||
297 | unsigned long vif_bitmap; | ||
298 | unsigned int vifs; | ||
299 | struct carl9170_vif vif_priv[AR9170_MAX_VIRTUAL_MAC]; | ||
300 | |||
301 | /* beaconing */ | ||
302 | spinlock_t beacon_lock; | ||
303 | unsigned int global_pretbtt; | ||
304 | unsigned int global_beacon_int; | ||
305 | struct carl9170_vif_info *beacon_iter; | ||
306 | unsigned int beacon_enabled; | ||
307 | |||
308 | /* cryptographic engine */ | ||
309 | u64 usedkeys; | ||
310 | bool rx_software_decryption; | ||
311 | bool disable_offload; | ||
312 | |||
313 | /* filter settings */ | ||
314 | u64 cur_mc_hash; | ||
315 | u32 cur_filter; | ||
316 | unsigned int filter_state; | ||
317 | bool sniffer_enabled; | ||
318 | |||
319 | /* MAC */ | ||
320 | enum carl9170_erp_modes erp_mode; | ||
321 | |||
322 | /* PHY */ | ||
323 | struct ieee80211_channel *channel; | ||
324 | int noise[4]; | ||
325 | unsigned int chan_fail; | ||
326 | unsigned int total_chan_fail; | ||
327 | u8 heavy_clip; | ||
328 | u8 ht_settings; | ||
329 | |||
330 | /* power calibration data */ | ||
331 | u8 power_5G_leg[4]; | ||
332 | u8 power_2G_cck[4]; | ||
333 | u8 power_2G_ofdm[4]; | ||
334 | u8 power_5G_ht20[8]; | ||
335 | u8 power_5G_ht40[8]; | ||
336 | u8 power_2G_ht20[8]; | ||
337 | u8 power_2G_ht40[8]; | ||
338 | |||
339 | #ifdef CONFIG_CARL9170_LEDS | ||
340 | /* LED */ | ||
341 | struct delayed_work led_work; | ||
342 | struct carl9170_led leds[AR9170_NUM_LEDS]; | ||
343 | #endif /* CONFIG_CARL9170_LEDS */ | ||
344 | |||
345 | /* qos queue settings */ | ||
346 | spinlock_t tx_stats_lock; | ||
347 | struct carl9170_tx_queue_stats tx_stats[__AR9170_NUM_TXQ]; | ||
348 | struct ieee80211_tx_queue_params edcf[5]; | ||
349 | struct completion tx_flush; | ||
350 | |||
351 | /* CMD */ | ||
352 | int cmd_seq; | ||
353 | int readlen; | ||
354 | u8 *readbuf; | ||
355 | spinlock_t cmd_lock; | ||
356 | struct completion cmd_wait; | ||
357 | union { | ||
358 | __le32 cmd_buf[PAYLOAD_MAX + 1]; | ||
359 | struct carl9170_cmd cmd; | ||
360 | struct carl9170_rsp rsp; | ||
361 | }; | ||
362 | |||
363 | /* statistics */ | ||
364 | unsigned int tx_dropped; | ||
365 | unsigned int tx_ack_failures; | ||
366 | unsigned int tx_fcs_errors; | ||
367 | unsigned int tx_ampdu_timeout; | ||
368 | unsigned int rx_dropped; | ||
369 | |||
370 | /* EEPROM */ | ||
371 | struct ar9170_eeprom eeprom; | ||
372 | |||
373 | /* tx queuing */ | ||
374 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | ||
375 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; | ||
376 | struct delayed_work tx_janitor; | ||
377 | unsigned long tx_janitor_last_run; | ||
378 | bool tx_schedule; | ||
379 | |||
380 | /* tx ampdu */ | ||
381 | struct work_struct ampdu_work; | ||
382 | spinlock_t tx_ampdu_list_lock; | ||
383 | struct carl9170_sta_tid *tx_ampdu_iter; | ||
384 | struct list_head tx_ampdu_list; | ||
385 | atomic_t tx_ampdu_upload; | ||
386 | atomic_t tx_ampdu_scheduler; | ||
387 | atomic_t tx_total_pending; | ||
388 | atomic_t tx_total_queued; | ||
389 | unsigned int tx_ampdu_list_len; | ||
390 | int current_density; | ||
391 | int current_factor; | ||
392 | bool tx_ampdu_schedule; | ||
393 | |||
394 | /* internal memory management */ | ||
395 | spinlock_t mem_lock; | ||
396 | unsigned long *mem_bitmap; | ||
397 | atomic_t mem_free_blocks; | ||
398 | atomic_t mem_allocs; | ||
399 | |||
400 | /* rxstream mpdu merge */ | ||
401 | struct ar9170_rx_head rx_plcp; | ||
402 | bool rx_has_plcp; | ||
403 | struct sk_buff *rx_failover; | ||
404 | int rx_failover_missing; | ||
405 | |||
406 | #ifdef CONFIG_CARL9170_WPC | ||
407 | struct { | ||
408 | bool pbc_state; | ||
409 | struct input_dev *pbc; | ||
410 | char name[32]; | ||
411 | char phys[32]; | ||
412 | } wps; | ||
413 | #endif /* CONFIG_CARL9170_WPC */ | ||
414 | |||
415 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
416 | struct carl9170_debug debug; | ||
417 | struct dentry *debug_dir; | ||
418 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
419 | |||
420 | /* PSM */ | ||
421 | struct work_struct ps_work; | ||
422 | struct { | ||
423 | unsigned int dtim_counter; | ||
424 | unsigned long last_beacon; | ||
425 | unsigned long last_action; | ||
426 | unsigned long last_slept; | ||
427 | unsigned int sleep_ms; | ||
428 | unsigned int off_override; | ||
429 | bool state; | ||
430 | } ps; | ||
431 | }; | ||
432 | |||
433 | enum carl9170_ps_off_override_reasons { | ||
434 | PS_OFF_VIF = BIT(0), | ||
435 | PS_OFF_BCN = BIT(1), | ||
436 | PS_OFF_5GHZ = BIT(2), | ||
437 | }; | ||
438 | |||
439 | struct carl9170_ba_stats { | ||
440 | u8 ampdu_len; | ||
441 | u8 ampdu_ack_len; | ||
442 | bool clear; | ||
443 | }; | ||
444 | |||
445 | struct carl9170_sta_info { | ||
446 | bool ht_sta; | ||
447 | unsigned int ampdu_max_len; | ||
448 | struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; | ||
449 | struct carl9170_ba_stats stats[CARL9170_NUM_TID]; | ||
450 | }; | ||
451 | |||
452 | struct carl9170_tx_info { | ||
453 | unsigned long timeout; | ||
454 | struct ar9170 *ar; | ||
455 | struct kref ref; | ||
456 | }; | ||
457 | |||
458 | #define CHK_DEV_STATE(a, s) (((struct ar9170 *)a)->state >= (s)) | ||
459 | #define IS_INITIALIZED(a) (CHK_DEV_STATE(a, CARL9170_STOPPED)) | ||
460 | #define IS_ACCEPTING_CMD(a) (CHK_DEV_STATE(a, CARL9170_IDLE)) | ||
461 | #define IS_STARTED(a) (CHK_DEV_STATE(a, CARL9170_STARTED)) | ||
462 | |||
463 | static inline void __carl9170_set_state(struct ar9170 *ar, | ||
464 | enum carl9170_device_state newstate) | ||
465 | { | ||
466 | ar->state = newstate; | ||
467 | } | ||
468 | |||
469 | static inline void carl9170_set_state(struct ar9170 *ar, | ||
470 | enum carl9170_device_state newstate) | ||
471 | { | ||
472 | unsigned long flags; | ||
473 | |||
474 | spin_lock_irqsave(&ar->state_lock, flags); | ||
475 | __carl9170_set_state(ar, newstate); | ||
476 | spin_unlock_irqrestore(&ar->state_lock, flags); | ||
477 | } | ||
478 | |||
479 | static inline void carl9170_set_state_when(struct ar9170 *ar, | ||
480 | enum carl9170_device_state min, enum carl9170_device_state newstate) | ||
481 | { | ||
482 | unsigned long flags; | ||
483 | |||
484 | spin_lock_irqsave(&ar->state_lock, flags); | ||
485 | if (CHK_DEV_STATE(ar, min)) | ||
486 | __carl9170_set_state(ar, newstate); | ||
487 | spin_unlock_irqrestore(&ar->state_lock, flags); | ||
488 | } | ||
489 | |||
490 | /* exported interface */ | ||
491 | void *carl9170_alloc(size_t priv_size); | ||
492 | int carl9170_register(struct ar9170 *ar); | ||
493 | void carl9170_unregister(struct ar9170 *ar); | ||
494 | void carl9170_free(struct ar9170 *ar); | ||
495 | void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r); | ||
496 | void carl9170_ps_check(struct ar9170 *ar); | ||
497 | |||
498 | /* USB back-end */ | ||
499 | int carl9170_usb_open(struct ar9170 *ar); | ||
500 | void carl9170_usb_stop(struct ar9170 *ar); | ||
501 | void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb); | ||
502 | void carl9170_usb_handle_tx_err(struct ar9170 *ar); | ||
503 | int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids, | ||
504 | u32 plen, void *payload, u32 rlen, void *resp); | ||
505 | int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, | ||
506 | const bool free_buf); | ||
507 | int carl9170_usb_restart(struct ar9170 *ar); | ||
508 | void carl9170_usb_reset(struct ar9170 *ar); | ||
509 | |||
510 | /* MAC */ | ||
511 | int carl9170_init_mac(struct ar9170 *ar); | ||
512 | int carl9170_set_qos(struct ar9170 *ar); | ||
513 | int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); | ||
514 | int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id, | ||
515 | const u8 *mac); | ||
516 | int carl9170_set_operating_mode(struct ar9170 *ar); | ||
517 | int carl9170_set_beacon_timers(struct ar9170 *ar); | ||
518 | int carl9170_set_dyn_sifs_ack(struct ar9170 *ar); | ||
519 | int carl9170_set_rts_cts_rate(struct ar9170 *ar); | ||
520 | int carl9170_set_ampdu_settings(struct ar9170 *ar); | ||
521 | int carl9170_set_slot_time(struct ar9170 *ar); | ||
522 | int carl9170_set_mac_rates(struct ar9170 *ar); | ||
523 | int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry); | ||
524 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit); | ||
525 | int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, | ||
526 | const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen); | ||
527 | int carl9170_disable_key(struct ar9170 *ar, const u8 id); | ||
528 | |||
529 | /* RX */ | ||
530 | void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len); | ||
531 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); | ||
532 | |||
533 | /* TX */ | ||
534 | int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
535 | void carl9170_tx_janitor(struct work_struct *work); | ||
536 | void carl9170_tx_process_status(struct ar9170 *ar, | ||
537 | const struct carl9170_rsp *cmd); | ||
538 | void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | ||
539 | const bool success); | ||
540 | void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); | ||
541 | void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb); | ||
542 | void carl9170_tx_scheduler(struct ar9170 *ar); | ||
543 | void carl9170_tx_get_skb(struct sk_buff *skb); | ||
544 | int carl9170_tx_put_skb(struct sk_buff *skb); | ||
545 | |||
546 | /* LEDs */ | ||
547 | #ifdef CONFIG_CARL9170_LEDS | ||
548 | int carl9170_led_register(struct ar9170 *ar); | ||
549 | void carl9170_led_unregister(struct ar9170 *ar); | ||
550 | #endif /* CONFIG_CARL9170_LEDS */ | ||
551 | int carl9170_led_init(struct ar9170 *ar); | ||
552 | int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state); | ||
553 | |||
554 | /* PHY / RF */ | ||
555 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
556 | enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi); | ||
557 | int carl9170_get_noisefloor(struct ar9170 *ar); | ||
558 | |||
559 | /* FW */ | ||
560 | int carl9170_parse_firmware(struct ar9170 *ar); | ||
561 | int carl9170_fw_fix_eeprom(struct ar9170 *ar); | ||
562 | |||
563 | extern struct ieee80211_rate __carl9170_ratetable[]; | ||
564 | extern int modparam_noht; | ||
565 | |||
566 | static inline struct ar9170 *carl9170_get_priv(struct carl9170_vif *carl_vif) | ||
567 | { | ||
568 | return container_of(carl_vif, struct ar9170, | ||
569 | vif_priv[carl_vif->id]); | ||
570 | } | ||
571 | |||
572 | static inline struct ieee80211_hdr *carl9170_get_hdr(struct sk_buff *skb) | ||
573 | { | ||
574 | return (void *)((struct _carl9170_tx_superframe *) | ||
575 | skb->data)->frame_data; | ||
576 | } | ||
577 | |||
578 | static inline u16 get_seq_h(struct ieee80211_hdr *hdr) | ||
579 | { | ||
580 | return le16_to_cpu(hdr->seq_ctrl) >> 4; | ||
581 | } | ||
582 | |||
583 | static inline u16 carl9170_get_seq(struct sk_buff *skb) | ||
584 | { | ||
585 | return get_seq_h(carl9170_get_hdr(skb)); | ||
586 | } | ||
587 | |||
588 | static inline u16 get_tid_h(struct ieee80211_hdr *hdr) | ||
589 | { | ||
590 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
591 | } | ||
592 | |||
593 | static inline u16 carl9170_get_tid(struct sk_buff *skb) | ||
594 | { | ||
595 | return get_tid_h(carl9170_get_hdr(skb)); | ||
596 | } | ||
597 | |||
598 | static inline struct ieee80211_vif * | ||
599 | carl9170_get_vif(struct carl9170_vif_info *priv) | ||
600 | { | ||
601 | return container_of((void *)priv, struct ieee80211_vif, drv_priv); | ||
602 | } | ||
603 | |||
604 | /* Protected by ar->mutex or RCU */ | ||
605 | static inline struct ieee80211_vif *carl9170_get_main_vif(struct ar9170 *ar) | ||
606 | { | ||
607 | struct carl9170_vif_info *cvif; | ||
608 | |||
609 | list_for_each_entry_rcu(cvif, &ar->vif_list, list) { | ||
610 | if (cvif->active) | ||
611 | return carl9170_get_vif(cvif); | ||
612 | } | ||
613 | |||
614 | return NULL; | ||
615 | } | ||
616 | |||
617 | static inline bool is_main_vif(struct ar9170 *ar, struct ieee80211_vif *vif) | ||
618 | { | ||
619 | bool ret; | ||
620 | |||
621 | rcu_read_lock(); | ||
622 | ret = (carl9170_get_main_vif(ar) == vif); | ||
623 | rcu_read_unlock(); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | #endif /* __CARL9170_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c new file mode 100644 index 000000000000..c21f3364bfec --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/cmd.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include "carl9170.h" | ||
40 | #include "cmd.h" | ||
41 | |||
42 | int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) | ||
43 | { | ||
44 | __le32 buf[2] = { | ||
45 | cpu_to_le32(reg), | ||
46 | cpu_to_le32(val), | ||
47 | }; | ||
48 | int err; | ||
49 | |||
50 | err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf), | ||
51 | (u8 *) buf, 0, NULL); | ||
52 | if (err) { | ||
53 | if (net_ratelimit()) { | ||
54 | wiphy_err(ar->hw->wiphy, "writing reg %#x " | ||
55 | "(val %#x) failed (%d)\n", reg, val, err); | ||
56 | } | ||
57 | } | ||
58 | return err; | ||
59 | } | ||
60 | |||
61 | int carl9170_read_mreg(struct ar9170 *ar, const int nregs, | ||
62 | const u32 *regs, u32 *out) | ||
63 | { | ||
64 | int i, err; | ||
65 | __le32 *offs, *res; | ||
66 | |||
67 | /* abuse "out" for the register offsets, must be same length */ | ||
68 | offs = (__le32 *)out; | ||
69 | for (i = 0; i < nregs; i++) | ||
70 | offs[i] = cpu_to_le32(regs[i]); | ||
71 | |||
72 | /* also use the same buffer for the input */ | ||
73 | res = (__le32 *)out; | ||
74 | |||
75 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, | ||
76 | 4 * nregs, (u8 *)offs, | ||
77 | 4 * nregs, (u8 *)res); | ||
78 | if (err) { | ||
79 | if (net_ratelimit()) { | ||
80 | wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n", | ||
81 | err); | ||
82 | } | ||
83 | return err; | ||
84 | } | ||
85 | |||
86 | /* convert result to cpu endian */ | ||
87 | for (i = 0; i < nregs; i++) | ||
88 | out[i] = le32_to_cpu(res[i]); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) | ||
94 | { | ||
95 | return carl9170_read_mreg(ar, 1, ®, val); | ||
96 | } | ||
97 | |||
98 | int carl9170_echo_test(struct ar9170 *ar, const u32 v) | ||
99 | { | ||
100 | u32 echores; | ||
101 | int err; | ||
102 | |||
103 | err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO, | ||
104 | 4, (u8 *)&v, | ||
105 | 4, (u8 *)&echores); | ||
106 | if (err) | ||
107 | return err; | ||
108 | |||
109 | if (v != echores) { | ||
110 | wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores); | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, | ||
118 | const enum carl9170_cmd_oids cmd, const unsigned int len) | ||
119 | { | ||
120 | struct carl9170_cmd *tmp; | ||
121 | |||
122 | tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC); | ||
123 | if (tmp) { | ||
124 | tmp->hdr.cmd = cmd; | ||
125 | tmp->hdr.len = len; | ||
126 | } | ||
127 | |||
128 | return tmp; | ||
129 | } | ||
130 | |||
131 | int carl9170_reboot(struct ar9170 *ar) | ||
132 | { | ||
133 | struct carl9170_cmd *cmd; | ||
134 | int err; | ||
135 | |||
136 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0); | ||
137 | if (!cmd) | ||
138 | return -ENOMEM; | ||
139 | |||
140 | err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true); | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | int carl9170_mac_reset(struct ar9170 *ar) | ||
145 | { | ||
146 | return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST, | ||
147 | 0, NULL, 0, NULL); | ||
148 | } | ||
149 | |||
150 | int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, | ||
151 | const u32 mode, const u32 addr, const u32 len) | ||
152 | { | ||
153 | struct carl9170_cmd *cmd; | ||
154 | |||
155 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC, | ||
156 | sizeof(struct carl9170_bcn_ctrl_cmd)); | ||
157 | if (!cmd) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id); | ||
161 | cmd->bcn_ctrl.mode = cpu_to_le32(mode); | ||
162 | cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr); | ||
163 | cmd->bcn_ctrl.bcn_len = cpu_to_le32(len); | ||
164 | |||
165 | return __carl9170_exec_cmd(ar, cmd, true); | ||
166 | } | ||
167 | |||
168 | int carl9170_powersave(struct ar9170 *ar, const bool ps) | ||
169 | { | ||
170 | struct carl9170_cmd *cmd; | ||
171 | u32 state; | ||
172 | |||
173 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC, | ||
174 | sizeof(struct carl9170_psm)); | ||
175 | if (!cmd) | ||
176 | return -ENOMEM; | ||
177 | |||
178 | if (ps) { | ||
179 | /* Sleep until next TBTT */ | ||
180 | state = CARL9170_PSM_SLEEP | 1; | ||
181 | } else { | ||
182 | /* wake up immediately */ | ||
183 | state = 1; | ||
184 | } | ||
185 | |||
186 | cmd->psm.state = cpu_to_le32(state); | ||
187 | return __carl9170_exec_cmd(ar, cmd, true); | ||
188 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h new file mode 100644 index 000000000000..0fc83d2336fd --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/cmd.h | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | #ifndef __CMD_H | ||
40 | #define __CMD_H | ||
41 | |||
42 | #include "carl9170.h" | ||
43 | |||
44 | /* basic HW access */ | ||
45 | int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); | ||
46 | int carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val); | ||
47 | int carl9170_read_mreg(struct ar9170 *ar, const int nregs, | ||
48 | const u32 *regs, u32 *out); | ||
49 | int carl9170_echo_test(struct ar9170 *ar, u32 v); | ||
50 | int carl9170_reboot(struct ar9170 *ar); | ||
51 | int carl9170_mac_reset(struct ar9170 *ar); | ||
52 | int carl9170_powersave(struct ar9170 *ar, const bool power_on); | ||
53 | int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, | ||
54 | const u32 mode, const u32 addr, const u32 len); | ||
55 | |||
56 | static inline int carl9170_flush_cab(struct ar9170 *ar, | ||
57 | const unsigned int vif_id) | ||
58 | { | ||
59 | return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); | ||
60 | } | ||
61 | |||
62 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, | ||
63 | const enum carl9170_cmd_oids cmd, const unsigned int len); | ||
64 | |||
65 | /* | ||
66 | * Macros to facilitate writing multiple registers in a single | ||
67 | * write-combining USB command. Note that when the first group | ||
68 | * fails the whole thing will fail without any others attempted, | ||
69 | * but you won't know which write in the group failed. | ||
70 | */ | ||
71 | #define carl9170_regwrite_begin(ar) \ | ||
72 | do { \ | ||
73 | int __nreg = 0, __err = 0; \ | ||
74 | struct ar9170 *__ar = ar; | ||
75 | |||
76 | #define carl9170_regwrite(r, v) do { \ | ||
77 | __ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \ | ||
78 | __ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \ | ||
79 | __nreg++; \ | ||
80 | if ((__nreg >= PAYLOAD_MAX/2)) { \ | ||
81 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
82 | __err = carl9170_exec_cmd(__ar, \ | ||
83 | CARL9170_CMD_WREG, 8 * __nreg, \ | ||
84 | (u8 *) &__ar->cmd_buf[1], 0, NULL); \ | ||
85 | else \ | ||
86 | goto __regwrite_out; \ | ||
87 | \ | ||
88 | __nreg = 0; \ | ||
89 | if (__err) \ | ||
90 | goto __regwrite_out; \ | ||
91 | } \ | ||
92 | } while (0) | ||
93 | |||
94 | #define carl9170_regwrite_finish() \ | ||
95 | __regwrite_out : \ | ||
96 | if (__err == 0 && __nreg) { \ | ||
97 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
98 | __err = carl9170_exec_cmd(__ar, \ | ||
99 | CARL9170_CMD_WREG, 8 * __nreg, \ | ||
100 | (u8 *) &__ar->cmd_buf[1], 0, NULL); \ | ||
101 | __nreg = 0; \ | ||
102 | } | ||
103 | |||
104 | #define carl9170_regwrite_result() \ | ||
105 | __err; \ | ||
106 | } while (0); | ||
107 | |||
108 | |||
109 | #define carl9170_async_get_buf() \ | ||
110 | do { \ | ||
111 | __cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC, \ | ||
112 | CARL9170_MAX_CMD_PAYLOAD_LEN); \ | ||
113 | if (__cmd == NULL) { \ | ||
114 | __err = -ENOMEM; \ | ||
115 | goto __async_regwrite_out; \ | ||
116 | } \ | ||
117 | } while (0); | ||
118 | |||
119 | #define carl9170_async_regwrite_begin(carl) \ | ||
120 | do { \ | ||
121 | int __nreg = 0, __err = 0; \ | ||
122 | struct ar9170 *__carl = carl; \ | ||
123 | struct carl9170_cmd *__cmd; \ | ||
124 | carl9170_async_get_buf(); \ | ||
125 | |||
126 | #define carl9170_async_regwrite(r, v) do { \ | ||
127 | __cmd->wreg.regs[__nreg].addr = cpu_to_le32(r); \ | ||
128 | __cmd->wreg.regs[__nreg].val = cpu_to_le32(v); \ | ||
129 | __nreg++; \ | ||
130 | if ((__nreg >= PAYLOAD_MAX/2)) { \ | ||
131 | if (IS_ACCEPTING_CMD(__carl)) { \ | ||
132 | __cmd->hdr.len = 8 * __nreg; \ | ||
133 | __err = __carl9170_exec_cmd(__carl, __cmd, true);\ | ||
134 | __cmd = NULL; \ | ||
135 | carl9170_async_get_buf(); \ | ||
136 | } else { \ | ||
137 | goto __async_regwrite_out; \ | ||
138 | } \ | ||
139 | __nreg = 0; \ | ||
140 | if (__err) \ | ||
141 | goto __async_regwrite_out; \ | ||
142 | } \ | ||
143 | } while (0) | ||
144 | |||
145 | #define carl9170_async_regwrite_finish() \ | ||
146 | __async_regwrite_out : \ | ||
147 | if (__err == 0 && __nreg) { \ | ||
148 | __cmd->hdr.len = 8 * __nreg; \ | ||
149 | if (IS_ACCEPTING_CMD(__carl)) \ | ||
150 | __err = __carl9170_exec_cmd(__carl, __cmd, true);\ | ||
151 | __nreg = 0; \ | ||
152 | } | ||
153 | |||
154 | #define carl9170_async_regwrite_result() \ | ||
155 | __err; \ | ||
156 | } while (0); | ||
157 | |||
158 | #endif /* __CMD_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c new file mode 100644 index 000000000000..19b48369ffed --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/debug.c | |||
@@ -0,0 +1,906 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * debug(fs) probing | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2008-2009 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/seq_file.h> | ||
44 | #include <linux/vmalloc.h> | ||
45 | #include "carl9170.h" | ||
46 | #include "cmd.h" | ||
47 | |||
48 | #define ADD(buf, off, max, fmt, args...) \ | ||
49 | off += snprintf(&buf[off], max - off, fmt, ##args); | ||
50 | |||
51 | static int carl9170_debugfs_open(struct inode *inode, struct file *file) | ||
52 | { | ||
53 | file->private_data = inode->i_private; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct carl9170_debugfs_fops { | ||
58 | unsigned int read_bufsize; | ||
59 | mode_t attr; | ||
60 | char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize, | ||
61 | ssize_t *len); | ||
62 | ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size); | ||
63 | const struct file_operations fops; | ||
64 | |||
65 | enum carl9170_device_state req_dev_state; | ||
66 | }; | ||
67 | |||
68 | static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf, | ||
69 | size_t count, loff_t *ppos) | ||
70 | { | ||
71 | struct carl9170_debugfs_fops *dfops; | ||
72 | struct ar9170 *ar; | ||
73 | char *buf = NULL, *res_buf = NULL; | ||
74 | ssize_t ret = 0; | ||
75 | int err = 0; | ||
76 | |||
77 | if (!count) | ||
78 | return 0; | ||
79 | |||
80 | ar = file->private_data; | ||
81 | |||
82 | if (!ar) | ||
83 | return -ENODEV; | ||
84 | dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); | ||
85 | |||
86 | if (!dfops->read) | ||
87 | return -ENOSYS; | ||
88 | |||
89 | if (dfops->read_bufsize) { | ||
90 | buf = vmalloc(dfops->read_bufsize); | ||
91 | if (!buf) | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | |||
95 | mutex_lock(&ar->mutex); | ||
96 | if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) { | ||
97 | err = -ENODEV; | ||
98 | res_buf = buf; | ||
99 | goto out_free; | ||
100 | } | ||
101 | |||
102 | res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret); | ||
103 | |||
104 | if (ret > 0) | ||
105 | err = simple_read_from_buffer(userbuf, count, ppos, | ||
106 | res_buf, ret); | ||
107 | else | ||
108 | err = ret; | ||
109 | |||
110 | WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf)); | ||
111 | |||
112 | out_free: | ||
113 | vfree(res_buf); | ||
114 | mutex_unlock(&ar->mutex); | ||
115 | return err; | ||
116 | } | ||
117 | |||
118 | static ssize_t carl9170_debugfs_write(struct file *file, | ||
119 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
120 | { | ||
121 | struct carl9170_debugfs_fops *dfops; | ||
122 | struct ar9170 *ar; | ||
123 | char *buf = NULL; | ||
124 | int err = 0; | ||
125 | |||
126 | if (!count) | ||
127 | return 0; | ||
128 | |||
129 | if (count > PAGE_SIZE) | ||
130 | return -E2BIG; | ||
131 | |||
132 | ar = file->private_data; | ||
133 | |||
134 | if (!ar) | ||
135 | return -ENODEV; | ||
136 | dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); | ||
137 | |||
138 | if (!dfops->write) | ||
139 | return -ENOSYS; | ||
140 | |||
141 | buf = vmalloc(count); | ||
142 | if (!buf) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | if (copy_from_user(buf, userbuf, count)) { | ||
146 | err = -EFAULT; | ||
147 | goto out_free; | ||
148 | } | ||
149 | |||
150 | if (mutex_trylock(&ar->mutex) == 0) { | ||
151 | err = -EAGAIN; | ||
152 | goto out_free; | ||
153 | } | ||
154 | |||
155 | if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) { | ||
156 | err = -ENODEV; | ||
157 | goto out_unlock; | ||
158 | } | ||
159 | |||
160 | err = dfops->write(ar, buf, count); | ||
161 | if (err) | ||
162 | goto out_unlock; | ||
163 | |||
164 | out_unlock: | ||
165 | mutex_unlock(&ar->mutex); | ||
166 | |||
167 | out_free: | ||
168 | vfree(buf); | ||
169 | return err; | ||
170 | } | ||
171 | |||
172 | #define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \ | ||
173 | _attr, _dstate) \ | ||
174 | static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\ | ||
175 | .read_bufsize = _read_bufsize, \ | ||
176 | .read = _read, \ | ||
177 | .write = _write, \ | ||
178 | .attr = _attr, \ | ||
179 | .req_dev_state = _dstate, \ | ||
180 | .fops = { \ | ||
181 | .open = carl9170_debugfs_open, \ | ||
182 | .read = carl9170_debugfs_read, \ | ||
183 | .write = carl9170_debugfs_write, \ | ||
184 | .owner = THIS_MODULE \ | ||
185 | }, \ | ||
186 | } | ||
187 | |||
188 | #define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \ | ||
189 | __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \ | ||
190 | _attr, CARL9170_STARTED) \ | ||
191 | |||
192 | #define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) \ | ||
193 | DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
194 | NULL, _read_bufsize, S_IRUSR) | ||
195 | |||
196 | #define DEBUGFS_DECLARE_WO_FILE(name) \ | ||
197 | DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\ | ||
198 | 0, S_IWUSR) | ||
199 | |||
200 | #define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize) \ | ||
201 | DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
202 | carl9170_debugfs_##name ##_write, \ | ||
203 | _read_bufsize, S_IRUSR | S_IWUSR) | ||
204 | |||
205 | #define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate) \ | ||
206 | __DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
207 | carl9170_debugfs_##name ##_write, \ | ||
208 | _read_bufsize, S_IRUSR | S_IWUSR, _dstate) | ||
209 | |||
210 | #define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...) \ | ||
211 | static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar, \ | ||
212 | char *buf, size_t buf_size,\ | ||
213 | ssize_t *len) \ | ||
214 | { \ | ||
215 | ADD(buf, *len, buf_size, fmt "\n", ##value); \ | ||
216 | return buf; \ | ||
217 | } \ | ||
218 | DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) | ||
219 | |||
220 | static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf, | ||
221 | size_t bufsize, ssize_t *len) | ||
222 | { | ||
223 | ADD(buf, *len, bufsize, "jar: ["); | ||
224 | |||
225 | spin_lock_bh(&ar->mem_lock); | ||
226 | |||
227 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
228 | ar->mem_bitmap, ar->fw.mem_blocks); | ||
229 | |||
230 | ADD(buf, *len, bufsize, "]\n"); | ||
231 | |||
232 | ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n", | ||
233 | bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks), | ||
234 | ar->fw.mem_blocks, atomic_read(&ar->mem_allocs)); | ||
235 | |||
236 | ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n", | ||
237 | atomic_read(&ar->mem_free_blocks), | ||
238 | (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024, | ||
239 | (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024); | ||
240 | |||
241 | spin_unlock_bh(&ar->mem_lock); | ||
242 | |||
243 | return buf; | ||
244 | } | ||
245 | DEBUGFS_DECLARE_RO_FILE(mem_usage, 512); | ||
246 | |||
247 | static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf, | ||
248 | size_t bufsize, ssize_t *len) | ||
249 | { | ||
250 | ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" : | ||
251 | "Software"); | ||
252 | |||
253 | ADD(buf, *len, bufsize, "[ VO VI " | ||
254 | " BE BK ]\n"); | ||
255 | |||
256 | spin_lock_bh(&ar->tx_stats_lock); | ||
257 | ADD(buf, *len, bufsize, "[length/limit length/limit " | ||
258 | "length/limit length/limit ]\n" | ||
259 | "[ %3d/%3d %3d/%3d " | ||
260 | " %3d/%3d %3d/%3d ]\n\n", | ||
261 | ar->tx_stats[0].len, ar->tx_stats[0].limit, | ||
262 | ar->tx_stats[1].len, ar->tx_stats[1].limit, | ||
263 | ar->tx_stats[2].len, ar->tx_stats[2].limit, | ||
264 | ar->tx_stats[3].len, ar->tx_stats[3].limit); | ||
265 | |||
266 | ADD(buf, *len, bufsize, "[ total total " | ||
267 | " total total ]\n" | ||
268 | "[%10d %10d %10d %10d ]\n\n", | ||
269 | ar->tx_stats[0].count, ar->tx_stats[1].count, | ||
270 | ar->tx_stats[2].count, ar->tx_stats[3].count); | ||
271 | |||
272 | spin_unlock_bh(&ar->tx_stats_lock); | ||
273 | |||
274 | ADD(buf, *len, bufsize, "[ pend/waittx pend/waittx " | ||
275 | " pend/waittx pend/waittx]\n" | ||
276 | "[ %3d/%3d %3d/%3d " | ||
277 | " %3d/%3d %3d/%3d ]\n\n", | ||
278 | skb_queue_len(&ar->tx_pending[0]), | ||
279 | skb_queue_len(&ar->tx_status[0]), | ||
280 | skb_queue_len(&ar->tx_pending[1]), | ||
281 | skb_queue_len(&ar->tx_status[1]), | ||
282 | skb_queue_len(&ar->tx_pending[2]), | ||
283 | skb_queue_len(&ar->tx_status[2]), | ||
284 | skb_queue_len(&ar->tx_pending[3]), | ||
285 | skb_queue_len(&ar->tx_status[3])); | ||
286 | |||
287 | return buf; | ||
288 | } | ||
289 | DEBUGFS_DECLARE_RO_FILE(qos_stat, 512); | ||
290 | |||
291 | static void carl9170_debugfs_format_frame(struct ar9170 *ar, | ||
292 | struct sk_buff *skb, const char *prefix, char *buf, | ||
293 | ssize_t *off, ssize_t bufsize) | ||
294 | { | ||
295 | struct _carl9170_tx_superframe *txc = (void *) skb->data; | ||
296 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
297 | struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
298 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
299 | |||
300 | ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, " | ||
301 | "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie, | ||
302 | ieee80211_get_DA(hdr), get_seq_h(hdr), | ||
303 | le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control), | ||
304 | jiffies_to_msecs(jiffies - arinfo->timeout)); | ||
305 | } | ||
306 | |||
307 | |||
308 | static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf, | ||
309 | size_t bufsize, ssize_t *len) | ||
310 | { | ||
311 | struct carl9170_sta_tid *iter; | ||
312 | struct sk_buff *skb; | ||
313 | int cnt = 0, fc; | ||
314 | int offset; | ||
315 | |||
316 | rcu_read_lock(); | ||
317 | list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { | ||
318 | |||
319 | spin_lock_bh(&iter->lock); | ||
320 | ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, " | ||
321 | "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n", | ||
322 | cnt, iter->tid, iter->bsn, iter->snx, iter->hsn, | ||
323 | iter->max, iter->state, iter->counter); | ||
324 | |||
325 | ADD(buf, *len, bufsize, "\tWindow: ["); | ||
326 | |||
327 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
328 | iter->bitmap, CARL9170_BAW_BITS); | ||
329 | |||
330 | #define BM_STR_OFF(offset) \ | ||
331 | ((CARL9170_BAW_BITS - (offset) - 1) / 4 + \ | ||
332 | (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1) | ||
333 | |||
334 | ADD(buf, *len, bufsize, ",W]\n"); | ||
335 | |||
336 | offset = BM_STR_OFF(0); | ||
337 | ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T"); | ||
338 | |||
339 | offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn)); | ||
340 | ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W"); | ||
341 | |||
342 | offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) % | ||
343 | CARL9170_BAW_BITS); | ||
344 | ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N"); | ||
345 | |||
346 | ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: " | ||
347 | " currently queued:%d\n", skb_queue_len(&iter->queue)); | ||
348 | |||
349 | fc = 0; | ||
350 | skb_queue_walk(&iter->queue, skb) { | ||
351 | char prefix[32]; | ||
352 | |||
353 | snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc); | ||
354 | carl9170_debugfs_format_frame(ar, skb, prefix, buf, | ||
355 | len, bufsize); | ||
356 | |||
357 | fc++; | ||
358 | } | ||
359 | spin_unlock_bh(&iter->lock); | ||
360 | cnt++; | ||
361 | } | ||
362 | rcu_read_unlock(); | ||
363 | |||
364 | return buf; | ||
365 | } | ||
366 | DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000); | ||
367 | |||
368 | static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf, | ||
369 | ssize_t *len, size_t bufsize, struct sk_buff_head *queue) | ||
370 | { | ||
371 | struct sk_buff *skb; | ||
372 | char prefix[16]; | ||
373 | int fc = 0; | ||
374 | |||
375 | spin_lock_bh(&queue->lock); | ||
376 | skb_queue_walk(queue, skb) { | ||
377 | snprintf(prefix, sizeof(prefix), "%3d :", fc); | ||
378 | carl9170_debugfs_format_frame(ar, skb, prefix, buf, | ||
379 | len, bufsize); | ||
380 | fc++; | ||
381 | } | ||
382 | spin_unlock_bh(&queue->lock); | ||
383 | } | ||
384 | |||
385 | #define DEBUGFS_QUEUE_DUMP(q, qi) \ | ||
386 | static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar, \ | ||
387 | char *buf, size_t bufsize, ssize_t *len) \ | ||
388 | { \ | ||
389 | carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]); \ | ||
390 | return buf; \ | ||
391 | } \ | ||
392 | DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000); | ||
393 | |||
394 | static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf, | ||
395 | size_t bufsize, ssize_t *len) | ||
396 | { | ||
397 | ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ? | ||
398 | "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM"))); | ||
399 | |||
400 | ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms); | ||
401 | ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n", | ||
402 | jiffies_to_msecs(jiffies - ar->ps.last_action)); | ||
403 | ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n", | ||
404 | jiffies_to_msecs(jiffies - ar->ps.last_slept)); | ||
405 | |||
406 | return buf; | ||
407 | } | ||
408 | DEBUGFS_DECLARE_RO_FILE(sta_psm, 160); | ||
409 | |||
410 | static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf, | ||
411 | size_t bufsize, ssize_t *len) | ||
412 | { | ||
413 | int i; | ||
414 | |||
415 | for (i = 0; i < ar->hw->queues; i++) { | ||
416 | ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n", | ||
417 | i, ieee80211_queue_stopped(ar->hw, i) ? | ||
418 | jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0, | ||
419 | jiffies_to_msecs(ar->max_queue_stop_timeout[i])); | ||
420 | |||
421 | ar->max_queue_stop_timeout[i] = 0; | ||
422 | } | ||
423 | |||
424 | return buf; | ||
425 | } | ||
426 | DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180); | ||
427 | |||
428 | static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf, | ||
429 | size_t bufsize, ssize_t *len) | ||
430 | { | ||
431 | int err; | ||
432 | |||
433 | err = carl9170_get_noisefloor(ar); | ||
434 | if (err) { | ||
435 | *len = err; | ||
436 | return buf; | ||
437 | } | ||
438 | |||
439 | ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n", | ||
440 | ar->noise[0], ar->noise[2]); | ||
441 | ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n", | ||
442 | ar->noise[1], ar->noise[3]); | ||
443 | |||
444 | return buf; | ||
445 | } | ||
446 | DEBUGFS_DECLARE_RO_FILE(phy_noise, 180); | ||
447 | |||
448 | static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf, | ||
449 | size_t bufsize, ssize_t *len) | ||
450 | { | ||
451 | struct carl9170_vif_info *iter; | ||
452 | int i = 0; | ||
453 | |||
454 | ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n", | ||
455 | ar->vifs, ar->fw.vif_num); | ||
456 | |||
457 | ADD(buf, *len, bufsize, "VIF bitmap: ["); | ||
458 | |||
459 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
460 | &ar->vif_bitmap, ar->fw.vif_num); | ||
461 | |||
462 | ADD(buf, *len, bufsize, "]\n"); | ||
463 | |||
464 | rcu_read_lock(); | ||
465 | list_for_each_entry_rcu(iter, &ar->vif_list, list) { | ||
466 | struct ieee80211_vif *vif = carl9170_get_vif(iter); | ||
467 | ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x " | ||
468 | " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ? | ||
469 | "Master" : " Slave"), iter->id, vif->type, vif->addr, | ||
470 | iter->enable_beacon ? "beaconing " : ""); | ||
471 | i++; | ||
472 | } | ||
473 | rcu_read_unlock(); | ||
474 | |||
475 | return buf; | ||
476 | } | ||
477 | DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000); | ||
478 | |||
479 | #define UPDATE_COUNTER(ar, name) ({ \ | ||
480 | u32 __tmp[ARRAY_SIZE(name##_regs)]; \ | ||
481 | unsigned int __i, __err = -ENODEV; \ | ||
482 | \ | ||
483 | for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \ | ||
484 | __tmp[__i] = name##_regs[__i].reg; \ | ||
485 | ar->debug.stats.name##_counter[__i] = 0; \ | ||
486 | } \ | ||
487 | \ | ||
488 | if (IS_STARTED(ar)) \ | ||
489 | __err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs), \ | ||
490 | __tmp, ar->debug.stats.name##_counter); \ | ||
491 | (__err); }) | ||
492 | |||
493 | #define TALLY_SUM_UP(ar, name) do { \ | ||
494 | unsigned int __i; \ | ||
495 | \ | ||
496 | for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \ | ||
497 | ar->debug.stats.name##_sum[__i] += \ | ||
498 | ar->debug.stats.name##_counter[__i]; \ | ||
499 | } \ | ||
500 | } while (0) | ||
501 | |||
502 | #define DEBUGFS_HW_TALLY_FILE(name, f) \ | ||
503 | static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \ | ||
504 | char *dum, size_t bufsize, ssize_t *ret) \ | ||
505 | { \ | ||
506 | char *buf; \ | ||
507 | int i, max_len, err; \ | ||
508 | \ | ||
509 | max_len = ARRAY_SIZE(name##_regs) * 80; \ | ||
510 | buf = vmalloc(max_len); \ | ||
511 | if (!buf) \ | ||
512 | return NULL; \ | ||
513 | \ | ||
514 | err = UPDATE_COUNTER(ar, name); \ | ||
515 | if (err) { \ | ||
516 | *ret = err; \ | ||
517 | return buf; \ | ||
518 | } \ | ||
519 | \ | ||
520 | TALLY_SUM_UP(ar, name); \ | ||
521 | \ | ||
522 | for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \ | ||
523 | ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n", \ | ||
524 | name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\ | ||
525 | ar->debug.stats.name ##_counter[i]); \ | ||
526 | } \ | ||
527 | \ | ||
528 | return buf; \ | ||
529 | } \ | ||
530 | DEBUGFS_DECLARE_RO_FILE(name, 0); | ||
531 | |||
532 | #define DEBUGFS_HW_REG_FILE(name, f) \ | ||
533 | static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \ | ||
534 | char *dum, size_t bufsize, ssize_t *ret) \ | ||
535 | { \ | ||
536 | char *buf; \ | ||
537 | int i, max_len, err; \ | ||
538 | \ | ||
539 | max_len = ARRAY_SIZE(name##_regs) * 80; \ | ||
540 | buf = vmalloc(max_len); \ | ||
541 | if (!buf) \ | ||
542 | return NULL; \ | ||
543 | \ | ||
544 | err = UPDATE_COUNTER(ar, name); \ | ||
545 | if (err) { \ | ||
546 | *ret = err; \ | ||
547 | return buf; \ | ||
548 | } \ | ||
549 | \ | ||
550 | for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \ | ||
551 | ADD(buf, *ret, max_len, "%22s = %" f "\n", \ | ||
552 | name##_regs[i].nreg, \ | ||
553 | ar->debug.stats.name##_counter[i]); \ | ||
554 | } \ | ||
555 | \ | ||
556 | return buf; \ | ||
557 | } \ | ||
558 | DEBUGFS_DECLARE_RO_FILE(name, 0); | ||
559 | |||
560 | static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar, | ||
561 | const char *buf, size_t count) | ||
562 | { | ||
563 | int err = 0, i, n = 0, max_len = 32, res; | ||
564 | unsigned int reg, tmp; | ||
565 | |||
566 | if (!count) | ||
567 | return 0; | ||
568 | |||
569 | if (count > max_len) | ||
570 | return -E2BIG; | ||
571 | |||
572 | res = sscanf(buf, "0x%X %d", ®, &n); | ||
573 | if (res < 1) { | ||
574 | err = -EINVAL; | ||
575 | goto out; | ||
576 | } | ||
577 | |||
578 | if (res == 1) | ||
579 | n = 1; | ||
580 | |||
581 | if (n > 15) { | ||
582 | err = -EMSGSIZE; | ||
583 | goto out; | ||
584 | } | ||
585 | |||
586 | if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) { | ||
587 | err = -EADDRNOTAVAIL; | ||
588 | goto out; | ||
589 | } | ||
590 | |||
591 | if (reg & 3) { | ||
592 | err = -EINVAL; | ||
593 | goto out; | ||
594 | } | ||
595 | |||
596 | for (i = 0; i < n; i++) { | ||
597 | err = carl9170_read_reg(ar, reg + (i << 2), &tmp); | ||
598 | if (err) | ||
599 | goto out; | ||
600 | |||
601 | ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2); | ||
602 | ar->debug.ring[ar->debug.ring_tail].value = tmp; | ||
603 | ar->debug.ring_tail++; | ||
604 | ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE; | ||
605 | } | ||
606 | |||
607 | out: | ||
608 | return err ? err : count; | ||
609 | } | ||
610 | |||
611 | static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf, | ||
612 | size_t bufsize, ssize_t *ret) | ||
613 | { | ||
614 | int i = 0; | ||
615 | |||
616 | while (ar->debug.ring_head != ar->debug.ring_tail) { | ||
617 | ADD(buf, *ret, bufsize, "%.8x = %.8x\n", | ||
618 | ar->debug.ring[ar->debug.ring_head].reg, | ||
619 | ar->debug.ring[ar->debug.ring_head].value); | ||
620 | |||
621 | ar->debug.ring_head++; | ||
622 | ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE; | ||
623 | |||
624 | if (i++ == 64) | ||
625 | break; | ||
626 | } | ||
627 | ar->debug.ring_head = ar->debug.ring_tail; | ||
628 | return buf; | ||
629 | } | ||
630 | DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40); | ||
631 | |||
632 | static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf, | ||
633 | size_t count) | ||
634 | { | ||
635 | int err; | ||
636 | |||
637 | if (count < 1) | ||
638 | return -EINVAL; | ||
639 | |||
640 | switch (buf[0]) { | ||
641 | case 'F': | ||
642 | ar->needs_full_reset = true; | ||
643 | break; | ||
644 | |||
645 | case 'R': | ||
646 | if (!IS_STARTED(ar)) { | ||
647 | err = -EAGAIN; | ||
648 | goto out; | ||
649 | } | ||
650 | |||
651 | ar->needs_full_reset = false; | ||
652 | break; | ||
653 | |||
654 | case 'M': | ||
655 | err = carl9170_mac_reset(ar); | ||
656 | if (err < 0) | ||
657 | count = err; | ||
658 | |||
659 | goto out; | ||
660 | |||
661 | case 'P': | ||
662 | err = carl9170_set_channel(ar, ar->hw->conf.channel, | ||
663 | ar->hw->conf.channel_type, CARL9170_RFI_COLD); | ||
664 | if (err < 0) | ||
665 | count = err; | ||
666 | |||
667 | goto out; | ||
668 | |||
669 | default: | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | carl9170_restart(ar, CARL9170_RR_USER_REQUEST); | ||
674 | |||
675 | out: | ||
676 | return count; | ||
677 | } | ||
678 | |||
679 | static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf, | ||
680 | size_t bufsize, ssize_t *ret) | ||
681 | { | ||
682 | ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, " | ||
683 | "[M]ac reset\n"); | ||
684 | ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n", | ||
685 | ar->restart_counter, ar->last_reason); | ||
686 | ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n", | ||
687 | ar->total_chan_fail, ar->chan_fail); | ||
688 | ADD(buf, *ret, bufsize, "reported firmware errors:%d\n", | ||
689 | ar->fw.err_counter); | ||
690 | ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n", | ||
691 | ar->fw.bug_counter); | ||
692 | ADD(buf, *ret, bufsize, "pending restart requests:%d\n", | ||
693 | atomic_read(&ar->pending_restarts)); | ||
694 | return buf; | ||
695 | } | ||
696 | __DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED); | ||
697 | |||
698 | static const char *erp_modes[] = { | ||
699 | [CARL9170_ERP_INVALID] = "INVALID", | ||
700 | [CARL9170_ERP_AUTO] = "Automatic", | ||
701 | [CARL9170_ERP_MAC80211] = "Set by MAC80211", | ||
702 | [CARL9170_ERP_OFF] = "Force Off", | ||
703 | [CARL9170_ERP_RTS] = "Force RTS", | ||
704 | [CARL9170_ERP_CTS] = "Force CTS" | ||
705 | }; | ||
706 | |||
707 | static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf, | ||
708 | size_t bufsize, ssize_t *ret) | ||
709 | { | ||
710 | ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode, | ||
711 | erp_modes[ar->erp_mode]); | ||
712 | return buf; | ||
713 | } | ||
714 | |||
715 | static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf, | ||
716 | size_t count) | ||
717 | { | ||
718 | int res, val; | ||
719 | |||
720 | if (count < 1) | ||
721 | return -EINVAL; | ||
722 | |||
723 | res = sscanf(buf, "%d", &val); | ||
724 | if (res != 1) | ||
725 | return -EINVAL; | ||
726 | |||
727 | if (!((val > CARL9170_ERP_INVALID) && | ||
728 | (val < __CARL9170_ERP_NUM))) | ||
729 | return -EINVAL; | ||
730 | |||
731 | ar->erp_mode = val; | ||
732 | return count; | ||
733 | } | ||
734 | |||
735 | DEBUGFS_DECLARE_RW_FILE(erp, 80); | ||
736 | |||
737 | static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar, | ||
738 | const char *buf, size_t count) | ||
739 | { | ||
740 | int err = 0, max_len = 22, res; | ||
741 | u32 reg, val; | ||
742 | |||
743 | if (!count) | ||
744 | return 0; | ||
745 | |||
746 | if (count > max_len) | ||
747 | return -E2BIG; | ||
748 | |||
749 | res = sscanf(buf, "0x%X 0x%X", ®, &val); | ||
750 | if (res != 2) { | ||
751 | err = -EINVAL; | ||
752 | goto out; | ||
753 | } | ||
754 | |||
755 | if (reg <= 0x100000 || reg >= 0x280000) { | ||
756 | err = -EADDRNOTAVAIL; | ||
757 | goto out; | ||
758 | } | ||
759 | |||
760 | if (reg & 3) { | ||
761 | err = -EINVAL; | ||
762 | goto out; | ||
763 | } | ||
764 | |||
765 | err = carl9170_write_reg(ar, reg, val); | ||
766 | if (err) | ||
767 | goto out; | ||
768 | |||
769 | out: | ||
770 | return err ? err : count; | ||
771 | } | ||
772 | DEBUGFS_DECLARE_WO_FILE(hw_iowrite32); | ||
773 | |||
774 | DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u"); | ||
775 | DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u"); | ||
776 | DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u"); | ||
777 | DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x"); | ||
778 | DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x"); | ||
779 | DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x"); | ||
780 | DEBUGFS_QUEUE_DUMP(tx_status, 0); | ||
781 | DEBUGFS_QUEUE_DUMP(tx_status, 1); | ||
782 | DEBUGFS_QUEUE_DUMP(tx_status, 2); | ||
783 | DEBUGFS_QUEUE_DUMP(tx_status, 3); | ||
784 | DEBUGFS_QUEUE_DUMP(tx_pending, 0); | ||
785 | DEBUGFS_QUEUE_DUMP(tx_pending, 1); | ||
786 | DEBUGFS_QUEUE_DUMP(tx_pending, 2); | ||
787 | DEBUGFS_QUEUE_DUMP(tx_pending, 3); | ||
788 | DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d", | ||
789 | atomic_read(&ar->tx_anch_urbs)); | ||
790 | DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d", | ||
791 | atomic_read(&ar->rx_anch_urbs)); | ||
792 | DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d", | ||
793 | atomic_read(&ar->rx_work_urbs)); | ||
794 | DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d", | ||
795 | atomic_read(&ar->rx_pool_urbs)); | ||
796 | |||
797 | DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d", | ||
798 | atomic_read(&ar->tx_total_queued)); | ||
799 | DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d", | ||
800 | atomic_read(&ar->tx_ampdu_scheduler)); | ||
801 | DEBUGFS_READONLY_FILE(tx_ampdu_timeout, 20, "%d", | ||
802 | ar->tx_ampdu_timeout); | ||
803 | |||
804 | DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d", | ||
805 | atomic_read(&ar->tx_total_pending)); | ||
806 | |||
807 | DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d", | ||
808 | ar->tx_ampdu_list_len); | ||
809 | |||
810 | DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d", | ||
811 | atomic_read(&ar->tx_ampdu_upload)); | ||
812 | |||
813 | DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago", | ||
814 | jiffies_to_msecs(jiffies - ar->tx_janitor_last_run)); | ||
815 | |||
816 | DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped); | ||
817 | |||
818 | DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped); | ||
819 | |||
820 | DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled); | ||
821 | DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d", | ||
822 | ar->rx_software_decryption); | ||
823 | DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d", | ||
824 | ar->current_factor); | ||
825 | DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d", | ||
826 | ar->current_density); | ||
827 | |||
828 | DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int); | ||
829 | DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt); | ||
830 | |||
831 | void carl9170_debugfs_register(struct ar9170 *ar) | ||
832 | { | ||
833 | ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME, | ||
834 | ar->hw->wiphy->debugfsdir); | ||
835 | |||
836 | #define DEBUGFS_ADD(name) \ | ||
837 | debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \ | ||
838 | ar->debug_dir, ar, \ | ||
839 | &carl_debugfs_##name ## _ops.fops); | ||
840 | |||
841 | DEBUGFS_ADD(usb_tx_anch_urbs); | ||
842 | DEBUGFS_ADD(usb_rx_pool_urbs); | ||
843 | DEBUGFS_ADD(usb_rx_anch_urbs); | ||
844 | DEBUGFS_ADD(usb_rx_work_urbs); | ||
845 | |||
846 | DEBUGFS_ADD(tx_total_queued); | ||
847 | DEBUGFS_ADD(tx_total_pending); | ||
848 | DEBUGFS_ADD(tx_dropped); | ||
849 | DEBUGFS_ADD(tx_stuck); | ||
850 | DEBUGFS_ADD(tx_ampdu_upload); | ||
851 | DEBUGFS_ADD(tx_ampdu_scheduler); | ||
852 | DEBUGFS_ADD(tx_ampdu_list_len); | ||
853 | |||
854 | DEBUGFS_ADD(rx_dropped); | ||
855 | DEBUGFS_ADD(sniffer_enabled); | ||
856 | DEBUGFS_ADD(rx_software_decryption); | ||
857 | |||
858 | DEBUGFS_ADD(mem_usage); | ||
859 | DEBUGFS_ADD(qos_stat); | ||
860 | DEBUGFS_ADD(sta_psm); | ||
861 | DEBUGFS_ADD(ampdu_state); | ||
862 | |||
863 | DEBUGFS_ADD(hw_tx_tally); | ||
864 | DEBUGFS_ADD(hw_rx_tally); | ||
865 | DEBUGFS_ADD(hw_phy_errors); | ||
866 | DEBUGFS_ADD(phy_noise); | ||
867 | |||
868 | DEBUGFS_ADD(hw_wlan_queue); | ||
869 | DEBUGFS_ADD(hw_pta_queue); | ||
870 | DEBUGFS_ADD(hw_ampdu_info); | ||
871 | |||
872 | DEBUGFS_ADD(ampdu_density); | ||
873 | DEBUGFS_ADD(ampdu_factor); | ||
874 | |||
875 | DEBUGFS_ADD(tx_ampdu_timeout); | ||
876 | |||
877 | DEBUGFS_ADD(tx_janitor_last_run); | ||
878 | |||
879 | DEBUGFS_ADD(tx_status_0); | ||
880 | DEBUGFS_ADD(tx_status_1); | ||
881 | DEBUGFS_ADD(tx_status_2); | ||
882 | DEBUGFS_ADD(tx_status_3); | ||
883 | |||
884 | DEBUGFS_ADD(tx_pending_0); | ||
885 | DEBUGFS_ADD(tx_pending_1); | ||
886 | DEBUGFS_ADD(tx_pending_2); | ||
887 | DEBUGFS_ADD(tx_pending_3); | ||
888 | |||
889 | DEBUGFS_ADD(hw_ioread32); | ||
890 | DEBUGFS_ADD(hw_iowrite32); | ||
891 | DEBUGFS_ADD(bug); | ||
892 | |||
893 | DEBUGFS_ADD(erp); | ||
894 | |||
895 | DEBUGFS_ADD(vif_dump); | ||
896 | |||
897 | DEBUGFS_ADD(beacon_int); | ||
898 | DEBUGFS_ADD(pretbtt); | ||
899 | |||
900 | #undef DEBUGFS_ADD | ||
901 | } | ||
902 | |||
903 | void carl9170_debugfs_unregister(struct ar9170 *ar) | ||
904 | { | ||
905 | debugfs_remove_recursive(ar->debug_dir); | ||
906 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/debug.h b/drivers/net/wireless/ath/carl9170/debug.h new file mode 100644 index 000000000000..ea4b97524122 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/debug.h | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * debug header | ||
5 | * | ||
6 | * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __DEBUG_H | ||
39 | #define __DEBUG_H | ||
40 | |||
41 | #include "eeprom.h" | ||
42 | #include "wlan.h" | ||
43 | #include "hw.h" | ||
44 | #include "fwdesc.h" | ||
45 | #include "fwcmd.h" | ||
46 | #include "../regd.h" | ||
47 | |||
48 | struct hw_stat_reg_entry { | ||
49 | u32 reg; | ||
50 | char nreg[32]; | ||
51 | }; | ||
52 | |||
53 | #define STAT_MAC_REG(reg) \ | ||
54 | { (AR9170_MAC_REG_##reg), #reg } | ||
55 | |||
56 | #define STAT_PTA_REG(reg) \ | ||
57 | { (AR9170_PTA_REG_##reg), #reg } | ||
58 | |||
59 | #define STAT_USB_REG(reg) \ | ||
60 | { (AR9170_USB_REG_##reg), #reg } | ||
61 | |||
62 | static const struct hw_stat_reg_entry hw_rx_tally_regs[] = { | ||
63 | STAT_MAC_REG(RX_CRC32), STAT_MAC_REG(RX_CRC16), | ||
64 | STAT_MAC_REG(RX_TIMEOUT_COUNT), STAT_MAC_REG(RX_ERR_DECRYPTION_UNI), | ||
65 | STAT_MAC_REG(RX_ERR_DECRYPTION_MUL), STAT_MAC_REG(RX_MPDU), | ||
66 | STAT_MAC_REG(RX_DROPPED_MPDU), STAT_MAC_REG(RX_DEL_MPDU), | ||
67 | }; | ||
68 | |||
69 | static const struct hw_stat_reg_entry hw_phy_errors_regs[] = { | ||
70 | STAT_MAC_REG(RX_PHY_MISC_ERROR), STAT_MAC_REG(RX_PHY_XR_ERROR), | ||
71 | STAT_MAC_REG(RX_PHY_OFDM_ERROR), STAT_MAC_REG(RX_PHY_CCK_ERROR), | ||
72 | STAT_MAC_REG(RX_PHY_HT_ERROR), STAT_MAC_REG(RX_PHY_TOTAL), | ||
73 | }; | ||
74 | |||
75 | static const struct hw_stat_reg_entry hw_tx_tally_regs[] = { | ||
76 | STAT_MAC_REG(TX_TOTAL), STAT_MAC_REG(TX_UNDERRUN), | ||
77 | STAT_MAC_REG(TX_RETRY), | ||
78 | }; | ||
79 | |||
80 | static const struct hw_stat_reg_entry hw_wlan_queue_regs[] = { | ||
81 | STAT_MAC_REG(DMA_STATUS), STAT_MAC_REG(DMA_TRIGGER), | ||
82 | STAT_MAC_REG(DMA_TXQ0_ADDR), STAT_MAC_REG(DMA_TXQ0_CURR_ADDR), | ||
83 | STAT_MAC_REG(DMA_TXQ1_ADDR), STAT_MAC_REG(DMA_TXQ1_CURR_ADDR), | ||
84 | STAT_MAC_REG(DMA_TXQ2_ADDR), STAT_MAC_REG(DMA_TXQ2_CURR_ADDR), | ||
85 | STAT_MAC_REG(DMA_TXQ3_ADDR), STAT_MAC_REG(DMA_TXQ3_CURR_ADDR), | ||
86 | STAT_MAC_REG(DMA_RXQ_ADDR), STAT_MAC_REG(DMA_RXQ_CURR_ADDR), | ||
87 | }; | ||
88 | |||
89 | static const struct hw_stat_reg_entry hw_ampdu_info_regs[] = { | ||
90 | STAT_MAC_REG(AMPDU_DENSITY), STAT_MAC_REG(AMPDU_FACTOR), | ||
91 | }; | ||
92 | |||
93 | static const struct hw_stat_reg_entry hw_pta_queue_regs[] = { | ||
94 | STAT_PTA_REG(DN_CURR_ADDRH), STAT_PTA_REG(DN_CURR_ADDRL), | ||
95 | STAT_PTA_REG(UP_CURR_ADDRH), STAT_PTA_REG(UP_CURR_ADDRL), | ||
96 | STAT_PTA_REG(DMA_STATUS), STAT_PTA_REG(DMA_MODE_CTRL), | ||
97 | }; | ||
98 | |||
99 | #define DEFINE_TALLY(name) \ | ||
100 | u32 name##_sum[ARRAY_SIZE(name##_regs)], \ | ||
101 | name##_counter[ARRAY_SIZE(name##_regs)] \ | ||
102 | |||
103 | #define DEFINE_STAT(name) \ | ||
104 | u32 name##_counter[ARRAY_SIZE(name##_regs)] \ | ||
105 | |||
106 | struct ath_stats { | ||
107 | DEFINE_TALLY(hw_tx_tally); | ||
108 | DEFINE_TALLY(hw_rx_tally); | ||
109 | DEFINE_TALLY(hw_phy_errors); | ||
110 | DEFINE_STAT(hw_wlan_queue); | ||
111 | DEFINE_STAT(hw_pta_queue); | ||
112 | DEFINE_STAT(hw_ampdu_info); | ||
113 | }; | ||
114 | |||
115 | struct carl9170_debug_mem_rbe { | ||
116 | u32 reg; | ||
117 | u32 value; | ||
118 | }; | ||
119 | |||
120 | #define CARL9170_DEBUG_RING_SIZE 64 | ||
121 | |||
122 | struct carl9170_debug { | ||
123 | struct ath_stats stats; | ||
124 | struct carl9170_debug_mem_rbe ring[CARL9170_DEBUG_RING_SIZE]; | ||
125 | struct mutex ring_lock; | ||
126 | unsigned int ring_head, ring_tail; | ||
127 | struct delayed_work update_tally; | ||
128 | }; | ||
129 | |||
130 | struct ar9170; | ||
131 | |||
132 | void carl9170_debugfs_register(struct ar9170 *ar); | ||
133 | void carl9170_debugfs_unregister(struct ar9170 *ar); | ||
134 | #endif /* __DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/eeprom.h b/drivers/net/wireless/ath/carl9170/eeprom.h new file mode 100644 index 000000000000..7cff40ac7759 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/eeprom.h | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * EEPROM layout | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __CARL9170_SHARED_EEPROM_H | ||
39 | #define __CARL9170_SHARED_EEPROM_H | ||
40 | |||
41 | #define AR9170_EEPROM_START 0x1600 | ||
42 | |||
43 | #define AR5416_MAX_CHAINS 2 | ||
44 | #define AR5416_MODAL_SPURS 5 | ||
45 | |||
46 | struct ar9170_eeprom_modal { | ||
47 | __le32 antCtrlChain[AR5416_MAX_CHAINS]; | ||
48 | __le32 antCtrlCommon; | ||
49 | s8 antennaGainCh[AR5416_MAX_CHAINS]; | ||
50 | u8 switchSettling; | ||
51 | u8 txRxAttenCh[AR5416_MAX_CHAINS]; | ||
52 | u8 rxTxMarginCh[AR5416_MAX_CHAINS]; | ||
53 | s8 adcDesiredSize; | ||
54 | s8 pgaDesiredSize; | ||
55 | u8 xlnaGainCh[AR5416_MAX_CHAINS]; | ||
56 | u8 txEndToXpaOff; | ||
57 | u8 txEndToRxOn; | ||
58 | u8 txFrameToXpaOn; | ||
59 | u8 thresh62; | ||
60 | s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; | ||
61 | u8 xpdGain; | ||
62 | u8 xpd; | ||
63 | s8 iqCalICh[AR5416_MAX_CHAINS]; | ||
64 | s8 iqCalQCh[AR5416_MAX_CHAINS]; | ||
65 | u8 pdGainOverlap; | ||
66 | u8 ob; | ||
67 | u8 db; | ||
68 | u8 xpaBiasLvl; | ||
69 | u8 pwrDecreaseFor2Chain; | ||
70 | u8 pwrDecreaseFor3Chain; | ||
71 | u8 txFrameToDataStart; | ||
72 | u8 txFrameToPaOn; | ||
73 | u8 ht40PowerIncForPdadc; | ||
74 | u8 bswAtten[AR5416_MAX_CHAINS]; | ||
75 | u8 bswMargin[AR5416_MAX_CHAINS]; | ||
76 | u8 swSettleHt40; | ||
77 | u8 reserved[22]; | ||
78 | struct spur_channel { | ||
79 | __le16 spurChan; | ||
80 | u8 spurRangeLow; | ||
81 | u8 spurRangeHigh; | ||
82 | } __packed spur_channels[AR5416_MODAL_SPURS]; | ||
83 | } __packed; | ||
84 | |||
85 | #define AR5416_NUM_PD_GAINS 4 | ||
86 | #define AR5416_PD_GAIN_ICEPTS 5 | ||
87 | |||
88 | struct ar9170_calibration_data_per_freq { | ||
89 | u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
90 | u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
91 | } __packed; | ||
92 | |||
93 | #define AR5416_NUM_5G_CAL_PIERS 8 | ||
94 | #define AR5416_NUM_2G_CAL_PIERS 4 | ||
95 | |||
96 | #define AR5416_NUM_5G_TARGET_PWRS 8 | ||
97 | #define AR5416_NUM_2G_CCK_TARGET_PWRS 3 | ||
98 | #define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 | ||
99 | #define AR5416_MAX_NUM_TGT_PWRS 8 | ||
100 | |||
101 | struct ar9170_calibration_target_power_legacy { | ||
102 | u8 freq; | ||
103 | u8 power[4]; | ||
104 | } __packed; | ||
105 | |||
106 | struct ar9170_calibration_target_power_ht { | ||
107 | u8 freq; | ||
108 | u8 power[8]; | ||
109 | } __packed; | ||
110 | |||
111 | #define AR5416_NUM_CTLS 24 | ||
112 | |||
113 | struct ar9170_calctl_edges { | ||
114 | u8 channel; | ||
115 | #define AR9170_CALCTL_EDGE_FLAGS 0xC0 | ||
116 | u8 power_flags; | ||
117 | } __packed; | ||
118 | |||
119 | #define AR5416_NUM_BAND_EDGES 8 | ||
120 | |||
121 | struct ar9170_calctl_data { | ||
122 | struct ar9170_calctl_edges | ||
123 | control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; | ||
124 | } __packed; | ||
125 | |||
126 | struct ar9170_eeprom { | ||
127 | __le16 length; | ||
128 | __le16 checksum; | ||
129 | __le16 version; | ||
130 | u8 operating_flags; | ||
131 | #define AR9170_OPFLAG_5GHZ 1 | ||
132 | #define AR9170_OPFLAG_2GHZ 2 | ||
133 | u8 misc; | ||
134 | __le16 reg_domain[2]; | ||
135 | u8 mac_address[6]; | ||
136 | u8 rx_mask; | ||
137 | u8 tx_mask; | ||
138 | __le16 rf_silent; | ||
139 | __le16 bluetooth_options; | ||
140 | __le16 device_capabilities; | ||
141 | __le32 build_number; | ||
142 | u8 deviceType; | ||
143 | u8 reserved[33]; | ||
144 | |||
145 | u8 customer_data[64]; | ||
146 | |||
147 | struct ar9170_eeprom_modal | ||
148 | modal_header[2]; | ||
149 | |||
150 | u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; | ||
151 | u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; | ||
152 | |||
153 | struct ar9170_calibration_data_per_freq | ||
154 | cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], | ||
155 | cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; | ||
156 | |||
157 | /* power calibration data */ | ||
158 | struct ar9170_calibration_target_power_legacy | ||
159 | cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; | ||
160 | struct ar9170_calibration_target_power_ht | ||
161 | cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], | ||
162 | cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; | ||
163 | |||
164 | struct ar9170_calibration_target_power_legacy | ||
165 | cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], | ||
166 | cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
167 | struct ar9170_calibration_target_power_ht | ||
168 | cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], | ||
169 | cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
170 | |||
171 | /* conformance testing limits */ | ||
172 | u8 ctl_index[AR5416_NUM_CTLS]; | ||
173 | struct ar9170_calctl_data | ||
174 | ctl_data[AR5416_NUM_CTLS]; | ||
175 | |||
176 | u8 pad; | ||
177 | __le16 subsystem_id; | ||
178 | } __packed; | ||
179 | |||
180 | #define AR9170_LED_MODE_POWER_ON 0x0001 | ||
181 | #define AR9170_LED_MODE_RESERVED 0x0002 | ||
182 | #define AR9170_LED_MODE_DISABLE_STATE 0x0004 | ||
183 | #define AR9170_LED_MODE_OFF_IN_PSM 0x0008 | ||
184 | |||
185 | /* AR9170_LED_MODE BIT is set */ | ||
186 | #define AR9170_LED_MODE_FREQUENCY_S 4 | ||
187 | #define AR9170_LED_MODE_FREQUENCY 0x0030 | ||
188 | #define AR9170_LED_MODE_FREQUENCY_1HZ 0x0000 | ||
189 | #define AR9170_LED_MODE_FREQUENCY_0_5HZ 0x0010 | ||
190 | #define AR9170_LED_MODE_FREQUENCY_0_25HZ 0x0020 | ||
191 | #define AR9170_LED_MODE_FREQUENCY_0_125HZ 0x0030 | ||
192 | |||
193 | /* AR9170_LED_MODE BIT is not set */ | ||
194 | #define AR9170_LED_MODE_CONN_STATE_S 4 | ||
195 | #define AR9170_LED_MODE_CONN_STATE 0x0030 | ||
196 | #define AR9170_LED_MODE_CONN_STATE_FORCE_OFF 0x0000 | ||
197 | #define AR9170_LED_MODE_CONN_STATE_FORCE_ON 0x0010 | ||
198 | /* Idle off / Active on */ | ||
199 | #define AR9170_LED_MODE_CONN_STATE_IOFF_AON 0x0020 | ||
200 | /* Idle on / Active off */ | ||
201 | #define AR9170_LED_MODE_CONN_STATE_ION_AOFF 0x0010 | ||
202 | |||
203 | #define AR9170_LED_MODE_MODE 0x0040 | ||
204 | #define AR9170_LED_MODE_RESERVED2 0x0080 | ||
205 | |||
206 | #define AR9170_LED_MODE_TON_SCAN_S 8 | ||
207 | #define AR9170_LED_MODE_TON_SCAN 0x0f00 | ||
208 | |||
209 | #define AR9170_LED_MODE_TOFF_SCAN_S 12 | ||
210 | #define AR9170_LED_MODE_TOFF_SCAN 0xf000 | ||
211 | |||
212 | struct ar9170_led_mode { | ||
213 | __le16 led; | ||
214 | }; | ||
215 | |||
216 | #endif /* __CARL9170_SHARED_EEPROM_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c new file mode 100644 index 000000000000..36615462b87a --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * firmware parser | ||
5 | * | ||
6 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/firmware.h> | ||
25 | #include <linux/crc32.h> | ||
26 | #include "carl9170.h" | ||
27 | #include "fwcmd.h" | ||
28 | #include "version.h" | ||
29 | |||
30 | #define MAKE_STR(symbol) #symbol | ||
31 | #define TO_STR(symbol) MAKE_STR(symbol) | ||
32 | #define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER) | ||
33 | MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT); | ||
34 | |||
35 | static const u8 otus_magic[4] = { OTUS_MAGIC }; | ||
36 | |||
37 | static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4], | ||
38 | const unsigned int len, const u8 compatible_revision) | ||
39 | { | ||
40 | const struct carl9170fw_desc_head *iter; | ||
41 | |||
42 | carl9170fw_for_each_hdr(iter, ar->fw.desc) { | ||
43 | if (carl9170fw_desc_cmp(iter, descid, len, | ||
44 | compatible_revision)) | ||
45 | return (void *)iter; | ||
46 | } | ||
47 | |||
48 | /* needed to find the LAST desc */ | ||
49 | if (carl9170fw_desc_cmp(iter, descid, len, | ||
50 | compatible_revision)) | ||
51 | return (void *)iter; | ||
52 | |||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | static int carl9170_fw_verify_descs(struct ar9170 *ar, | ||
57 | const struct carl9170fw_desc_head *head, unsigned int max_len) | ||
58 | { | ||
59 | const struct carl9170fw_desc_head *pos; | ||
60 | unsigned long pos_addr, end_addr; | ||
61 | unsigned int pos_length; | ||
62 | |||
63 | if (max_len < sizeof(*pos)) | ||
64 | return -ENODATA; | ||
65 | |||
66 | max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len); | ||
67 | |||
68 | pos = head; | ||
69 | pos_addr = (unsigned long) pos; | ||
70 | end_addr = pos_addr + max_len; | ||
71 | |||
72 | while (pos_addr < end_addr) { | ||
73 | if (pos_addr + sizeof(*head) > end_addr) | ||
74 | return -E2BIG; | ||
75 | |||
76 | pos_length = le16_to_cpu(pos->length); | ||
77 | |||
78 | if (pos_length < sizeof(*head)) | ||
79 | return -EBADMSG; | ||
80 | |||
81 | if (pos_length > max_len) | ||
82 | return -EOVERFLOW; | ||
83 | |||
84 | if (pos_addr + pos_length > end_addr) | ||
85 | return -EMSGSIZE; | ||
86 | |||
87 | if (carl9170fw_desc_cmp(pos, LAST_MAGIC, | ||
88 | CARL9170FW_LAST_DESC_SIZE, | ||
89 | CARL9170FW_LAST_DESC_CUR_VER)) | ||
90 | return 0; | ||
91 | |||
92 | pos_addr += pos_length; | ||
93 | pos = (void *)pos_addr; | ||
94 | max_len -= pos_length; | ||
95 | } | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | |||
99 | static void carl9170_fw_info(struct ar9170 *ar) | ||
100 | { | ||
101 | const struct carl9170fw_motd_desc *motd_desc; | ||
102 | unsigned int str_ver_len; | ||
103 | u32 fw_date; | ||
104 | |||
105 | dev_info(&ar->udev->dev, "driver API: %s 2%03d-%02d-%02d [%d-%d]\n", | ||
106 | CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR, | ||
107 | CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY, | ||
108 | CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER); | ||
109 | |||
110 | motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC, | ||
111 | sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER); | ||
112 | |||
113 | if (motd_desc) { | ||
114 | str_ver_len = strnlen(motd_desc->release, | ||
115 | CARL9170FW_MOTD_RELEASE_LEN); | ||
116 | |||
117 | fw_date = le32_to_cpu(motd_desc->fw_year_month_day); | ||
118 | |||
119 | dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n", | ||
120 | str_ver_len, motd_desc->release, | ||
121 | CARL9170FW_GET_YEAR(fw_date), | ||
122 | CARL9170FW_GET_MONTH(fw_date), | ||
123 | CARL9170FW_GET_DAY(fw_date)); | ||
124 | |||
125 | strlcpy(ar->hw->wiphy->fw_version, motd_desc->release, | ||
126 | sizeof(ar->hw->wiphy->fw_version)); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static bool valid_dma_addr(const u32 address) | ||
131 | { | ||
132 | if (address >= AR9170_SRAM_OFFSET && | ||
133 | address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE)) | ||
134 | return true; | ||
135 | |||
136 | return false; | ||
137 | } | ||
138 | |||
139 | static bool valid_cpu_addr(const u32 address) | ||
140 | { | ||
141 | if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET && | ||
142 | address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE))) | ||
143 | return true; | ||
144 | |||
145 | return false; | ||
146 | } | ||
147 | |||
148 | static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | ||
149 | { | ||
150 | const struct carl9170fw_otus_desc *otus_desc; | ||
151 | const struct carl9170fw_chk_desc *chk_desc; | ||
152 | const struct carl9170fw_last_desc *last_desc; | ||
153 | |||
154 | last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, | ||
155 | sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); | ||
156 | if (!last_desc) | ||
157 | return -EINVAL; | ||
158 | |||
159 | otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC, | ||
160 | sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER); | ||
161 | if (!otus_desc) { | ||
162 | dev_err(&ar->udev->dev, "failed to find compatible firmware " | ||
163 | "descriptor.\n"); | ||
164 | return -ENODATA; | ||
165 | } | ||
166 | |||
167 | chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC, | ||
168 | sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER); | ||
169 | |||
170 | if (chk_desc) { | ||
171 | unsigned long fin, diff; | ||
172 | unsigned int dsc_len; | ||
173 | u32 crc32; | ||
174 | |||
175 | dsc_len = min_t(unsigned int, len, | ||
176 | (unsigned long)chk_desc - (unsigned long)otus_desc); | ||
177 | |||
178 | fin = (unsigned long) last_desc + sizeof(*last_desc); | ||
179 | diff = fin - (unsigned long) otus_desc; | ||
180 | |||
181 | if (diff < len) | ||
182 | len -= diff; | ||
183 | |||
184 | if (len < 256) | ||
185 | return -EIO; | ||
186 | |||
187 | crc32 = crc32_le(~0, data, len); | ||
188 | if (cpu_to_le32(crc32) != chk_desc->fw_crc32) { | ||
189 | dev_err(&ar->udev->dev, "fw checksum test failed.\n"); | ||
190 | return -ENOEXEC; | ||
191 | } | ||
192 | |||
193 | crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len); | ||
194 | if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) { | ||
195 | dev_err(&ar->udev->dev, "descriptor check failed.\n"); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | } else { | ||
199 | dev_warn(&ar->udev->dev, "Unprotected firmware image.\n"); | ||
200 | } | ||
201 | |||
202 | #define SUPP(feat) \ | ||
203 | (carl9170fw_supports(otus_desc->feature_set, feat)) | ||
204 | |||
205 | if (!SUPP(CARL9170FW_DUMMY_FEATURE)) { | ||
206 | dev_err(&ar->udev->dev, "invalid firmware descriptor " | ||
207 | "format detected.\n"); | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | ar->fw.api_version = otus_desc->api_ver; | ||
212 | |||
213 | if (ar->fw.api_version < CARL9170FW_API_MIN_VER || | ||
214 | ar->fw.api_version > CARL9170FW_API_MAX_VER) { | ||
215 | dev_err(&ar->udev->dev, "unsupported firmware api version.\n"); | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) || | ||
220 | !SUPP(CARL9170FW_HANDLE_BACK_REQ)) { | ||
221 | dev_err(&ar->udev->dev, "firmware does support " | ||
222 | "mandatory features.\n"); | ||
223 | return -ECANCELED; | ||
224 | } | ||
225 | |||
226 | if (ilog2(le32_to_cpu(otus_desc->feature_set)) >= | ||
227 | __CARL9170FW_FEATURE_NUM) { | ||
228 | dev_warn(&ar->udev->dev, "driver does not support all " | ||
229 | "firmware features.\n"); | ||
230 | } | ||
231 | |||
232 | if (!SUPP(CARL9170FW_COMMAND_CAM)) { | ||
233 | dev_info(&ar->udev->dev, "crypto offloading is disabled " | ||
234 | "by firmware.\n"); | ||
235 | ar->disable_offload = true; | ||
236 | } | ||
237 | |||
238 | if (SUPP(CARL9170FW_PSM)) | ||
239 | ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS; | ||
240 | |||
241 | if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) { | ||
242 | dev_err(&ar->udev->dev, "firmware does not provide " | ||
243 | "mandatory interfaces.\n"); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | if (SUPP(CARL9170FW_MINIBOOT)) | ||
248 | ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size); | ||
249 | else | ||
250 | ar->fw.offset = 0; | ||
251 | |||
252 | if (SUPP(CARL9170FW_USB_DOWN_STREAM)) { | ||
253 | ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream); | ||
254 | ar->fw.tx_stream = true; | ||
255 | } | ||
256 | |||
257 | if (SUPP(CARL9170FW_USB_UP_STREAM)) | ||
258 | ar->fw.rx_stream = true; | ||
259 | |||
260 | ar->fw.vif_num = otus_desc->vif_num; | ||
261 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; | ||
262 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); | ||
263 | ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len); | ||
264 | ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe); | ||
265 | atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks); | ||
266 | ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len); | ||
267 | |||
268 | if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num || | ||
269 | ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs || | ||
270 | ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 || | ||
271 | ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 || | ||
272 | !valid_cpu_addr(ar->fw.address)) { | ||
273 | dev_err(&ar->udev->dev, "firmware shows obvious signs of " | ||
274 | "malicious tampering.\n"); | ||
275 | return -EINVAL; | ||
276 | } | ||
277 | |||
278 | ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr); | ||
279 | ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len); | ||
280 | |||
281 | if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >= | ||
282 | AR9170_MAC_BCN_LENGTH_MAX) { | ||
283 | ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | ||
284 | |||
285 | if (SUPP(CARL9170FW_WLANTX_CAB)) { | ||
286 | ar->hw->wiphy->interface_modes |= | ||
287 | BIT(NL80211_IFTYPE_AP); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | #undef SUPPORTED | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static struct carl9170fw_desc_head * | ||
296 | carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len) | ||
297 | |||
298 | { | ||
299 | int scan = 0, found = 0; | ||
300 | |||
301 | if (!carl9170fw_size_check(len)) { | ||
302 | dev_err(&ar->udev->dev, "firmware size is out of bound.\n"); | ||
303 | return NULL; | ||
304 | } | ||
305 | |||
306 | while (scan < len - sizeof(struct carl9170fw_desc_head)) { | ||
307 | if (fw_data[scan++] == otus_magic[found]) | ||
308 | found++; | ||
309 | else | ||
310 | found = 0; | ||
311 | |||
312 | if (scan >= len) | ||
313 | break; | ||
314 | |||
315 | if (found == sizeof(otus_magic)) | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | if (found != sizeof(otus_magic)) | ||
320 | return NULL; | ||
321 | |||
322 | return (void *)&fw_data[scan - found]; | ||
323 | } | ||
324 | |||
325 | int carl9170_fw_fix_eeprom(struct ar9170 *ar) | ||
326 | { | ||
327 | const struct carl9170fw_fix_desc *fix_desc = NULL; | ||
328 | unsigned int i, n, off; | ||
329 | u32 *data = (void *)&ar->eeprom; | ||
330 | |||
331 | fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC, | ||
332 | sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER); | ||
333 | |||
334 | if (!fix_desc) | ||
335 | return 0; | ||
336 | |||
337 | n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) / | ||
338 | sizeof(struct carl9170fw_fix_entry); | ||
339 | |||
340 | for (i = 0; i < n; i++) { | ||
341 | off = le32_to_cpu(fix_desc->data[i].address) - | ||
342 | AR9170_EEPROM_START; | ||
343 | |||
344 | if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) { | ||
345 | dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i); | ||
346 | continue; | ||
347 | } | ||
348 | |||
349 | data[off / sizeof(*data)] &= | ||
350 | le32_to_cpu(fix_desc->data[i].mask); | ||
351 | data[off / sizeof(*data)] |= | ||
352 | le32_to_cpu(fix_desc->data[i].value); | ||
353 | } | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | int carl9170_parse_firmware(struct ar9170 *ar) | ||
359 | { | ||
360 | const struct carl9170fw_desc_head *fw_desc = NULL; | ||
361 | const struct firmware *fw = ar->fw.fw; | ||
362 | unsigned long header_offset = 0; | ||
363 | int err; | ||
364 | |||
365 | if (WARN_ON(!fw)) | ||
366 | return -EINVAL; | ||
367 | |||
368 | fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size); | ||
369 | |||
370 | if (!fw_desc) { | ||
371 | dev_err(&ar->udev->dev, "unsupported firmware.\n"); | ||
372 | return -ENODATA; | ||
373 | } | ||
374 | |||
375 | header_offset = (unsigned long)fw_desc - (unsigned long)fw->data; | ||
376 | |||
377 | err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset); | ||
378 | if (err) { | ||
379 | dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err); | ||
380 | return err; | ||
381 | } | ||
382 | |||
383 | ar->fw.desc = fw_desc; | ||
384 | |||
385 | carl9170_fw_info(ar); | ||
386 | |||
387 | err = carl9170_fw(ar, fw->data, fw->size); | ||
388 | if (err) { | ||
389 | dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n", | ||
390 | err); | ||
391 | return err; | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h new file mode 100644 index 000000000000..d4a4e1dbef06 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * Firmware command interface definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_FWCMD_H | ||
40 | #define __CARL9170_SHARED_FWCMD_H | ||
41 | |||
42 | #define CARL9170_MAX_CMD_LEN 64 | ||
43 | #define CARL9170_MAX_CMD_PAYLOAD_LEN 60 | ||
44 | |||
45 | #define CARL9170FW_API_MIN_VER 1 | ||
46 | #define CARL9170FW_API_MAX_VER 1 | ||
47 | |||
48 | enum carl9170_cmd_oids { | ||
49 | CARL9170_CMD_RREG = 0x00, | ||
50 | CARL9170_CMD_WREG = 0x01, | ||
51 | CARL9170_CMD_ECHO = 0x02, | ||
52 | CARL9170_CMD_SWRST = 0x03, | ||
53 | CARL9170_CMD_REBOOT = 0x04, | ||
54 | CARL9170_CMD_BCN_CTRL = 0x05, | ||
55 | CARL9170_CMD_READ_TSF = 0x06, | ||
56 | |||
57 | /* CAM */ | ||
58 | CARL9170_CMD_EKEY = 0x10, | ||
59 | CARL9170_CMD_DKEY = 0x11, | ||
60 | |||
61 | /* RF / PHY */ | ||
62 | CARL9170_CMD_FREQUENCY = 0x20, | ||
63 | CARL9170_CMD_RF_INIT = 0x21, | ||
64 | CARL9170_CMD_SYNTH = 0x22, | ||
65 | CARL9170_CMD_FREQ_START = 0x23, | ||
66 | CARL9170_CMD_PSM = 0x24, | ||
67 | |||
68 | /* Asychronous command flag */ | ||
69 | CARL9170_CMD_ASYNC_FLAG = 0x40, | ||
70 | CARL9170_CMD_WREG_ASYNC = (CARL9170_CMD_WREG | | ||
71 | CARL9170_CMD_ASYNC_FLAG), | ||
72 | CARL9170_CMD_REBOOT_ASYNC = (CARL9170_CMD_REBOOT | | ||
73 | CARL9170_CMD_ASYNC_FLAG), | ||
74 | CARL9170_CMD_BCN_CTRL_ASYNC = (CARL9170_CMD_BCN_CTRL | | ||
75 | CARL9170_CMD_ASYNC_FLAG), | ||
76 | CARL9170_CMD_PSM_ASYNC = (CARL9170_CMD_PSM | | ||
77 | CARL9170_CMD_ASYNC_FLAG), | ||
78 | |||
79 | /* responses and traps */ | ||
80 | CARL9170_RSP_FLAG = 0xc0, | ||
81 | CARL9170_RSP_PRETBTT = 0xc0, | ||
82 | CARL9170_RSP_TXCOMP = 0xc1, | ||
83 | CARL9170_RSP_BEACON_CONFIG = 0xc2, | ||
84 | CARL9170_RSP_ATIM = 0xc3, | ||
85 | CARL9170_RSP_WATCHDOG = 0xc6, | ||
86 | CARL9170_RSP_TEXT = 0xca, | ||
87 | CARL9170_RSP_HEXDUMP = 0xcc, | ||
88 | CARL9170_RSP_RADAR = 0xcd, | ||
89 | CARL9170_RSP_GPIO = 0xce, | ||
90 | CARL9170_RSP_BOOT = 0xcf, | ||
91 | }; | ||
92 | |||
93 | struct carl9170_set_key_cmd { | ||
94 | __le16 user; | ||
95 | __le16 keyId; | ||
96 | __le16 type; | ||
97 | u8 macAddr[6]; | ||
98 | u32 key[4]; | ||
99 | } __packed; | ||
100 | #define CARL9170_SET_KEY_CMD_SIZE 28 | ||
101 | |||
102 | struct carl9170_disable_key_cmd { | ||
103 | __le16 user; | ||
104 | __le16 padding; | ||
105 | } __packed; | ||
106 | #define CARL9170_DISABLE_KEY_CMD_SIZE 4 | ||
107 | |||
108 | struct carl9170_u32_list { | ||
109 | u32 vals[0]; | ||
110 | } __packed; | ||
111 | |||
112 | struct carl9170_reg_list { | ||
113 | __le32 regs[0]; | ||
114 | } __packed; | ||
115 | |||
116 | struct carl9170_write_reg { | ||
117 | struct { | ||
118 | __le32 addr; | ||
119 | __le32 val; | ||
120 | } regs[0] __packed; | ||
121 | } __packed; | ||
122 | |||
123 | #define CARL9170FW_PHY_HT_ENABLE 0x4 | ||
124 | #define CARL9170FW_PHY_HT_DYN2040 0x8 | ||
125 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3 | ||
126 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF_S 2 | ||
127 | |||
128 | struct carl9170_rf_init { | ||
129 | __le32 freq; | ||
130 | u8 ht_settings; | ||
131 | u8 padding2[3]; | ||
132 | __le32 delta_slope_coeff_exp; | ||
133 | __le32 delta_slope_coeff_man; | ||
134 | __le32 delta_slope_coeff_exp_shgi; | ||
135 | __le32 delta_slope_coeff_man_shgi; | ||
136 | __le32 finiteLoopCount; | ||
137 | } __packed; | ||
138 | #define CARL9170_RF_INIT_SIZE 28 | ||
139 | |||
140 | struct carl9170_rf_init_result { | ||
141 | __le32 ret; /* AR9170_PHY_REG_AGC_CONTROL */ | ||
142 | } __packed; | ||
143 | #define CARL9170_RF_INIT_RESULT_SIZE 4 | ||
144 | |||
145 | #define CARL9170_PSM_SLEEP 0x1000 | ||
146 | #define CARL9170_PSM_SOFTWARE 0 | ||
147 | #define CARL9170_PSM_WAKE 0 /* internally used. */ | ||
148 | #define CARL9170_PSM_COUNTER 0xfff | ||
149 | #define CARL9170_PSM_COUNTER_S 0 | ||
150 | |||
151 | struct carl9170_psm { | ||
152 | __le32 state; | ||
153 | } __packed; | ||
154 | #define CARL9170_PSM_SIZE 4 | ||
155 | |||
156 | struct carl9170_bcn_ctrl_cmd { | ||
157 | __le32 vif_id; | ||
158 | __le32 mode; | ||
159 | __le32 bcn_addr; | ||
160 | __le32 bcn_len; | ||
161 | } __packed; | ||
162 | #define CARL9170_BCN_CTRL_CMD_SIZE 16 | ||
163 | |||
164 | #define CARL9170_BCN_CTRL_DRAIN 0 | ||
165 | #define CARL9170_BCN_CTRL_CAB_TRIGGER 1 | ||
166 | |||
167 | struct carl9170_cmd_head { | ||
168 | union { | ||
169 | struct { | ||
170 | u8 len; | ||
171 | u8 cmd; | ||
172 | u8 seq; | ||
173 | u8 ext; | ||
174 | } __packed; | ||
175 | |||
176 | u32 hdr_data; | ||
177 | } __packed; | ||
178 | } __packed; | ||
179 | |||
180 | struct carl9170_cmd { | ||
181 | struct carl9170_cmd_head hdr; | ||
182 | union { | ||
183 | struct carl9170_set_key_cmd setkey; | ||
184 | struct carl9170_disable_key_cmd disablekey; | ||
185 | struct carl9170_u32_list echo; | ||
186 | struct carl9170_reg_list rreg; | ||
187 | struct carl9170_write_reg wreg; | ||
188 | struct carl9170_rf_init rf_init; | ||
189 | struct carl9170_psm psm; | ||
190 | struct carl9170_bcn_ctrl_cmd bcn_ctrl; | ||
191 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; | ||
192 | } __packed; | ||
193 | } __packed; | ||
194 | |||
195 | #define CARL9170_TX_STATUS_QUEUE 3 | ||
196 | #define CARL9170_TX_STATUS_QUEUE_S 0 | ||
197 | #define CARL9170_TX_STATUS_RIX_S 2 | ||
198 | #define CARL9170_TX_STATUS_RIX (3 << CARL9170_TX_STATUS_RIX_S) | ||
199 | #define CARL9170_TX_STATUS_TRIES_S 4 | ||
200 | #define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S) | ||
201 | #define CARL9170_TX_STATUS_SUCCESS 0x80 | ||
202 | |||
203 | /* | ||
204 | * NOTE: | ||
205 | * Both structs [carl9170_tx_status and _carl9170_tx_status] | ||
206 | * need to be "bit for bit" in sync. | ||
207 | */ | ||
208 | struct carl9170_tx_status { | ||
209 | /* | ||
210 | * Beware of compiler bugs in all gcc pre 4.4! | ||
211 | */ | ||
212 | |||
213 | u8 cookie; | ||
214 | u8 queue:2; | ||
215 | u8 rix:2; | ||
216 | u8 tries:3; | ||
217 | u8 success:1; | ||
218 | } __packed; | ||
219 | struct _carl9170_tx_status { | ||
220 | /* | ||
221 | * This version should be immune to all alignment bugs. | ||
222 | */ | ||
223 | |||
224 | u8 cookie; | ||
225 | u8 info; | ||
226 | } __packed; | ||
227 | #define CARL9170_TX_STATUS_SIZE 2 | ||
228 | |||
229 | #define CARL9170_RSP_TX_STATUS_NUM (CARL9170_MAX_CMD_PAYLOAD_LEN / \ | ||
230 | sizeof(struct _carl9170_tx_status)) | ||
231 | |||
232 | #define CARL9170_TX_MAX_RATE_TRIES 7 | ||
233 | |||
234 | #define CARL9170_TX_MAX_RATES 4 | ||
235 | #define CARL9170_TX_MAX_RETRY_RATES (CARL9170_TX_MAX_RATES - 1) | ||
236 | #define CARL9170_ERR_MAGIC "ERR:" | ||
237 | #define CARL9170_BUG_MAGIC "BUG:" | ||
238 | |||
239 | struct carl9170_gpio { | ||
240 | __le32 gpio; | ||
241 | } __packed; | ||
242 | #define CARL9170_GPIO_SIZE 4 | ||
243 | |||
244 | struct carl9170_tsf_rsp { | ||
245 | union { | ||
246 | __le32 tsf[2]; | ||
247 | __le64 tsf_64; | ||
248 | } __packed; | ||
249 | } __packed; | ||
250 | #define CARL9170_TSF_RSP_SIZE 8 | ||
251 | |||
252 | struct carl9170_rsp { | ||
253 | struct carl9170_cmd_head hdr; | ||
254 | |||
255 | union { | ||
256 | struct carl9170_rf_init_result rf_init_res; | ||
257 | struct carl9170_u32_list rreg_res; | ||
258 | struct carl9170_u32_list echo; | ||
259 | struct carl9170_tx_status tx_status[0]; | ||
260 | struct _carl9170_tx_status _tx_status[0]; | ||
261 | struct carl9170_gpio gpio; | ||
262 | struct carl9170_tsf_rsp tsf; | ||
263 | struct carl9170_psm psm; | ||
264 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; | ||
265 | } __packed; | ||
266 | } __packed; | ||
267 | |||
268 | #endif /* __CARL9170_SHARED_FWCMD_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h new file mode 100644 index 000000000000..7cd811708fe5 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * Shared CARL9170 Header | ||
3 | * | ||
4 | * Firmware descriptor format | ||
5 | * | ||
6 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU 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; see the file COPYING. If not, see | ||
19 | * http://www.gnu.org/licenses/. | ||
20 | */ | ||
21 | |||
22 | #ifndef __CARL9170_SHARED_FWDESC_H | ||
23 | #define __CARL9170_SHARED_FWDESC_H | ||
24 | |||
25 | /* NOTE: Don't mess with the order of the flags! */ | ||
26 | enum carl9170fw_feature_list { | ||
27 | /* Always set */ | ||
28 | CARL9170FW_DUMMY_FEATURE, | ||
29 | |||
30 | /* | ||
31 | * Indicates that this image has special boot block which prevents | ||
32 | * legacy drivers to drive the firmware. | ||
33 | */ | ||
34 | CARL9170FW_MINIBOOT, | ||
35 | |||
36 | /* usb registers are initialized by the firmware */ | ||
37 | CARL9170FW_USB_INIT_FIRMWARE, | ||
38 | |||
39 | /* command traps & notifications are send through EP2 */ | ||
40 | CARL9170FW_USB_RESP_EP2, | ||
41 | |||
42 | /* usb download (app -> fw) stream */ | ||
43 | CARL9170FW_USB_DOWN_STREAM, | ||
44 | |||
45 | /* usb upload (fw -> app) stream */ | ||
46 | CARL9170FW_USB_UP_STREAM, | ||
47 | |||
48 | /* unusable - reserved to flag non-functional debug firmwares */ | ||
49 | CARL9170FW_UNUSABLE, | ||
50 | |||
51 | /* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */ | ||
52 | CARL9170FW_COMMAND_PHY, | ||
53 | |||
54 | /* AR9170_CMD_EKEY, AR9170_CMD_DKEY */ | ||
55 | CARL9170FW_COMMAND_CAM, | ||
56 | |||
57 | /* Firmware has a software Content After Beacon Queueing mechanism */ | ||
58 | CARL9170FW_WLANTX_CAB, | ||
59 | |||
60 | /* The firmware is capable of responding to incoming BAR frames */ | ||
61 | CARL9170FW_HANDLE_BACK_REQ, | ||
62 | |||
63 | /* GPIO Interrupt | CARL9170_RSP_GPIO */ | ||
64 | CARL9170FW_GPIO_INTERRUPT, | ||
65 | |||
66 | /* Firmware PSM support | CARL9170_CMD_PSM */ | ||
67 | CARL9170FW_PSM, | ||
68 | |||
69 | /* KEEP LAST */ | ||
70 | __CARL9170FW_FEATURE_NUM | ||
71 | }; | ||
72 | |||
73 | #define OTUS_MAGIC "OTAR" | ||
74 | #define MOTD_MAGIC "MOTD" | ||
75 | #define FIX_MAGIC "FIX\0" | ||
76 | #define DBG_MAGIC "DBG\0" | ||
77 | #define CHK_MAGIC "CHK\0" | ||
78 | #define LAST_MAGIC "LAST" | ||
79 | |||
80 | #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) | ||
81 | #define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31) | ||
82 | #define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372) | ||
83 | |||
84 | #define CARL9170FW_GET_DAY(d) (((d) % 31) + 1) | ||
85 | #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) | ||
86 | #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) | ||
87 | |||
88 | struct carl9170fw_desc_head { | ||
89 | u8 magic[4]; | ||
90 | __le16 length; | ||
91 | u8 min_ver; | ||
92 | u8 cur_ver; | ||
93 | } __packed; | ||
94 | #define CARL9170FW_DESC_HEAD_SIZE \ | ||
95 | (sizeof(struct carl9170fw_desc_head)) | ||
96 | |||
97 | #define CARL9170FW_OTUS_DESC_MIN_VER 6 | ||
98 | #define CARL9170FW_OTUS_DESC_CUR_VER 6 | ||
99 | struct carl9170fw_otus_desc { | ||
100 | struct carl9170fw_desc_head head; | ||
101 | __le32 feature_set; | ||
102 | __le32 fw_address; | ||
103 | __le32 bcn_addr; | ||
104 | __le16 bcn_len; | ||
105 | __le16 miniboot_size; | ||
106 | __le16 tx_frag_len; | ||
107 | __le16 rx_max_frame_len; | ||
108 | u8 tx_descs; | ||
109 | u8 cmd_bufs; | ||
110 | u8 api_ver; | ||
111 | u8 vif_num; | ||
112 | } __packed; | ||
113 | #define CARL9170FW_OTUS_DESC_SIZE \ | ||
114 | (sizeof(struct carl9170fw_otus_desc)) | ||
115 | |||
116 | #define CARL9170FW_MOTD_STRING_LEN 24 | ||
117 | #define CARL9170FW_MOTD_RELEASE_LEN 20 | ||
118 | #define CARL9170FW_MOTD_DESC_MIN_VER 1 | ||
119 | #define CARL9170FW_MOTD_DESC_CUR_VER 2 | ||
120 | struct carl9170fw_motd_desc { | ||
121 | struct carl9170fw_desc_head head; | ||
122 | __le32 fw_year_month_day; | ||
123 | char desc[CARL9170FW_MOTD_STRING_LEN]; | ||
124 | char release[CARL9170FW_MOTD_RELEASE_LEN]; | ||
125 | } __packed; | ||
126 | #define CARL9170FW_MOTD_DESC_SIZE \ | ||
127 | (sizeof(struct carl9170fw_motd_desc)) | ||
128 | |||
129 | #define CARL9170FW_FIX_DESC_MIN_VER 1 | ||
130 | #define CARL9170FW_FIX_DESC_CUR_VER 2 | ||
131 | struct carl9170fw_fix_entry { | ||
132 | __le32 address; | ||
133 | __le32 mask; | ||
134 | __le32 value; | ||
135 | } __packed; | ||
136 | |||
137 | struct carl9170fw_fix_desc { | ||
138 | struct carl9170fw_desc_head head; | ||
139 | struct carl9170fw_fix_entry data[0]; | ||
140 | } __packed; | ||
141 | #define CARL9170FW_FIX_DESC_SIZE \ | ||
142 | (sizeof(struct carl9170fw_fix_desc)) | ||
143 | |||
144 | #define CARL9170FW_DBG_DESC_MIN_VER 1 | ||
145 | #define CARL9170FW_DBG_DESC_CUR_VER 2 | ||
146 | struct carl9170fw_dbg_desc { | ||
147 | struct carl9170fw_desc_head head; | ||
148 | |||
149 | __le32 bogoclock_addr; | ||
150 | __le32 counter_addr; | ||
151 | __le32 rx_total_addr; | ||
152 | __le32 rx_overrun_addr; | ||
153 | |||
154 | /* Put your debugging definitions here */ | ||
155 | } __packed; | ||
156 | #define CARL9170FW_DBG_DESC_SIZE \ | ||
157 | (sizeof(struct carl9170fw_dbg_desc)) | ||
158 | |||
159 | #define CARL9170FW_CHK_DESC_MIN_VER 1 | ||
160 | #define CARL9170FW_CHK_DESC_CUR_VER 2 | ||
161 | struct carl9170fw_chk_desc { | ||
162 | struct carl9170fw_desc_head head; | ||
163 | __le32 fw_crc32; | ||
164 | __le32 hdr_crc32; | ||
165 | } __packed; | ||
166 | #define CARL9170FW_CHK_DESC_SIZE \ | ||
167 | (sizeof(struct carl9170fw_chk_desc)) | ||
168 | |||
169 | #define CARL9170FW_LAST_DESC_MIN_VER 1 | ||
170 | #define CARL9170FW_LAST_DESC_CUR_VER 2 | ||
171 | struct carl9170fw_last_desc { | ||
172 | struct carl9170fw_desc_head head; | ||
173 | } __packed; | ||
174 | #define CARL9170FW_LAST_DESC_SIZE \ | ||
175 | (sizeof(struct carl9170fw_fix_desc)) | ||
176 | |||
177 | #define CARL9170FW_DESC_MAX_LENGTH 8192 | ||
178 | |||
179 | #define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \ | ||
180 | .head = { \ | ||
181 | .magic = _magic, \ | ||
182 | .length = cpu_to_le16(_length), \ | ||
183 | .min_ver = _min_ver, \ | ||
184 | .cur_ver = _cur_ver, \ | ||
185 | } | ||
186 | |||
187 | static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, | ||
188 | u8 magic[4], __le16 length, | ||
189 | u8 min_ver, u8 cur_ver) | ||
190 | { | ||
191 | head->magic[0] = magic[0]; | ||
192 | head->magic[1] = magic[1]; | ||
193 | head->magic[2] = magic[2]; | ||
194 | head->magic[3] = magic[3]; | ||
195 | |||
196 | head->length = length; | ||
197 | head->min_ver = min_ver; | ||
198 | head->cur_ver = cur_ver; | ||
199 | } | ||
200 | |||
201 | #define carl9170fw_for_each_hdr(desc, fw_desc) \ | ||
202 | for (desc = fw_desc; \ | ||
203 | memcmp(desc->magic, LAST_MAGIC, 4) && \ | ||
204 | le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ | ||
205 | le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ | ||
206 | desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) | ||
207 | |||
208 | #define CHECK_HDR_VERSION(head, _min_ver) \ | ||
209 | (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \ | ||
210 | |||
211 | static inline bool carl9170fw_supports(__le32 list, u8 feature) | ||
212 | { | ||
213 | return le32_to_cpu(list) & BIT(feature); | ||
214 | } | ||
215 | |||
216 | static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, | ||
217 | const u8 descid[4], u16 min_len, | ||
218 | u8 compatible_revision) | ||
219 | { | ||
220 | if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && | ||
221 | descid[2] == head->magic[2] && descid[3] == head->magic[3] && | ||
222 | !CHECK_HDR_VERSION(head, compatible_revision) && | ||
223 | (le16_to_cpu(head->length) >= min_len)) | ||
224 | return true; | ||
225 | |||
226 | return false; | ||
227 | } | ||
228 | |||
229 | #define CARL9170FW_MIN_SIZE 32 | ||
230 | #define CARL9170FW_MAX_SIZE 16384 | ||
231 | |||
232 | static inline bool carl9170fw_size_check(unsigned int len) | ||
233 | { | ||
234 | return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE); | ||
235 | } | ||
236 | |||
237 | #endif /* __CARL9170_SHARED_FWDESC_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h new file mode 100644 index 000000000000..b1292ac5b703 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -0,0 +1,736 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * Register map, hardware-specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_HW_H | ||
40 | #define __CARL9170_SHARED_HW_H | ||
41 | |||
42 | /* High Speed UART */ | ||
43 | #define AR9170_UART_REG_BASE 0x1c0000 | ||
44 | |||
45 | /* Definitions of interrupt registers */ | ||
46 | #define AR9170_UART_REG_RX_BUFFER (AR9170_UART_REG_BASE + 0x000) | ||
47 | #define AR9170_UART_REG_TX_HOLDING (AR9170_UART_REG_BASE + 0x004) | ||
48 | #define AR9170_UART_REG_FIFO_CONTROL (AR9170_UART_REG_BASE + 0x010) | ||
49 | #define AR9170_UART_FIFO_CTRL_RESET_RX_FIFO 0x02 | ||
50 | #define AR9170_UART_FIFO_CTRL_RESET_TX_FIFO 0x04 | ||
51 | |||
52 | #define AR9170_UART_REG_LINE_CONTROL (AR9170_UART_REG_BASE + 0x014) | ||
53 | #define AR9170_UART_REG_MODEM_CONTROL (AR9170_UART_REG_BASE + 0x018) | ||
54 | #define AR9170_UART_MODEM_CTRL_DTR_BIT 0x01 | ||
55 | #define AR9170_UART_MODEM_CTRL_RTS_BIT 0x02 | ||
56 | #define AR9170_UART_MODEM_CTRL_INTERNAL_LOOP_BACK 0x10 | ||
57 | #define AR9170_UART_MODEM_CTRL_AUTO_RTS 0x20 | ||
58 | #define AR9170_UART_MODEM_CTRL_AUTO_CTR 0x40 | ||
59 | |||
60 | #define AR9170_UART_REG_LINE_STATUS (AR9170_UART_REG_BASE + 0x01c) | ||
61 | #define AR9170_UART_LINE_STS_RX_DATA_READY 0x01 | ||
62 | #define AR9170_UART_LINE_STS_RX_BUFFER_OVERRUN 0x02 | ||
63 | #define AR9170_UART_LINE_STS_RX_BREAK_IND 0x10 | ||
64 | #define AR9170_UART_LINE_STS_TX_FIFO_NEAR_EMPTY 0x20 | ||
65 | #define AR9170_UART_LINE_STS_TRANSMITTER_EMPTY 0x40 | ||
66 | |||
67 | #define AR9170_UART_REG_MODEM_STATUS (AR9170_UART_REG_BASE + 0x020) | ||
68 | #define AR9170_UART_MODEM_STS_CTS_CHANGE 0x01 | ||
69 | #define AR9170_UART_MODEM_STS_DSR_CHANGE 0x02 | ||
70 | #define AR9170_UART_MODEM_STS_DCD_CHANGE 0x08 | ||
71 | #define AR9170_UART_MODEM_STS_CTS_COMPL 0x10 | ||
72 | #define AR9170_UART_MODEM_STS_DSR_COMPL 0x20 | ||
73 | #define AR9170_UART_MODEM_STS_DCD_COMPL 0x80 | ||
74 | |||
75 | #define AR9170_UART_REG_SCRATCH (AR9170_UART_REG_BASE + 0x024) | ||
76 | #define AR9170_UART_REG_DIVISOR_LSB (AR9170_UART_REG_BASE + 0x028) | ||
77 | #define AR9170_UART_REG_DIVISOR_MSB (AR9170_UART_REG_BASE + 0x02c) | ||
78 | #define AR9170_UART_REG_WORD_RX_BUFFER (AR9170_UART_REG_BASE + 0x034) | ||
79 | #define AR9170_UART_REG_WORD_TX_HOLDING (AR9170_UART_REG_BASE + 0x038) | ||
80 | #define AR9170_UART_REG_FIFO_COUNT (AR9170_UART_REG_BASE + 0x03c) | ||
81 | #define AR9170_UART_REG_REMAINDER (AR9170_UART_REG_BASE + 0x04c) | ||
82 | |||
83 | /* Timer */ | ||
84 | #define AR9170_TIMER_REG_BASE 0x1c1000 | ||
85 | |||
86 | #define AR9170_TIMER_REG_WATCH_DOG (AR9170_TIMER_REG_BASE + 0x000) | ||
87 | #define AR9170_TIMER_REG_TIMER0 (AR9170_TIMER_REG_BASE + 0x010) | ||
88 | #define AR9170_TIMER_REG_TIMER1 (AR9170_TIMER_REG_BASE + 0x014) | ||
89 | #define AR9170_TIMER_REG_TIMER2 (AR9170_TIMER_REG_BASE + 0x018) | ||
90 | #define AR9170_TIMER_REG_TIMER3 (AR9170_TIMER_REG_BASE + 0x01c) | ||
91 | #define AR9170_TIMER_REG_TIMER4 (AR9170_TIMER_REG_BASE + 0x020) | ||
92 | #define AR9170_TIMER_REG_CONTROL (AR9170_TIMER_REG_BASE + 0x024) | ||
93 | #define AR9170_TIMER_CTRL_DISABLE_CLOCK 0x100 | ||
94 | |||
95 | #define AR9170_TIMER_REG_INTERRUPT (AR9170_TIMER_REG_BASE + 0x028) | ||
96 | #define AR9170_TIMER_INT_TIMER0 0x001 | ||
97 | #define AR9170_TIMER_INT_TIMER1 0x002 | ||
98 | #define AR9170_TIMER_INT_TIMER2 0x004 | ||
99 | #define AR9170_TIMER_INT_TIMER3 0x008 | ||
100 | #define AR9170_TIMER_INT_TIMER4 0x010 | ||
101 | #define AR9170_TIMER_INT_TICK_TIMER 0x100 | ||
102 | |||
103 | #define AR9170_TIMER_REG_TICK_TIMER (AR9170_TIMER_REG_BASE + 0x030) | ||
104 | #define AR9170_TIMER_REG_CLOCK_LOW (AR9170_TIMER_REG_BASE + 0x040) | ||
105 | #define AR9170_TIMER_REG_CLOCK_HIGH (AR9170_TIMER_REG_BASE + 0x044) | ||
106 | |||
107 | #define AR9170_MAC_REG_BASE 0x1c3000 | ||
108 | |||
109 | #define AR9170_MAC_REG_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x500) | ||
110 | #define AR9170_MAC_POWER_STATE_CTRL_RESET 0x20 | ||
111 | |||
112 | #define AR9170_MAC_REG_MAC_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x50c) | ||
113 | |||
114 | #define AR9170_MAC_REG_INT_CTRL (AR9170_MAC_REG_BASE + 0x510) | ||
115 | #define AR9170_MAC_INT_TXC BIT(0) | ||
116 | #define AR9170_MAC_INT_RXC BIT(1) | ||
117 | #define AR9170_MAC_INT_RETRY_FAIL BIT(2) | ||
118 | #define AR9170_MAC_INT_WAKEUP BIT(3) | ||
119 | #define AR9170_MAC_INT_ATIM BIT(4) | ||
120 | #define AR9170_MAC_INT_DTIM BIT(5) | ||
121 | #define AR9170_MAC_INT_CFG_BCN BIT(6) | ||
122 | #define AR9170_MAC_INT_ABORT BIT(7) | ||
123 | #define AR9170_MAC_INT_QOS BIT(8) | ||
124 | #define AR9170_MAC_INT_MIMO_PS BIT(9) | ||
125 | #define AR9170_MAC_INT_KEY_GEN BIT(10) | ||
126 | #define AR9170_MAC_INT_DECRY_NOUSER BIT(11) | ||
127 | #define AR9170_MAC_INT_RADAR BIT(12) | ||
128 | #define AR9170_MAC_INT_QUIET_FRAME BIT(13) | ||
129 | #define AR9170_MAC_INT_PRETBTT BIT(14) | ||
130 | |||
131 | #define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) | ||
132 | #define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) | ||
133 | |||
134 | #define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51c) | ||
135 | #define AR9170_MAC_ATIM_PERIOD_S 0 | ||
136 | #define AR9170_MAC_ATIM_PERIOD 0x0000ffff | ||
137 | |||
138 | #define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) | ||
139 | #define AR9170_MAC_BCN_PERIOD_S 0 | ||
140 | #define AR9170_MAC_BCN_PERIOD 0x0000ffff | ||
141 | #define AR9170_MAC_BCN_DTIM_S 16 | ||
142 | #define AR9170_MAC_BCN_DTIM 0x00ff0000 | ||
143 | #define AR9170_MAC_BCN_AP_MODE BIT(24) | ||
144 | #define AR9170_MAC_BCN_IBSS_MODE BIT(25) | ||
145 | #define AR9170_MAC_BCN_PWR_MGT BIT(26) | ||
146 | #define AR9170_MAC_BCN_STA_PS BIT(27) | ||
147 | |||
148 | #define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) | ||
149 | #define AR9170_MAC_PRETBTT_S 0 | ||
150 | #define AR9170_MAC_PRETBTT 0x0000ffff | ||
151 | #define AR9170_MAC_PRETBTT2_S 16 | ||
152 | #define AR9170_MAC_PRETBTT2 0xffff0000 | ||
153 | |||
154 | #define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) | ||
155 | #define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) | ||
156 | #define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) | ||
157 | #define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) | ||
158 | |||
159 | #define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) | ||
160 | #define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) | ||
161 | |||
162 | #define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62c) | ||
163 | |||
164 | #define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) | ||
165 | #define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) | ||
166 | #define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) | ||
167 | #define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) | ||
168 | #define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) | ||
169 | #define AR9170_MAC_REG_AFTER_PNP (AR9170_MAC_REG_BASE + 0x648) | ||
170 | #define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64c) | ||
171 | |||
172 | #define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) | ||
173 | #define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) | ||
174 | #define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0) | ||
175 | #define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000 | ||
176 | #define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) | ||
177 | #define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3) | ||
178 | #define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70 | ||
179 | |||
180 | #define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) | ||
181 | #define AR9170_MAC_REG_MISC_684 (AR9170_MAC_REG_BASE + 0x684) | ||
182 | #define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) | ||
183 | |||
184 | #define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) | ||
185 | #define AR9170_MAC_FTF_ASSOC_REQ BIT(0) | ||
186 | #define AR9170_MAC_FTF_ASSOC_RESP BIT(1) | ||
187 | #define AR9170_MAC_FTF_REASSOC_REQ BIT(2) | ||
188 | #define AR9170_MAC_FTF_REASSOC_RESP BIT(3) | ||
189 | #define AR9170_MAC_FTF_PRB_REQ BIT(4) | ||
190 | #define AR9170_MAC_FTF_PRB_RESP BIT(5) | ||
191 | #define AR9170_MAC_FTF_BIT6 BIT(6) | ||
192 | #define AR9170_MAC_FTF_BIT7 BIT(7) | ||
193 | #define AR9170_MAC_FTF_BEACON BIT(8) | ||
194 | #define AR9170_MAC_FTF_ATIM BIT(9) | ||
195 | #define AR9170_MAC_FTF_DEASSOC BIT(10) | ||
196 | #define AR9170_MAC_FTF_AUTH BIT(11) | ||
197 | #define AR9170_MAC_FTF_DEAUTH BIT(12) | ||
198 | #define AR9170_MAC_FTF_BIT13 BIT(13) | ||
199 | #define AR9170_MAC_FTF_BIT14 BIT(14) | ||
200 | #define AR9170_MAC_FTF_BIT15 BIT(15) | ||
201 | #define AR9170_MAC_FTF_BAR BIT(24) | ||
202 | #define AR9170_MAC_FTF_BA BIT(25) | ||
203 | #define AR9170_MAC_FTF_PSPOLL BIT(26) | ||
204 | #define AR9170_MAC_FTF_RTS BIT(27) | ||
205 | #define AR9170_MAC_FTF_CTS BIT(28) | ||
206 | #define AR9170_MAC_FTF_ACK BIT(29) | ||
207 | #define AR9170_MAC_FTF_CFE BIT(30) | ||
208 | #define AR9170_MAC_FTF_CFE_ACK BIT(31) | ||
209 | #define AR9170_MAC_FTF_DEFAULTS 0x0500ffff | ||
210 | #define AR9170_MAC_FTF_MONITOR 0xff00ffff | ||
211 | |||
212 | #define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) | ||
213 | #define AR9170_MAC_REG_ACK_TPC (AR9170_MAC_REG_BASE + 0x694) | ||
214 | #define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) | ||
215 | #define AR9170_MAC_REG_RX_TIMEOUT_COUNT (AR9170_MAC_REG_BASE + 0x69c) | ||
216 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6a0) | ||
217 | #define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6a4) | ||
218 | #define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6a8) | ||
219 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6ac) | ||
220 | #define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6b0) | ||
221 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6bc) | ||
222 | #define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0) | ||
223 | #define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4) | ||
224 | #define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8) | ||
225 | #define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc) | ||
226 | |||
227 | #define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4) | ||
228 | |||
229 | #define AR9170_MAC_REG_CHANNEL_BUSY (AR9170_MAC_REG_BASE + 0x6e8) | ||
230 | #define AR9170_MAC_REG_EXT_BUSY (AR9170_MAC_REG_BASE + 0x6ec) | ||
231 | |||
232 | #define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6f0) | ||
233 | #define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6f4) | ||
234 | #define AR9170_MAC_REG_ACK_FC (AR9170_MAC_REG_BASE + 0x6f8) | ||
235 | |||
236 | #define AR9170_MAC_REG_CAM_MODE (AR9170_MAC_REG_BASE + 0x700) | ||
237 | #define AR9170_MAC_CAM_IBSS 0xe0 | ||
238 | #define AR9170_MAC_CAM_AP 0xa1 | ||
239 | #define AR9170_MAC_CAM_STA 0x2 | ||
240 | #define AR9170_MAC_CAM_AP_WDS 0x3 | ||
241 | #define AR9170_MAC_CAM_DEFAULTS (0xf << 24) | ||
242 | #define AR9170_MAC_CAM_HOST_PENDING 0x80000000 | ||
243 | |||
244 | #define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) | ||
245 | #define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) | ||
246 | |||
247 | #define AR9170_MAC_REG_CAM_ADDR (AR9170_MAC_REG_BASE + 0x70c) | ||
248 | #define AR9170_MAC_CAM_ADDR_WRITE 0x80000000 | ||
249 | #define AR9170_MAC_REG_CAM_DATA0 (AR9170_MAC_REG_BASE + 0x720) | ||
250 | #define AR9170_MAC_REG_CAM_DATA1 (AR9170_MAC_REG_BASE + 0x724) | ||
251 | #define AR9170_MAC_REG_CAM_DATA2 (AR9170_MAC_REG_BASE + 0x728) | ||
252 | #define AR9170_MAC_REG_CAM_DATA3 (AR9170_MAC_REG_BASE + 0x72c) | ||
253 | |||
254 | #define AR9170_MAC_REG_CAM_DBG0 (AR9170_MAC_REG_BASE + 0x730) | ||
255 | #define AR9170_MAC_REG_CAM_DBG1 (AR9170_MAC_REG_BASE + 0x734) | ||
256 | #define AR9170_MAC_REG_CAM_DBG2 (AR9170_MAC_REG_BASE + 0x738) | ||
257 | #define AR9170_MAC_REG_CAM_STATE (AR9170_MAC_REG_BASE + 0x73c) | ||
258 | #define AR9170_MAC_CAM_STATE_READ_PENDING 0x40000000 | ||
259 | #define AR9170_MAC_CAM_STATE_WRITE_PENDING 0x80000000 | ||
260 | |||
261 | #define AR9170_MAC_REG_CAM_TXKEY (AR9170_MAC_REG_BASE + 0x740) | ||
262 | #define AR9170_MAC_REG_CAM_RXKEY (AR9170_MAC_REG_BASE + 0x750) | ||
263 | |||
264 | #define AR9170_MAC_REG_CAM_TX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x760) | ||
265 | #define AR9170_MAC_REG_CAM_RX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x770) | ||
266 | #define AR9170_MAC_REG_CAM_TX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x780) | ||
267 | #define AR9170_MAC_REG_CAM_RX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x790) | ||
268 | |||
269 | #define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xb00) | ||
270 | #define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xb04) | ||
271 | #define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xb08) | ||
272 | #define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xb0c) | ||
273 | #define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xb10) | ||
274 | #define AR9170_MAC_REG_AC2_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xb14) | ||
275 | #define AR9170_MAC_REG_AC4_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xb18) | ||
276 | #define AR9170_MAC_REG_TXOP_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0xb1c) | ||
277 | #define AR9170_MAC_REG_TXOP_ACK_INTERVAL (AR9170_MAC_REG_BASE + 0xb20) | ||
278 | #define AR9170_MAC_REG_CONTENTION_POINT (AR9170_MAC_REG_BASE + 0xb24) | ||
279 | #define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xb28) | ||
280 | #define AR9170_MAC_REG_TID_CFACK_CFEND_RATE (AR9170_MAC_REG_BASE + 0xb2c) | ||
281 | #define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xb30) | ||
282 | #define AR9170_MAC_REG_TKIP_TSC (AR9170_MAC_REG_BASE + 0xb34) | ||
283 | #define AR9170_MAC_REG_TXOP_DURATION (AR9170_MAC_REG_BASE + 0xb38) | ||
284 | #define AR9170_MAC_REG_TX_QOS_THRESHOLD (AR9170_MAC_REG_BASE + 0xb3c) | ||
285 | #define AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA (AR9170_MAC_REG_BASE + 0xb40) | ||
286 | #define AR9170_MAC_VIRTUAL_CCA_Q0 BIT(15) | ||
287 | #define AR9170_MAC_VIRTUAL_CCA_Q1 BIT(16) | ||
288 | #define AR9170_MAC_VIRTUAL_CCA_Q2 BIT(17) | ||
289 | #define AR9170_MAC_VIRTUAL_CCA_Q3 BIT(18) | ||
290 | #define AR9170_MAC_VIRTUAL_CCA_Q4 BIT(19) | ||
291 | #define AR9170_MAC_VIRTUAL_CCA_ALL (0xf8000) | ||
292 | |||
293 | #define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xb44) | ||
294 | #define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xb48) | ||
295 | |||
296 | #define AR9170_MAC_REG_AMPDU_COUNT (AR9170_MAC_REG_BASE + 0xb88) | ||
297 | #define AR9170_MAC_REG_MPDU_COUNT (AR9170_MAC_REG_BASE + 0xb8c) | ||
298 | |||
299 | #define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xb9c) | ||
300 | #define AR9170_MAC_AMPDU_FACTOR 0x7f0000 | ||
301 | #define AR9170_MAC_AMPDU_FACTOR_S 16 | ||
302 | #define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xba0) | ||
303 | #define AR9170_MAC_AMPDU_DENSITY 0x7 | ||
304 | #define AR9170_MAC_AMPDU_DENSITY_S 0 | ||
305 | |||
306 | #define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xbb0) | ||
307 | #define AR9170_MAC_FCS_SWFCS 0x1 | ||
308 | #define AR9170_MAC_FCS_FIFO_PROT 0x4 | ||
309 | |||
310 | #define AR9170_MAC_REG_RTS_CTS_TPC (AR9170_MAC_REG_BASE + 0xbb4) | ||
311 | #define AR9170_MAC_REG_CFEND_QOSNULL_TPC (AR9170_MAC_REG_BASE + 0xbb8) | ||
312 | |||
313 | #define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xc00) | ||
314 | #define AR9170_MAC_REG_RX_CONTROL (AR9170_MAC_REG_BASE + 0xc40) | ||
315 | #define AR9170_MAC_RX_CTRL_DEAGG 0x1 | ||
316 | #define AR9170_MAC_RX_CTRL_SHORT_FILTER 0x2 | ||
317 | #define AR9170_MAC_RX_CTRL_SA_DA_SEARCH 0x20 | ||
318 | #define AR9170_MAC_RX_CTRL_PASS_TO_HOST BIT(28) | ||
319 | #define AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER BIT(30) | ||
320 | |||
321 | #define AR9170_MAC_REG_RX_CONTROL_1 (AR9170_MAC_REG_BASE + 0xc44) | ||
322 | |||
323 | #define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xc50) | ||
324 | |||
325 | #define AR9170_MAC_REG_RX_MPDU (AR9170_MAC_REG_BASE + 0xca0) | ||
326 | #define AR9170_MAC_REG_RX_DROPPED_MPDU (AR9170_MAC_REG_BASE + 0xca4) | ||
327 | #define AR9170_MAC_REG_RX_DEL_MPDU (AR9170_MAC_REG_BASE + 0xca8) | ||
328 | #define AR9170_MAC_REG_RX_PHY_MISC_ERROR (AR9170_MAC_REG_BASE + 0xcac) | ||
329 | #define AR9170_MAC_REG_RX_PHY_XR_ERROR (AR9170_MAC_REG_BASE + 0xcb0) | ||
330 | #define AR9170_MAC_REG_RX_PHY_OFDM_ERROR (AR9170_MAC_REG_BASE + 0xcb4) | ||
331 | #define AR9170_MAC_REG_RX_PHY_CCK_ERROR (AR9170_MAC_REG_BASE + 0xcb8) | ||
332 | #define AR9170_MAC_REG_RX_PHY_HT_ERROR (AR9170_MAC_REG_BASE + 0xcbc) | ||
333 | #define AR9170_MAC_REG_RX_PHY_TOTAL (AR9170_MAC_REG_BASE + 0xcc0) | ||
334 | |||
335 | #define AR9170_MAC_REG_DMA_TXQ_ADDR (AR9170_MAC_REG_BASE + 0xd00) | ||
336 | #define AR9170_MAC_REG_DMA_TXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04) | ||
337 | #define AR9170_MAC_REG_DMA_TXQ0_ADDR (AR9170_MAC_REG_BASE + 0xd00) | ||
338 | #define AR9170_MAC_REG_DMA_TXQ0_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04) | ||
339 | #define AR9170_MAC_REG_DMA_TXQ1_ADDR (AR9170_MAC_REG_BASE + 0xd08) | ||
340 | #define AR9170_MAC_REG_DMA_TXQ1_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd0c) | ||
341 | #define AR9170_MAC_REG_DMA_TXQ2_ADDR (AR9170_MAC_REG_BASE + 0xd10) | ||
342 | #define AR9170_MAC_REG_DMA_TXQ2_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd14) | ||
343 | #define AR9170_MAC_REG_DMA_TXQ3_ADDR (AR9170_MAC_REG_BASE + 0xd18) | ||
344 | #define AR9170_MAC_REG_DMA_TXQ3_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd1c) | ||
345 | #define AR9170_MAC_REG_DMA_TXQ4_ADDR (AR9170_MAC_REG_BASE + 0xd20) | ||
346 | #define AR9170_MAC_REG_DMA_TXQ4_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd24) | ||
347 | #define AR9170_MAC_REG_DMA_RXQ_ADDR (AR9170_MAC_REG_BASE + 0xd28) | ||
348 | #define AR9170_MAC_REG_DMA_RXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd2c) | ||
349 | |||
350 | #define AR9170_MAC_REG_DMA_TRIGGER (AR9170_MAC_REG_BASE + 0xd30) | ||
351 | #define AR9170_DMA_TRIGGER_TXQ0 BIT(0) | ||
352 | #define AR9170_DMA_TRIGGER_TXQ1 BIT(1) | ||
353 | #define AR9170_DMA_TRIGGER_TXQ2 BIT(2) | ||
354 | #define AR9170_DMA_TRIGGER_TXQ3 BIT(3) | ||
355 | #define AR9170_DMA_TRIGGER_TXQ4 BIT(4) | ||
356 | #define AR9170_DMA_TRIGGER_RXQ BIT(8) | ||
357 | |||
358 | #define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38) | ||
359 | #define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c) | ||
360 | |||
361 | #define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c) | ||
362 | #define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f | ||
363 | #define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 | ||
364 | #define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 | ||
365 | #define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 | ||
366 | |||
367 | #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84) | ||
368 | #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88) | ||
369 | #define AR9170_MAC_BCN_LENGTH_MAX 256 | ||
370 | |||
371 | #define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c) | ||
372 | |||
373 | #define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xd90) | ||
374 | #define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xd94) | ||
375 | #define AR9170_BCN_CTRL_READY 0x01 | ||
376 | #define AR9170_BCN_CTRL_LOCK 0x02 | ||
377 | |||
378 | #define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98) | ||
379 | #define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c) | ||
380 | |||
381 | |||
382 | #define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0) | ||
383 | #define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4) | ||
384 | |||
385 | #define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0) | ||
386 | |||
387 | /* Random number generator */ | ||
388 | #define AR9170_RAND_REG_BASE 0x1d0000 | ||
389 | |||
390 | #define AR9170_RAND_REG_NUM (AR9170_RAND_REG_BASE + 0x000) | ||
391 | #define AR9170_RAND_REG_MODE (AR9170_RAND_REG_BASE + 0x004) | ||
392 | #define AR9170_RAND_MODE_MANUAL 0x000 | ||
393 | #define AR9170_RAND_MODE_FREE 0x001 | ||
394 | |||
395 | /* GPIO */ | ||
396 | #define AR9170_GPIO_REG_BASE 0x1d0100 | ||
397 | #define AR9170_GPIO_REG_PORT_TYPE (AR9170_GPIO_REG_BASE + 0x000) | ||
398 | #define AR9170_GPIO_REG_PORT_DATA (AR9170_GPIO_REG_BASE + 0x004) | ||
399 | #define AR9170_GPIO_PORT_LED_0 1 | ||
400 | #define AR9170_GPIO_PORT_LED_1 2 | ||
401 | /* WPS Button GPIO for TP-Link TL-WN821N */ | ||
402 | #define AR9170_GPIO_PORT_WPS_BUTTON_PRESSED 4 | ||
403 | |||
404 | /* Memory Controller */ | ||
405 | #define AR9170_MC_REG_BASE 0x1d1000 | ||
406 | |||
407 | #define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000) | ||
408 | #define AR9170_MC_REG_SEEPROM_WP0 (AR9170_MC_REG_BASE + 0x400) | ||
409 | #define AR9170_MC_REG_SEEPROM_WP1 (AR9170_MC_REG_BASE + 0x404) | ||
410 | #define AR9170_MC_REG_SEEPROM_WP2 (AR9170_MC_REG_BASE + 0x408) | ||
411 | |||
412 | /* Interrupt Controller */ | ||
413 | #define AR9170_MAX_INT_SRC 9 | ||
414 | #define AR9170_INT_REG_BASE 0x1d2000 | ||
415 | |||
416 | #define AR9170_INT_REG_FLAG (AR9170_INT_REG_BASE + 0x000) | ||
417 | #define AR9170_INT_REG_FIQ_MASK (AR9170_INT_REG_BASE + 0x004) | ||
418 | #define AR9170_INT_REG_IRQ_MASK (AR9170_INT_REG_BASE + 0x008) | ||
419 | /* INT_REG_FLAG, INT_REG_FIQ_MASK and INT_REG_IRQ_MASK */ | ||
420 | #define AR9170_INT_FLAG_WLAN 0x001 | ||
421 | #define AR9170_INT_FLAG_PTAB_BIT 0x002 | ||
422 | #define AR9170_INT_FLAG_SE_BIT 0x004 | ||
423 | #define AR9170_INT_FLAG_UART_BIT 0x008 | ||
424 | #define AR9170_INT_FLAG_TIMER_BIT 0x010 | ||
425 | #define AR9170_INT_FLAG_EXT_BIT 0x020 | ||
426 | #define AR9170_INT_FLAG_SW_BIT 0x040 | ||
427 | #define AR9170_INT_FLAG_USB_BIT 0x080 | ||
428 | #define AR9170_INT_FLAG_ETHERNET_BIT 0x100 | ||
429 | |||
430 | #define AR9170_INT_REG_PRIORITY1 (AR9170_INT_REG_BASE + 0x00c) | ||
431 | #define AR9170_INT_REG_PRIORITY2 (AR9170_INT_REG_BASE + 0x010) | ||
432 | #define AR9170_INT_REG_PRIORITY3 (AR9170_INT_REG_BASE + 0x014) | ||
433 | #define AR9170_INT_REG_EXT_INT_CONTROL (AR9170_INT_REG_BASE + 0x018) | ||
434 | #define AR9170_INT_REG_SW_INT_CONTROL (AR9170_INT_REG_BASE + 0x01c) | ||
435 | #define AR9170_INT_SW_INT_ENABLE 0x1 | ||
436 | |||
437 | #define AR9170_INT_REG_FIQ_ENCODE (AR9170_INT_REG_BASE + 0x020) | ||
438 | #define AR9170_INT_INT_IRQ_ENCODE (AR9170_INT_REG_BASE + 0x024) | ||
439 | |||
440 | /* Power Management */ | ||
441 | #define AR9170_PWR_REG_BASE 0x1d4000 | ||
442 | |||
443 | #define AR9170_PWR_REG_POWER_STATE (AR9170_PWR_REG_BASE + 0x000) | ||
444 | |||
445 | #define AR9170_PWR_REG_RESET (AR9170_PWR_REG_BASE + 0x004) | ||
446 | #define AR9170_PWR_RESET_COMMIT_RESET_MASK BIT(0) | ||
447 | #define AR9170_PWR_RESET_WLAN_MASK BIT(1) | ||
448 | #define AR9170_PWR_RESET_DMA_MASK BIT(2) | ||
449 | #define AR9170_PWR_RESET_BRIDGE_MASK BIT(3) | ||
450 | #define AR9170_PWR_RESET_AHB_MASK BIT(9) | ||
451 | #define AR9170_PWR_RESET_BB_WARM_RESET BIT(10) | ||
452 | #define AR9170_PWR_RESET_BB_COLD_RESET BIT(11) | ||
453 | #define AR9170_PWR_RESET_ADDA_CLK_COLD_RESET BIT(12) | ||
454 | #define AR9170_PWR_RESET_PLL BIT(13) | ||
455 | #define AR9170_PWR_RESET_USB_PLL BIT(14) | ||
456 | |||
457 | #define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) | ||
458 | #define AR9170_PWR_CLK_AHB_40MHZ 0 | ||
459 | #define AR9170_PWR_CLK_AHB_20_22MHZ 1 | ||
460 | #define AR9170_PWR_CLK_AHB_40_44MHZ 2 | ||
461 | #define AR9170_PWR_CLK_AHB_80_88MHZ 3 | ||
462 | #define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 | ||
463 | |||
464 | #define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010) | ||
465 | #define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014) | ||
466 | #define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020) | ||
467 | |||
468 | /* Faraday USB Controller */ | ||
469 | #define AR9170_USB_REG_BASE 0x1e1000 | ||
470 | |||
471 | #define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000) | ||
472 | #define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0) | ||
473 | #define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2) | ||
474 | #define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6) | ||
475 | |||
476 | #define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001) | ||
477 | #define AR9170_USB_DEVICE_ADDRESS_CONFIGURE BIT(7) | ||
478 | |||
479 | #define AR9170_USB_REG_TEST (AR9170_USB_REG_BASE + 0x002) | ||
480 | #define AR9170_USB_REG_PHY_TEST_SELECT (AR9170_USB_REG_BASE + 0x008) | ||
481 | #define AR9170_USB_REG_CX_CONFIG_STATUS (AR9170_USB_REG_BASE + 0x00b) | ||
482 | #define AR9170_USB_REG_EP0_DATA (AR9170_USB_REG_BASE + 0x00c) | ||
483 | #define AR9170_USB_REG_EP0_DATA1 (AR9170_USB_REG_BASE + 0x00c) | ||
484 | #define AR9170_USB_REG_EP0_DATA2 (AR9170_USB_REG_BASE + 0x00d) | ||
485 | |||
486 | #define AR9170_USB_REG_INTR_MASK_BYTE_0 (AR9170_USB_REG_BASE + 0x011) | ||
487 | #define AR9170_USB_REG_INTR_MASK_BYTE_1 (AR9170_USB_REG_BASE + 0x012) | ||
488 | #define AR9170_USB_REG_INTR_MASK_BYTE_2 (AR9170_USB_REG_BASE + 0x013) | ||
489 | #define AR9170_USB_REG_INTR_MASK_BYTE_3 (AR9170_USB_REG_BASE + 0x014) | ||
490 | #define AR9170_USB_REG_INTR_MASK_BYTE_4 (AR9170_USB_REG_BASE + 0x015) | ||
491 | #define AR9170_USB_INTR_DISABLE_OUT_INT (BIT(7) | BIT(6)) | ||
492 | |||
493 | #define AR9170_USB_REG_INTR_MASK_BYTE_5 (AR9170_USB_REG_BASE + 0x016) | ||
494 | #define AR9170_USB_REG_INTR_MASK_BYTE_6 (AR9170_USB_REG_BASE + 0x017) | ||
495 | #define AR9170_USB_INTR_DISABLE_IN_INT BIT(6) | ||
496 | |||
497 | #define AR9170_USB_REG_INTR_MASK_BYTE_7 (AR9170_USB_REG_BASE + 0x018) | ||
498 | |||
499 | #define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020) | ||
500 | |||
501 | #define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021) | ||
502 | #define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022) | ||
503 | #define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023) | ||
504 | #define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024) | ||
505 | #define AR9170_USB_REG_INTR_SOURCE_4 (AR9170_USB_REG_BASE + 0x025) | ||
506 | #define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026) | ||
507 | #define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027) | ||
508 | #define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028) | ||
509 | |||
510 | #define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030) | ||
511 | #define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030) | ||
512 | #define AR9170_USB_REG_EP2_MAP (AR9170_USB_REG_BASE + 0x031) | ||
513 | #define AR9170_USB_REG_EP3_MAP (AR9170_USB_REG_BASE + 0x032) | ||
514 | #define AR9170_USB_REG_EP4_MAP (AR9170_USB_REG_BASE + 0x033) | ||
515 | #define AR9170_USB_REG_EP5_MAP (AR9170_USB_REG_BASE + 0x034) | ||
516 | #define AR9170_USB_REG_EP6_MAP (AR9170_USB_REG_BASE + 0x035) | ||
517 | #define AR9170_USB_REG_EP7_MAP (AR9170_USB_REG_BASE + 0x036) | ||
518 | #define AR9170_USB_REG_EP8_MAP (AR9170_USB_REG_BASE + 0x037) | ||
519 | #define AR9170_USB_REG_EP9_MAP (AR9170_USB_REG_BASE + 0x038) | ||
520 | #define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039) | ||
521 | |||
522 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f) | ||
523 | #define AR9170_USB_EP_IN_TOGGLE 0x10 | ||
524 | |||
525 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e) | ||
526 | |||
527 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f) | ||
528 | #define AR9170_USB_EP_OUT_TOGGLE 0x10 | ||
529 | |||
530 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e) | ||
531 | |||
532 | #define AR9170_USB_REG_EP3_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0ae) | ||
533 | #define AR9170_USB_REG_EP3_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0be) | ||
534 | #define AR9170_USB_REG_EP4_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0af) | ||
535 | #define AR9170_USB_REG_EP4_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0bf) | ||
536 | |||
537 | #define AR9170_USB_REG_FIFO_MAP (AR9170_USB_REG_BASE + 0x080) | ||
538 | #define AR9170_USB_REG_FIFO0_MAP (AR9170_USB_REG_BASE + 0x080) | ||
539 | #define AR9170_USB_REG_FIFO1_MAP (AR9170_USB_REG_BASE + 0x081) | ||
540 | #define AR9170_USB_REG_FIFO2_MAP (AR9170_USB_REG_BASE + 0x082) | ||
541 | #define AR9170_USB_REG_FIFO3_MAP (AR9170_USB_REG_BASE + 0x083) | ||
542 | #define AR9170_USB_REG_FIFO4_MAP (AR9170_USB_REG_BASE + 0x084) | ||
543 | #define AR9170_USB_REG_FIFO5_MAP (AR9170_USB_REG_BASE + 0x085) | ||
544 | #define AR9170_USB_REG_FIFO6_MAP (AR9170_USB_REG_BASE + 0x086) | ||
545 | #define AR9170_USB_REG_FIFO7_MAP (AR9170_USB_REG_BASE + 0x087) | ||
546 | #define AR9170_USB_REG_FIFO8_MAP (AR9170_USB_REG_BASE + 0x088) | ||
547 | #define AR9170_USB_REG_FIFO9_MAP (AR9170_USB_REG_BASE + 0x089) | ||
548 | |||
549 | #define AR9170_USB_REG_FIFO_CONFIG (AR9170_USB_REG_BASE + 0x090) | ||
550 | #define AR9170_USB_REG_FIFO0_CONFIG (AR9170_USB_REG_BASE + 0x090) | ||
551 | #define AR9170_USB_REG_FIFO1_CONFIG (AR9170_USB_REG_BASE + 0x091) | ||
552 | #define AR9170_USB_REG_FIFO2_CONFIG (AR9170_USB_REG_BASE + 0x092) | ||
553 | #define AR9170_USB_REG_FIFO3_CONFIG (AR9170_USB_REG_BASE + 0x093) | ||
554 | #define AR9170_USB_REG_FIFO4_CONFIG (AR9170_USB_REG_BASE + 0x094) | ||
555 | #define AR9170_USB_REG_FIFO5_CONFIG (AR9170_USB_REG_BASE + 0x095) | ||
556 | #define AR9170_USB_REG_FIFO6_CONFIG (AR9170_USB_REG_BASE + 0x096) | ||
557 | #define AR9170_USB_REG_FIFO7_CONFIG (AR9170_USB_REG_BASE + 0x097) | ||
558 | #define AR9170_USB_REG_FIFO8_CONFIG (AR9170_USB_REG_BASE + 0x098) | ||
559 | #define AR9170_USB_REG_FIFO9_CONFIG (AR9170_USB_REG_BASE + 0x099) | ||
560 | |||
561 | #define AR9170_USB_REG_EP3_DATA (AR9170_USB_REG_BASE + 0x0f8) | ||
562 | #define AR9170_USB_REG_EP4_DATA (AR9170_USB_REG_BASE + 0x0fc) | ||
563 | |||
564 | #define AR9170_USB_REG_FIFO_SIZE (AR9170_USB_REG_BASE + 0x100) | ||
565 | #define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) | ||
566 | #define AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE BIT(0) | ||
567 | #define AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE BIT(1) | ||
568 | #define AR9170_USB_DMA_CTL_HIGH_SPEED BIT(2) | ||
569 | #define AR9170_USB_DMA_CTL_UP_PACKET_MODE BIT(3) | ||
570 | #define AR9170_USB_DMA_CTL_UP_STREAM_S 4 | ||
571 | #define AR9170_USB_DMA_CTL_UP_STREAM (BIT(4) | BIT(5)) | ||
572 | #define AR9170_USB_DMA_CTL_UP_STREAM_4K (0) | ||
573 | #define AR9170_USB_DMA_CTL_UP_STREAM_8K BIT(4) | ||
574 | #define AR9170_USB_DMA_CTL_UP_STREAM_16K BIT(5) | ||
575 | #define AR9170_USB_DMA_CTL_UP_STREAM_32K (BIT(4) | BIT(5)) | ||
576 | #define AR9170_USB_DMA_CTL_DOWN_STREAM BIT(6) | ||
577 | |||
578 | #define AR9170_USB_REG_DMA_STATUS (AR9170_USB_REG_BASE + 0x10c) | ||
579 | #define AR9170_USB_DMA_STATUS_UP_IDLE BIT(8) | ||
580 | #define AR9170_USB_DMA_STATUS_DN_IDLE BIT(16) | ||
581 | |||
582 | #define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) | ||
583 | #define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) | ||
584 | #define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0) | ||
585 | #define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1)) | ||
586 | |||
587 | /* PCI/USB to AHB Bridge */ | ||
588 | #define AR9170_PTA_REG_BASE 0x1e2000 | ||
589 | |||
590 | #define AR9170_PTA_REG_CMD (AR9170_PTA_REG_BASE + 0x000) | ||
591 | #define AR9170_PTA_REG_PARAM1 (AR9170_PTA_REG_BASE + 0x004) | ||
592 | #define AR9170_PTA_REG_PARAM2 (AR9170_PTA_REG_BASE + 0x008) | ||
593 | #define AR9170_PTA_REG_PARAM3 (AR9170_PTA_REG_BASE + 0x00c) | ||
594 | #define AR9170_PTA_REG_RSP (AR9170_PTA_REG_BASE + 0x010) | ||
595 | #define AR9170_PTA_REG_STATUS1 (AR9170_PTA_REG_BASE + 0x014) | ||
596 | #define AR9170_PTA_REG_STATUS2 (AR9170_PTA_REG_BASE + 0x018) | ||
597 | #define AR9170_PTA_REG_STATUS3 (AR9170_PTA_REG_BASE + 0x01c) | ||
598 | #define AR9170_PTA_REG_AHB_INT_FLAG (AR9170_PTA_REG_BASE + 0x020) | ||
599 | #define AR9170_PTA_REG_AHB_INT_MASK (AR9170_PTA_REG_BASE + 0x024) | ||
600 | #define AR9170_PTA_REG_AHB_INT_ACK (AR9170_PTA_REG_BASE + 0x028) | ||
601 | #define AR9170_PTA_REG_AHB_SCRATCH1 (AR9170_PTA_REG_BASE + 0x030) | ||
602 | #define AR9170_PTA_REG_AHB_SCRATCH2 (AR9170_PTA_REG_BASE + 0x034) | ||
603 | #define AR9170_PTA_REG_AHB_SCRATCH3 (AR9170_PTA_REG_BASE + 0x038) | ||
604 | #define AR9170_PTA_REG_AHB_SCRATCH4 (AR9170_PTA_REG_BASE + 0x03c) | ||
605 | |||
606 | #define AR9170_PTA_REG_SHARE_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124) | ||
607 | |||
608 | /* | ||
609 | * PCI to AHB Bridge | ||
610 | */ | ||
611 | |||
612 | #define AR9170_PTA_REG_INT_FLAG (AR9170_PTA_REG_BASE + 0x100) | ||
613 | #define AR9170_PTA_INT_FLAG_DN 0x01 | ||
614 | #define AR9170_PTA_INT_FLAG_UP 0x02 | ||
615 | #define AR9170_PTA_INT_FLAG_CMD 0x04 | ||
616 | |||
617 | #define AR9170_PTA_REG_INT_MASK (AR9170_PTA_REG_BASE + 0x104) | ||
618 | #define AR9170_PTA_REG_DN_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x108) | ||
619 | #define AR9170_PTA_REG_DN_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x10c) | ||
620 | #define AR9170_PTA_REG_UP_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x110) | ||
621 | #define AR9170_PTA_REG_UP_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x114) | ||
622 | #define AR9170_PTA_REG_DN_PEND_TIME (AR9170_PTA_REG_BASE + 0x118) | ||
623 | #define AR9170_PTA_REG_UP_PEND_TIME (AR9170_PTA_REG_BASE + 0x11c) | ||
624 | #define AR9170_PTA_REG_CONTROL (AR9170_PTA_REG_BASE + 0x120) | ||
625 | #define AR9170_PTA_CTRL_4_BEAT_BURST 0x00 | ||
626 | #define AR9170_PTA_CTRL_8_BEAT_BURST 0x01 | ||
627 | #define AR9170_PTA_CTRL_16_BEAT_BURST 0x02 | ||
628 | #define AR9170_PTA_CTRL_LOOPBACK_MODE 0x10 | ||
629 | |||
630 | #define AR9170_PTA_REG_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124) | ||
631 | #define AR9170_PTA_REG_MEM_ADDR (AR9170_PTA_REG_BASE + 0x128) | ||
632 | #define AR9170_PTA_REG_DN_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x12c) | ||
633 | #define AR9170_PTA_REG_UP_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x130) | ||
634 | #define AR9170_PTA_REG_DMA_STATUS (AR9170_PTA_REG_BASE + 0x134) | ||
635 | #define AR9170_PTA_REG_DN_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x138) | ||
636 | #define AR9170_PTA_REG_DN_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x13c) | ||
637 | #define AR9170_PTA_REG_UP_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x140) | ||
638 | #define AR9170_PTA_REG_UP_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x144) | ||
639 | #define AR9170_PTA_REG_DMA_MODE_CTRL (AR9170_PTA_REG_BASE + 0x148) | ||
640 | #define AR9170_PTA_DMA_MODE_CTRL_RESET BIT(0) | ||
641 | #define AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB BIT(1) | ||
642 | |||
643 | /* Protocol Controller Module */ | ||
644 | #define AR9170_MAC_REG_PC_REG_BASE (AR9170_MAC_REG_BASE + 0xe00) | ||
645 | |||
646 | |||
647 | #define AR9170_NUM_LEDS 2 | ||
648 | |||
649 | /* CAM */ | ||
650 | #define AR9170_CAM_MAX_USER 64 | ||
651 | #define AR9170_CAM_MAX_KEY_LENGTH 16 | ||
652 | |||
653 | #define AR9170_SRAM_OFFSET 0x100000 | ||
654 | #define AR9170_SRAM_SIZE 0x18000 | ||
655 | |||
656 | #define AR9170_PRAM_OFFSET 0x200000 | ||
657 | #define AR9170_PRAM_SIZE 0x8000 | ||
658 | |||
659 | enum cpu_clock { | ||
660 | AHB_STATIC_40MHZ = 0, | ||
661 | AHB_GMODE_22MHZ = 1, | ||
662 | AHB_AMODE_20MHZ = 1, | ||
663 | AHB_GMODE_44MHZ = 2, | ||
664 | AHB_AMODE_40MHZ = 2, | ||
665 | AHB_GMODE_88MHZ = 3, | ||
666 | AHB_AMODE_80MHZ = 3 | ||
667 | }; | ||
668 | |||
669 | /* USB endpoints */ | ||
670 | enum ar9170_usb_ep { | ||
671 | /* | ||
672 | * Control EP is always EP 0 (USB SPEC) | ||
673 | * | ||
674 | * The weird thing is: the original firmware has a few | ||
675 | * comments that suggest that the actual EP numbers | ||
676 | * are in the 1 to 10 range?! | ||
677 | */ | ||
678 | AR9170_USB_EP_CTRL = 0, | ||
679 | |||
680 | AR9170_USB_EP_TX, | ||
681 | AR9170_USB_EP_RX, | ||
682 | AR9170_USB_EP_IRQ, | ||
683 | AR9170_USB_EP_CMD, | ||
684 | AR9170_USB_NUM_EXTRA_EP = 4, | ||
685 | |||
686 | __AR9170_USB_NUM_EP, | ||
687 | |||
688 | __AR9170_USB_NUM_MAX_EP = 10 | ||
689 | }; | ||
690 | |||
691 | enum ar9170_usb_fifo { | ||
692 | __AR9170_USB_NUM_MAX_FIFO = 10 | ||
693 | }; | ||
694 | |||
695 | enum ar9170_tx_queues { | ||
696 | AR9170_TXQ0 = 0, | ||
697 | AR9170_TXQ1, | ||
698 | AR9170_TXQ2, | ||
699 | AR9170_TXQ3, | ||
700 | AR9170_TXQ_SPECIAL, | ||
701 | |||
702 | /* keep last */ | ||
703 | __AR9170_NUM_TX_QUEUES = 5 | ||
704 | }; | ||
705 | |||
706 | #define AR9170_TX_STREAM_TAG 0x697e | ||
707 | #define AR9170_RX_STREAM_TAG 0x4e00 | ||
708 | #define AR9170_RX_STREAM_MAX_SIZE 0xffff | ||
709 | |||
710 | struct ar9170_stream { | ||
711 | __le16 length; | ||
712 | __le16 tag; | ||
713 | |||
714 | u8 payload[0]; | ||
715 | }; | ||
716 | |||
717 | #define AR9170_MAX_ACKTABLE_ENTRIES 8 | ||
718 | #define AR9170_MAX_VIRTUAL_MAC 7 | ||
719 | |||
720 | #define AR9170_USB_EP_CTRL_MAX 64 | ||
721 | #define AR9170_USB_EP_TX_MAX 512 | ||
722 | #define AR9170_USB_EP_RX_MAX 512 | ||
723 | #define AR9170_USB_EP_IRQ_MAX 64 | ||
724 | #define AR9170_USB_EP_CMD_MAX 64 | ||
725 | |||
726 | /* Trigger PRETBTT interrupt 6 Kus earlier */ | ||
727 | #define CARL9170_PRETBTT_KUS 6 | ||
728 | |||
729 | #define AR5416_MAX_RATE_POWER 63 | ||
730 | |||
731 | #define SET_VAL(reg, value, newvalue) \ | ||
732 | (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | ||
733 | |||
734 | #define MOD_VAL(reg, value, newvalue) \ | ||
735 | (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | ||
736 | #endif /* __CARL9170_SHARED_HW_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c new file mode 100644 index 000000000000..4bb2cbd8bd9b --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/led.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * LED handling | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include "carl9170.h" | ||
41 | #include "cmd.h" | ||
42 | |||
43 | int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state) | ||
44 | { | ||
45 | return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state); | ||
46 | } | ||
47 | |||
48 | int carl9170_led_init(struct ar9170 *ar) | ||
49 | { | ||
50 | int err; | ||
51 | |||
52 | /* disable LEDs */ | ||
53 | /* GPIO [0/1 mode: output, 2/3: input] */ | ||
54 | err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); | ||
55 | if (err) | ||
56 | goto out; | ||
57 | |||
58 | /* GPIO 0/1 value: off */ | ||
59 | err = carl9170_led_set_state(ar, 0); | ||
60 | |||
61 | out: | ||
62 | return err; | ||
63 | } | ||
64 | |||
65 | #ifdef CONFIG_CARL9170_LEDS | ||
66 | static void carl9170_led_update(struct work_struct *work) | ||
67 | { | ||
68 | struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); | ||
69 | int i, tmp = 300, blink_delay = 1000; | ||
70 | u32 led_val = 0; | ||
71 | bool rerun = false; | ||
72 | |||
73 | if (!IS_ACCEPTING_CMD(ar)) | ||
74 | return; | ||
75 | |||
76 | mutex_lock(&ar->mutex); | ||
77 | for (i = 0; i < AR9170_NUM_LEDS; i++) { | ||
78 | if (ar->leds[i].registered) { | ||
79 | if (ar->leds[i].last_state || | ||
80 | ar->leds[i].toggled) { | ||
81 | |||
82 | if (ar->leds[i].toggled) | ||
83 | tmp = 70 + 200 / (ar->leds[i].toggled); | ||
84 | |||
85 | if (tmp < blink_delay) | ||
86 | blink_delay = tmp; | ||
87 | |||
88 | led_val |= 1 << i; | ||
89 | ar->leds[i].toggled = 0; | ||
90 | rerun = true; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | carl9170_led_set_state(ar, led_val); | ||
96 | mutex_unlock(&ar->mutex); | ||
97 | |||
98 | if (!rerun) | ||
99 | return; | ||
100 | |||
101 | ieee80211_queue_delayed_work(ar->hw, | ||
102 | &ar->led_work, | ||
103 | msecs_to_jiffies(blink_delay)); | ||
104 | } | ||
105 | |||
106 | static void carl9170_led_set_brightness(struct led_classdev *led, | ||
107 | enum led_brightness brightness) | ||
108 | { | ||
109 | struct carl9170_led *arl = container_of(led, struct carl9170_led, l); | ||
110 | struct ar9170 *ar = arl->ar; | ||
111 | |||
112 | if (!arl->registered) | ||
113 | return; | ||
114 | |||
115 | if (arl->last_state != !!brightness) { | ||
116 | arl->toggled++; | ||
117 | arl->last_state = !!brightness; | ||
118 | } | ||
119 | |||
120 | if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) | ||
121 | ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); | ||
122 | } | ||
123 | |||
124 | static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name, | ||
125 | char *trigger) | ||
126 | { | ||
127 | int err; | ||
128 | |||
129 | snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), | ||
130 | "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name); | ||
131 | |||
132 | ar->leds[i].ar = ar; | ||
133 | ar->leds[i].l.name = ar->leds[i].name; | ||
134 | ar->leds[i].l.brightness_set = carl9170_led_set_brightness; | ||
135 | ar->leds[i].l.brightness = 0; | ||
136 | ar->leds[i].l.default_trigger = trigger; | ||
137 | |||
138 | err = led_classdev_register(wiphy_dev(ar->hw->wiphy), | ||
139 | &ar->leds[i].l); | ||
140 | if (err) { | ||
141 | wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", | ||
142 | ar->leds[i].name, err); | ||
143 | } else { | ||
144 | ar->leds[i].registered = true; | ||
145 | } | ||
146 | |||
147 | return err; | ||
148 | } | ||
149 | |||
150 | void carl9170_led_unregister(struct ar9170 *ar) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | for (i = 0; i < AR9170_NUM_LEDS; i++) | ||
155 | if (ar->leds[i].registered) { | ||
156 | led_classdev_unregister(&ar->leds[i].l); | ||
157 | ar->leds[i].registered = false; | ||
158 | ar->leds[i].toggled = 0; | ||
159 | } | ||
160 | |||
161 | cancel_delayed_work_sync(&ar->led_work); | ||
162 | } | ||
163 | |||
164 | int carl9170_led_register(struct ar9170 *ar) | ||
165 | { | ||
166 | int err; | ||
167 | |||
168 | INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update); | ||
169 | |||
170 | err = carl9170_led_register_led(ar, 0, "tx", | ||
171 | ieee80211_get_tx_led_name(ar->hw)); | ||
172 | if (err) | ||
173 | goto fail; | ||
174 | |||
175 | if (ar->features & CARL9170_ONE_LED) | ||
176 | return 0; | ||
177 | |||
178 | err = carl9170_led_register_led(ar, 1, "assoc", | ||
179 | ieee80211_get_assoc_led_name(ar->hw)); | ||
180 | if (err) | ||
181 | goto fail; | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | fail: | ||
186 | carl9170_led_unregister(ar); | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | #endif /* CONFIG_CARL9170_LEDS */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c new file mode 100644 index 000000000000..2305bc27151c --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/mac.c | |||
@@ -0,0 +1,604 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * MAC programming | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
41 | #include "carl9170.h" | ||
42 | #include "cmd.h" | ||
43 | |||
44 | int carl9170_set_dyn_sifs_ack(struct ar9170 *ar) | ||
45 | { | ||
46 | u32 val; | ||
47 | |||
48 | if (conf_is_ht40(&ar->hw->conf)) | ||
49 | val = 0x010a; | ||
50 | else { | ||
51 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
52 | val = 0x105; | ||
53 | else | ||
54 | val = 0x104; | ||
55 | } | ||
56 | |||
57 | return carl9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); | ||
58 | } | ||
59 | |||
60 | int carl9170_set_rts_cts_rate(struct ar9170 *ar) | ||
61 | { | ||
62 | u32 rts_rate, cts_rate; | ||
63 | |||
64 | if (conf_is_ht(&ar->hw->conf)) { | ||
65 | /* 12 mbit OFDM */ | ||
66 | rts_rate = 0x1da; | ||
67 | cts_rate = 0x10a; | ||
68 | } else { | ||
69 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
70 | /* 11 mbit CCK */ | ||
71 | rts_rate = 033; | ||
72 | cts_rate = 003; | ||
73 | } else { | ||
74 | /* 6 mbit OFDM */ | ||
75 | rts_rate = 0x1bb; | ||
76 | cts_rate = 0x10b; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return carl9170_write_reg(ar, AR9170_MAC_REG_RTS_CTS_RATE, | ||
81 | rts_rate | (cts_rate) << 16); | ||
82 | } | ||
83 | |||
84 | int carl9170_set_slot_time(struct ar9170 *ar) | ||
85 | { | ||
86 | struct ieee80211_vif *vif; | ||
87 | u32 slottime = 20; | ||
88 | |||
89 | rcu_read_lock(); | ||
90 | vif = carl9170_get_main_vif(ar); | ||
91 | if (!vif) { | ||
92 | rcu_read_unlock(); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || | ||
97 | vif->bss_conf.use_short_slot) | ||
98 | slottime = 9; | ||
99 | |||
100 | rcu_read_unlock(); | ||
101 | |||
102 | return carl9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, | ||
103 | slottime << 10); | ||
104 | } | ||
105 | |||
106 | int carl9170_set_mac_rates(struct ar9170 *ar) | ||
107 | { | ||
108 | struct ieee80211_vif *vif; | ||
109 | u32 basic, mandatory; | ||
110 | |||
111 | rcu_read_lock(); | ||
112 | vif = carl9170_get_main_vif(ar); | ||
113 | |||
114 | if (!vif) { | ||
115 | rcu_read_unlock(); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | basic = (vif->bss_conf.basic_rates & 0xf); | ||
120 | basic |= (vif->bss_conf.basic_rates & 0xff0) << 4; | ||
121 | rcu_read_unlock(); | ||
122 | |||
123 | if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) | ||
124 | mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */ | ||
125 | else | ||
126 | mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */ | ||
127 | |||
128 | carl9170_regwrite_begin(ar); | ||
129 | carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, basic); | ||
130 | carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, mandatory); | ||
131 | carl9170_regwrite_finish(); | ||
132 | |||
133 | return carl9170_regwrite_result(); | ||
134 | } | ||
135 | |||
136 | int carl9170_set_qos(struct ar9170 *ar) | ||
137 | { | ||
138 | carl9170_regwrite_begin(ar); | ||
139 | |||
140 | carl9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | | ||
141 | (ar->edcf[0].cw_max << 16)); | ||
142 | carl9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | | ||
143 | (ar->edcf[1].cw_max << 16)); | ||
144 | carl9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | | ||
145 | (ar->edcf[2].cw_max << 16)); | ||
146 | carl9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | | ||
147 | (ar->edcf[3].cw_max << 16)); | ||
148 | carl9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | | ||
149 | (ar->edcf[4].cw_max << 16)); | ||
150 | |||
151 | carl9170_regwrite(AR9170_MAC_REG_AC2_AC1_AC0_AIFS, | ||
152 | ((ar->edcf[0].aifs * 9 + 10)) | | ||
153 | ((ar->edcf[1].aifs * 9 + 10) << 12) | | ||
154 | ((ar->edcf[2].aifs * 9 + 10) << 24)); | ||
155 | carl9170_regwrite(AR9170_MAC_REG_AC4_AC3_AC2_AIFS, | ||
156 | ((ar->edcf[2].aifs * 9 + 10) >> 8) | | ||
157 | ((ar->edcf[3].aifs * 9 + 10) << 4) | | ||
158 | ((ar->edcf[4].aifs * 9 + 10) << 16)); | ||
159 | |||
160 | carl9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, | ||
161 | ar->edcf[0].txop | ar->edcf[1].txop << 16); | ||
162 | carl9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, | ||
163 | ar->edcf[2].txop | ar->edcf[3].txop << 16 | | ||
164 | ar->edcf[4].txop << 24); | ||
165 | |||
166 | carl9170_regwrite_finish(); | ||
167 | |||
168 | return carl9170_regwrite_result(); | ||
169 | } | ||
170 | |||
171 | int carl9170_init_mac(struct ar9170 *ar) | ||
172 | { | ||
173 | carl9170_regwrite_begin(ar); | ||
174 | |||
175 | /* switch MAC to OTUS interface */ | ||
176 | carl9170_regwrite(0x1c3600, 0x3); | ||
177 | |||
178 | carl9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); | ||
179 | |||
180 | carl9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0x0); | ||
181 | |||
182 | carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, | ||
183 | AR9170_MAC_FTF_MONITOR); | ||
184 | |||
185 | /* enable MMIC */ | ||
186 | carl9170_regwrite(AR9170_MAC_REG_SNIFFER, | ||
187 | AR9170_MAC_SNIFFER_DEFAULTS); | ||
188 | |||
189 | carl9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); | ||
190 | |||
191 | carl9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); | ||
192 | carl9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); | ||
193 | carl9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); | ||
194 | |||
195 | /* CF-END & CF-ACK rate => 24M OFDM */ | ||
196 | carl9170_regwrite(AR9170_MAC_REG_TID_CFACK_CFEND_RATE, 0x59900000); | ||
197 | |||
198 | /* NAV protects ACK only (in TXOP) */ | ||
199 | carl9170_regwrite(AR9170_MAC_REG_TXOP_DURATION, 0x201); | ||
200 | |||
201 | /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ | ||
202 | /* OTUS set AM to 0x1 */ | ||
203 | carl9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); | ||
204 | |||
205 | carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); | ||
206 | |||
207 | /* Aggregation MAX number and timeout */ | ||
208 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa); | ||
209 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00); | ||
210 | |||
211 | carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, | ||
212 | AR9170_MAC_FTF_DEFAULTS); | ||
213 | |||
214 | carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, | ||
215 | AR9170_MAC_RX_CTRL_DEAGG | | ||
216 | AR9170_MAC_RX_CTRL_SHORT_FILTER); | ||
217 | |||
218 | /* rate sets */ | ||
219 | carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); | ||
220 | carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); | ||
221 | carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x0030033); | ||
222 | |||
223 | /* MIMO response control */ | ||
224 | carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, 0x4003c1e); | ||
225 | |||
226 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); | ||
227 | |||
228 | /* set PHY register read timeout (??) */ | ||
229 | carl9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); | ||
230 | |||
231 | /* Disable Rx TimeOut, workaround for BB. */ | ||
232 | carl9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); | ||
233 | |||
234 | /* Set WLAN DMA interrupt mode: generate int per packet */ | ||
235 | carl9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); | ||
236 | |||
237 | carl9170_regwrite(AR9170_MAC_REG_FCS_SELECT, | ||
238 | AR9170_MAC_FCS_FIFO_PROT); | ||
239 | |||
240 | /* Disables the CF_END frame, undocumented register */ | ||
241 | carl9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, | ||
242 | 0x141e0f48); | ||
243 | |||
244 | /* reset group hash table */ | ||
245 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, 0xffffffff); | ||
246 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, 0xffffffff); | ||
247 | |||
248 | /* disable PRETBTT interrupt */ | ||
249 | carl9170_regwrite(AR9170_MAC_REG_PRETBTT, 0x0); | ||
250 | carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, 0x0); | ||
251 | |||
252 | carl9170_regwrite_finish(); | ||
253 | |||
254 | return carl9170_regwrite_result(); | ||
255 | } | ||
256 | |||
257 | static int carl9170_set_mac_reg(struct ar9170 *ar, | ||
258 | const u32 reg, const u8 *mac) | ||
259 | { | ||
260 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
261 | |||
262 | if (!mac) | ||
263 | mac = zero; | ||
264 | |||
265 | carl9170_regwrite_begin(ar); | ||
266 | |||
267 | carl9170_regwrite(reg, get_unaligned_le32(mac)); | ||
268 | carl9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); | ||
269 | |||
270 | carl9170_regwrite_finish(); | ||
271 | |||
272 | return carl9170_regwrite_result(); | ||
273 | } | ||
274 | |||
275 | int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id, | ||
276 | const u8 *mac) | ||
277 | { | ||
278 | if (WARN_ON(id >= ar->fw.vif_num)) | ||
279 | return -EINVAL; | ||
280 | |||
281 | return carl9170_set_mac_reg(ar, | ||
282 | AR9170_MAC_REG_ACK_TABLE + (id - 1) * 8, mac); | ||
283 | } | ||
284 | |||
285 | int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) | ||
286 | { | ||
287 | int err; | ||
288 | |||
289 | carl9170_regwrite_begin(ar); | ||
290 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); | ||
291 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); | ||
292 | carl9170_regwrite_finish(); | ||
293 | err = carl9170_regwrite_result(); | ||
294 | if (err) | ||
295 | return err; | ||
296 | |||
297 | ar->cur_mc_hash = mc_hash; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | int carl9170_set_operating_mode(struct ar9170 *ar) | ||
302 | { | ||
303 | struct ieee80211_vif *vif; | ||
304 | struct ath_common *common = &ar->common; | ||
305 | u8 *mac_addr, *bssid; | ||
306 | u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; | ||
307 | u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS; | ||
308 | u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | | ||
309 | AR9170_MAC_RX_CTRL_SHORT_FILTER; | ||
310 | u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; | ||
311 | int err = 0; | ||
312 | |||
313 | rcu_read_lock(); | ||
314 | vif = carl9170_get_main_vif(ar); | ||
315 | |||
316 | if (vif) { | ||
317 | mac_addr = common->macaddr; | ||
318 | bssid = common->curbssid; | ||
319 | |||
320 | switch (vif->type) { | ||
321 | case NL80211_IFTYPE_MESH_POINT: | ||
322 | case NL80211_IFTYPE_ADHOC: | ||
323 | cam_mode |= AR9170_MAC_CAM_IBSS; | ||
324 | break; | ||
325 | case NL80211_IFTYPE_AP: | ||
326 | cam_mode |= AR9170_MAC_CAM_AP; | ||
327 | |||
328 | /* iwlagn 802.11n STA Workaround */ | ||
329 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
330 | break; | ||
331 | case NL80211_IFTYPE_WDS: | ||
332 | cam_mode |= AR9170_MAC_CAM_AP_WDS; | ||
333 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
334 | break; | ||
335 | case NL80211_IFTYPE_STATION: | ||
336 | cam_mode |= AR9170_MAC_CAM_STA; | ||
337 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
338 | break; | ||
339 | default: | ||
340 | WARN(1, "Unsupported operation mode %x\n", vif->type); | ||
341 | err = -EOPNOTSUPP; | ||
342 | break; | ||
343 | } | ||
344 | } else { | ||
345 | mac_addr = NULL; | ||
346 | bssid = NULL; | ||
347 | } | ||
348 | rcu_read_unlock(); | ||
349 | |||
350 | if (err) | ||
351 | return err; | ||
352 | |||
353 | if (ar->rx_software_decryption) | ||
354 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | ||
355 | |||
356 | if (ar->sniffer_enabled) { | ||
357 | rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | ||
358 | sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | ||
359 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | ||
360 | } | ||
361 | |||
362 | err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); | ||
363 | if (err) | ||
364 | return err; | ||
365 | |||
366 | err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); | ||
367 | if (err) | ||
368 | return err; | ||
369 | |||
370 | carl9170_regwrite_begin(ar); | ||
371 | carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); | ||
372 | carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode); | ||
373 | carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode); | ||
374 | carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, rx_ctrl); | ||
375 | carl9170_regwrite_finish(); | ||
376 | |||
377 | return carl9170_regwrite_result(); | ||
378 | } | ||
379 | |||
380 | int carl9170_set_hwretry_limit(struct ar9170 *ar, const unsigned int max_retry) | ||
381 | { | ||
382 | u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); | ||
383 | |||
384 | return carl9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); | ||
385 | } | ||
386 | |||
387 | int carl9170_set_beacon_timers(struct ar9170 *ar) | ||
388 | { | ||
389 | struct ieee80211_vif *vif; | ||
390 | u32 v = 0; | ||
391 | u32 pretbtt = 0; | ||
392 | |||
393 | rcu_read_lock(); | ||
394 | vif = carl9170_get_main_vif(ar); | ||
395 | |||
396 | if (vif) { | ||
397 | struct carl9170_vif_info *mvif; | ||
398 | mvif = (void *) vif->drv_priv; | ||
399 | |||
400 | if (mvif->enable_beacon && !WARN_ON(!ar->beacon_enabled)) { | ||
401 | ar->global_beacon_int = vif->bss_conf.beacon_int / | ||
402 | ar->beacon_enabled; | ||
403 | |||
404 | SET_VAL(AR9170_MAC_BCN_DTIM, v, | ||
405 | vif->bss_conf.dtim_period); | ||
406 | |||
407 | switch (vif->type) { | ||
408 | case NL80211_IFTYPE_MESH_POINT: | ||
409 | case NL80211_IFTYPE_ADHOC: | ||
410 | v |= AR9170_MAC_BCN_IBSS_MODE; | ||
411 | break; | ||
412 | case NL80211_IFTYPE_AP: | ||
413 | v |= AR9170_MAC_BCN_AP_MODE; | ||
414 | break; | ||
415 | default: | ||
416 | WARN_ON_ONCE(1); | ||
417 | break; | ||
418 | } | ||
419 | } else if (vif->type == NL80211_IFTYPE_STATION) { | ||
420 | ar->global_beacon_int = vif->bss_conf.beacon_int; | ||
421 | |||
422 | SET_VAL(AR9170_MAC_BCN_DTIM, v, | ||
423 | ar->hw->conf.ps_dtim_period); | ||
424 | |||
425 | v |= AR9170_MAC_BCN_STA_PS | | ||
426 | AR9170_MAC_BCN_PWR_MGT; | ||
427 | } | ||
428 | |||
429 | if (ar->global_beacon_int) { | ||
430 | if (ar->global_beacon_int < 15) { | ||
431 | rcu_read_unlock(); | ||
432 | return -ERANGE; | ||
433 | } | ||
434 | |||
435 | ar->global_pretbtt = ar->global_beacon_int - | ||
436 | CARL9170_PRETBTT_KUS; | ||
437 | } else { | ||
438 | ar->global_pretbtt = 0; | ||
439 | } | ||
440 | } else { | ||
441 | ar->global_beacon_int = 0; | ||
442 | ar->global_pretbtt = 0; | ||
443 | } | ||
444 | |||
445 | rcu_read_unlock(); | ||
446 | |||
447 | SET_VAL(AR9170_MAC_BCN_PERIOD, v, ar->global_beacon_int); | ||
448 | SET_VAL(AR9170_MAC_PRETBTT, pretbtt, ar->global_pretbtt); | ||
449 | SET_VAL(AR9170_MAC_PRETBTT2, pretbtt, ar->global_pretbtt); | ||
450 | |||
451 | carl9170_regwrite_begin(ar); | ||
452 | carl9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); | ||
453 | carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); | ||
454 | carl9170_regwrite_finish(); | ||
455 | return carl9170_regwrite_result(); | ||
456 | } | ||
457 | |||
458 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) | ||
459 | { | ||
460 | struct sk_buff *skb; | ||
461 | struct carl9170_vif_info *cvif; | ||
462 | __le32 *data, *old = NULL; | ||
463 | u32 word, off, addr, len; | ||
464 | int i = 0, err = 0; | ||
465 | |||
466 | rcu_read_lock(); | ||
467 | cvif = rcu_dereference(ar->beacon_iter); | ||
468 | retry: | ||
469 | if (ar->vifs == 0 || !cvif) | ||
470 | goto out_unlock; | ||
471 | |||
472 | list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { | ||
473 | if (cvif->active && cvif->enable_beacon) | ||
474 | goto found; | ||
475 | } | ||
476 | |||
477 | if (!ar->beacon_enabled || i++) | ||
478 | goto out_unlock; | ||
479 | |||
480 | goto retry; | ||
481 | |||
482 | found: | ||
483 | rcu_assign_pointer(ar->beacon_iter, cvif); | ||
484 | |||
485 | skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), | ||
486 | NULL, NULL); | ||
487 | |||
488 | if (!skb) { | ||
489 | err = -ENOMEM; | ||
490 | goto out_unlock; | ||
491 | } | ||
492 | |||
493 | spin_lock_bh(&ar->beacon_lock); | ||
494 | data = (__le32 *)skb->data; | ||
495 | if (cvif->beacon) | ||
496 | old = (__le32 *)cvif->beacon->data; | ||
497 | |||
498 | off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX; | ||
499 | addr = ar->fw.beacon_addr + off; | ||
500 | len = roundup(skb->len + FCS_LEN, 4); | ||
501 | |||
502 | if ((off + len) > ar->fw.beacon_max_len) { | ||
503 | if (net_ratelimit()) { | ||
504 | wiphy_err(ar->hw->wiphy, "beacon does not " | ||
505 | "fit into device memory!\n"); | ||
506 | } | ||
507 | |||
508 | spin_unlock_bh(&ar->beacon_lock); | ||
509 | dev_kfree_skb_any(skb); | ||
510 | err = -EINVAL; | ||
511 | goto out_unlock; | ||
512 | } | ||
513 | |||
514 | if (len > AR9170_MAC_BCN_LENGTH_MAX) { | ||
515 | if (net_ratelimit()) { | ||
516 | wiphy_err(ar->hw->wiphy, "no support for beacons " | ||
517 | "bigger than %d (yours:%d).\n", | ||
518 | AR9170_MAC_BCN_LENGTH_MAX, len); | ||
519 | } | ||
520 | |||
521 | spin_unlock_bh(&ar->beacon_lock); | ||
522 | dev_kfree_skb_any(skb); | ||
523 | err = -EMSGSIZE; | ||
524 | goto out_unlock; | ||
525 | } | ||
526 | |||
527 | carl9170_async_regwrite_begin(ar); | ||
528 | |||
529 | /* XXX: use skb->cb info */ | ||
530 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
531 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, | ||
532 | ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400); | ||
533 | } else { | ||
534 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, | ||
535 | ((skb->len + FCS_LEN) << 16) + 0x001b); | ||
536 | } | ||
537 | |||
538 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { | ||
539 | /* | ||
540 | * XXX: This accesses beyond skb data for up | ||
541 | * to the last 3 bytes!! | ||
542 | */ | ||
543 | |||
544 | if (old && (data[i] == old[i])) | ||
545 | continue; | ||
546 | |||
547 | word = le32_to_cpu(data[i]); | ||
548 | carl9170_async_regwrite(addr + 4 * i, word); | ||
549 | } | ||
550 | carl9170_async_regwrite_finish(); | ||
551 | |||
552 | dev_kfree_skb_any(cvif->beacon); | ||
553 | cvif->beacon = NULL; | ||
554 | |||
555 | err = carl9170_async_regwrite_result(); | ||
556 | if (!err) | ||
557 | cvif->beacon = skb; | ||
558 | spin_unlock_bh(&ar->beacon_lock); | ||
559 | if (err) | ||
560 | goto out_unlock; | ||
561 | |||
562 | if (submit) { | ||
563 | err = carl9170_bcn_ctrl(ar, cvif->id, | ||
564 | CARL9170_BCN_CTRL_CAB_TRIGGER, | ||
565 | addr, skb->len + FCS_LEN); | ||
566 | |||
567 | if (err) | ||
568 | goto out_unlock; | ||
569 | } | ||
570 | out_unlock: | ||
571 | rcu_read_unlock(); | ||
572 | return err; | ||
573 | } | ||
574 | |||
575 | int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, | ||
576 | const u8 ktype, const u8 keyidx, const u8 *keydata, | ||
577 | const int keylen) | ||
578 | { | ||
579 | struct carl9170_set_key_cmd key = { }; | ||
580 | static const u8 bcast[ETH_ALEN] = { | ||
581 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
582 | |||
583 | mac = mac ? : bcast; | ||
584 | |||
585 | key.user = cpu_to_le16(id); | ||
586 | key.keyId = cpu_to_le16(keyidx); | ||
587 | key.type = cpu_to_le16(ktype); | ||
588 | memcpy(&key.macAddr, mac, ETH_ALEN); | ||
589 | if (keydata) | ||
590 | memcpy(&key.key, keydata, keylen); | ||
591 | |||
592 | return carl9170_exec_cmd(ar, CARL9170_CMD_EKEY, | ||
593 | sizeof(key), (u8 *)&key, 0, NULL); | ||
594 | } | ||
595 | |||
596 | int carl9170_disable_key(struct ar9170 *ar, const u8 id) | ||
597 | { | ||
598 | struct carl9170_disable_key_cmd key = { }; | ||
599 | |||
600 | key.user = cpu_to_le16(id); | ||
601 | |||
602 | return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY, | ||
603 | sizeof(key), (u8 *)&key, 0, NULL); | ||
604 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c new file mode 100644 index 000000000000..43de9dfa5820 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -0,0 +1,1855 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * mac80211 interaction code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <linux/random.h> | ||
45 | #include <net/mac80211.h> | ||
46 | #include <net/cfg80211.h> | ||
47 | #include "hw.h" | ||
48 | #include "carl9170.h" | ||
49 | #include "cmd.h" | ||
50 | |||
51 | static int modparam_nohwcrypt; | ||
52 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
53 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware crypto offload."); | ||
54 | |||
55 | int modparam_noht; | ||
56 | module_param_named(noht, modparam_noht, int, S_IRUGO); | ||
57 | MODULE_PARM_DESC(noht, "Disable MPDU aggregation."); | ||
58 | |||
59 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | ||
60 | .bitrate = (_bitrate), \ | ||
61 | .flags = (_flags), \ | ||
62 | .hw_value = (_hw_rate) | (_txpidx) << 4, \ | ||
63 | } | ||
64 | |||
65 | struct ieee80211_rate __carl9170_ratetable[] = { | ||
66 | RATE(10, 0, 0, 0), | ||
67 | RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), | ||
68 | RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), | ||
69 | RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), | ||
70 | RATE(60, 0xb, 0, 0), | ||
71 | RATE(90, 0xf, 0, 0), | ||
72 | RATE(120, 0xa, 0, 0), | ||
73 | RATE(180, 0xe, 0, 0), | ||
74 | RATE(240, 0x9, 0, 0), | ||
75 | RATE(360, 0xd, 1, 0), | ||
76 | RATE(480, 0x8, 2, 0), | ||
77 | RATE(540, 0xc, 3, 0), | ||
78 | }; | ||
79 | #undef RATE | ||
80 | |||
81 | #define carl9170_g_ratetable (__carl9170_ratetable + 0) | ||
82 | #define carl9170_g_ratetable_size 12 | ||
83 | #define carl9170_a_ratetable (__carl9170_ratetable + 4) | ||
84 | #define carl9170_a_ratetable_size 8 | ||
85 | |||
86 | /* | ||
87 | * NB: The hw_value is used as an index into the carl9170_phy_freq_params | ||
88 | * array in phy.c so that we don't have to do frequency lookups! | ||
89 | */ | ||
90 | #define CHAN(_freq, _idx) { \ | ||
91 | .center_freq = (_freq), \ | ||
92 | .hw_value = (_idx), \ | ||
93 | .max_power = 18, /* XXX */ \ | ||
94 | } | ||
95 | |||
96 | static struct ieee80211_channel carl9170_2ghz_chantable[] = { | ||
97 | CHAN(2412, 0), | ||
98 | CHAN(2417, 1), | ||
99 | CHAN(2422, 2), | ||
100 | CHAN(2427, 3), | ||
101 | CHAN(2432, 4), | ||
102 | CHAN(2437, 5), | ||
103 | CHAN(2442, 6), | ||
104 | CHAN(2447, 7), | ||
105 | CHAN(2452, 8), | ||
106 | CHAN(2457, 9), | ||
107 | CHAN(2462, 10), | ||
108 | CHAN(2467, 11), | ||
109 | CHAN(2472, 12), | ||
110 | CHAN(2484, 13), | ||
111 | }; | ||
112 | |||
113 | static struct ieee80211_channel carl9170_5ghz_chantable[] = { | ||
114 | CHAN(4920, 14), | ||
115 | CHAN(4940, 15), | ||
116 | CHAN(4960, 16), | ||
117 | CHAN(4980, 17), | ||
118 | CHAN(5040, 18), | ||
119 | CHAN(5060, 19), | ||
120 | CHAN(5080, 20), | ||
121 | CHAN(5180, 21), | ||
122 | CHAN(5200, 22), | ||
123 | CHAN(5220, 23), | ||
124 | CHAN(5240, 24), | ||
125 | CHAN(5260, 25), | ||
126 | CHAN(5280, 26), | ||
127 | CHAN(5300, 27), | ||
128 | CHAN(5320, 28), | ||
129 | CHAN(5500, 29), | ||
130 | CHAN(5520, 30), | ||
131 | CHAN(5540, 31), | ||
132 | CHAN(5560, 32), | ||
133 | CHAN(5580, 33), | ||
134 | CHAN(5600, 34), | ||
135 | CHAN(5620, 35), | ||
136 | CHAN(5640, 36), | ||
137 | CHAN(5660, 37), | ||
138 | CHAN(5680, 38), | ||
139 | CHAN(5700, 39), | ||
140 | CHAN(5745, 40), | ||
141 | CHAN(5765, 41), | ||
142 | CHAN(5785, 42), | ||
143 | CHAN(5805, 43), | ||
144 | CHAN(5825, 44), | ||
145 | CHAN(5170, 45), | ||
146 | CHAN(5190, 46), | ||
147 | CHAN(5210, 47), | ||
148 | CHAN(5230, 48), | ||
149 | }; | ||
150 | #undef CHAN | ||
151 | |||
152 | #define CARL9170_HT_CAP \ | ||
153 | { \ | ||
154 | .ht_supported = true, \ | ||
155 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ | ||
156 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | ||
157 | IEEE80211_HT_CAP_SGI_40 | \ | ||
158 | IEEE80211_HT_CAP_DSSSCCK40 | \ | ||
159 | IEEE80211_HT_CAP_SM_PS, \ | ||
160 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ | ||
161 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | ||
162 | .mcs = { \ | ||
163 | .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ | ||
164 | .rx_highest = cpu_to_le16(300), \ | ||
165 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
166 | }, \ | ||
167 | } | ||
168 | |||
169 | static struct ieee80211_supported_band carl9170_band_2GHz = { | ||
170 | .channels = carl9170_2ghz_chantable, | ||
171 | .n_channels = ARRAY_SIZE(carl9170_2ghz_chantable), | ||
172 | .bitrates = carl9170_g_ratetable, | ||
173 | .n_bitrates = carl9170_g_ratetable_size, | ||
174 | .ht_cap = CARL9170_HT_CAP, | ||
175 | }; | ||
176 | |||
177 | static struct ieee80211_supported_band carl9170_band_5GHz = { | ||
178 | .channels = carl9170_5ghz_chantable, | ||
179 | .n_channels = ARRAY_SIZE(carl9170_5ghz_chantable), | ||
180 | .bitrates = carl9170_a_ratetable, | ||
181 | .n_bitrates = carl9170_a_ratetable_size, | ||
182 | .ht_cap = CARL9170_HT_CAP, | ||
183 | }; | ||
184 | |||
185 | static void carl9170_ampdu_gc(struct ar9170 *ar) | ||
186 | { | ||
187 | struct carl9170_sta_tid *tid_info; | ||
188 | LIST_HEAD(tid_gc); | ||
189 | |||
190 | rcu_read_lock(); | ||
191 | list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
192 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
193 | if (tid_info->state == CARL9170_TID_STATE_SHUTDOWN) { | ||
194 | tid_info->state = CARL9170_TID_STATE_KILLED; | ||
195 | list_del_rcu(&tid_info->list); | ||
196 | ar->tx_ampdu_list_len--; | ||
197 | list_add_tail(&tid_info->tmp_list, &tid_gc); | ||
198 | } | ||
199 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
200 | |||
201 | } | ||
202 | rcu_assign_pointer(ar->tx_ampdu_iter, tid_info); | ||
203 | rcu_read_unlock(); | ||
204 | |||
205 | synchronize_rcu(); | ||
206 | |||
207 | while (!list_empty(&tid_gc)) { | ||
208 | struct sk_buff *skb; | ||
209 | tid_info = list_first_entry(&tid_gc, struct carl9170_sta_tid, | ||
210 | tmp_list); | ||
211 | |||
212 | while ((skb = __skb_dequeue(&tid_info->queue))) | ||
213 | carl9170_tx_status(ar, skb, false); | ||
214 | |||
215 | list_del_init(&tid_info->tmp_list); | ||
216 | kfree(tid_info); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void carl9170_flush(struct ar9170 *ar, bool drop_queued) | ||
221 | { | ||
222 | if (drop_queued) { | ||
223 | int i; | ||
224 | |||
225 | /* | ||
226 | * We can only drop frames which have not been uploaded | ||
227 | * to the device yet. | ||
228 | */ | ||
229 | |||
230 | for (i = 0; i < ar->hw->queues; i++) { | ||
231 | struct sk_buff *skb; | ||
232 | |||
233 | while ((skb = skb_dequeue(&ar->tx_pending[i]))) | ||
234 | carl9170_tx_status(ar, skb, false); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /* Wait for all other outstanding frames to timeout. */ | ||
239 | if (atomic_read(&ar->tx_total_queued)) | ||
240 | WARN_ON(wait_for_completion_timeout(&ar->tx_flush, HZ) == 0); | ||
241 | } | ||
242 | |||
243 | static void carl9170_flush_ba(struct ar9170 *ar) | ||
244 | { | ||
245 | struct sk_buff_head free; | ||
246 | struct carl9170_sta_tid *tid_info; | ||
247 | struct sk_buff *skb; | ||
248 | |||
249 | __skb_queue_head_init(&free); | ||
250 | |||
251 | rcu_read_lock(); | ||
252 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
253 | list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
254 | if (tid_info->state > CARL9170_TID_STATE_SUSPEND) { | ||
255 | tid_info->state = CARL9170_TID_STATE_SUSPEND; | ||
256 | |||
257 | spin_lock(&tid_info->lock); | ||
258 | while ((skb = __skb_dequeue(&tid_info->queue))) | ||
259 | __skb_queue_tail(&free, skb); | ||
260 | spin_unlock(&tid_info->lock); | ||
261 | } | ||
262 | } | ||
263 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
264 | rcu_read_unlock(); | ||
265 | |||
266 | while ((skb = __skb_dequeue(&free))) | ||
267 | carl9170_tx_status(ar, skb, false); | ||
268 | } | ||
269 | |||
270 | static void carl9170_zap_queues(struct ar9170 *ar) | ||
271 | { | ||
272 | struct carl9170_vif_info *cvif; | ||
273 | unsigned int i; | ||
274 | |||
275 | carl9170_ampdu_gc(ar); | ||
276 | |||
277 | carl9170_flush_ba(ar); | ||
278 | carl9170_flush(ar, true); | ||
279 | |||
280 | for (i = 0; i < ar->hw->queues; i++) { | ||
281 | spin_lock_bh(&ar->tx_status[i].lock); | ||
282 | while (!skb_queue_empty(&ar->tx_status[i])) { | ||
283 | struct sk_buff *skb; | ||
284 | |||
285 | skb = skb_peek(&ar->tx_status[i]); | ||
286 | carl9170_tx_get_skb(skb); | ||
287 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
288 | carl9170_tx_drop(ar, skb); | ||
289 | spin_lock_bh(&ar->tx_status[i].lock); | ||
290 | carl9170_tx_put_skb(skb); | ||
291 | } | ||
292 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
293 | } | ||
294 | |||
295 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_SOFT < 1); | ||
296 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD < CARL9170_NUM_TX_LIMIT_SOFT); | ||
297 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD >= CARL9170_BAW_BITS); | ||
298 | |||
299 | /* reinitialize queues statistics */ | ||
300 | memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); | ||
301 | for (i = 0; i < ar->hw->queues; i++) | ||
302 | ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD; | ||
303 | |||
304 | for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++) | ||
305 | ar->mem_bitmap[i] = 0; | ||
306 | |||
307 | rcu_read_lock(); | ||
308 | list_for_each_entry_rcu(cvif, &ar->vif_list, list) { | ||
309 | spin_lock_bh(&ar->beacon_lock); | ||
310 | dev_kfree_skb_any(cvif->beacon); | ||
311 | cvif->beacon = NULL; | ||
312 | spin_unlock_bh(&ar->beacon_lock); | ||
313 | } | ||
314 | rcu_read_unlock(); | ||
315 | |||
316 | atomic_set(&ar->tx_ampdu_upload, 0); | ||
317 | atomic_set(&ar->tx_ampdu_scheduler, 0); | ||
318 | atomic_set(&ar->tx_total_pending, 0); | ||
319 | atomic_set(&ar->tx_total_queued, 0); | ||
320 | atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks); | ||
321 | } | ||
322 | |||
323 | #define CARL9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ | ||
324 | do { \ | ||
325 | queue.aifs = ai_fs; \ | ||
326 | queue.cw_min = cwmin; \ | ||
327 | queue.cw_max = cwmax; \ | ||
328 | queue.txop = _txop; \ | ||
329 | } while (0) | ||
330 | |||
331 | static int carl9170_op_start(struct ieee80211_hw *hw) | ||
332 | { | ||
333 | struct ar9170 *ar = hw->priv; | ||
334 | int err, i; | ||
335 | |||
336 | mutex_lock(&ar->mutex); | ||
337 | |||
338 | carl9170_zap_queues(ar); | ||
339 | |||
340 | /* reset QoS defaults */ | ||
341 | CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT */ | ||
342 | CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7, 15, 94); /* VIDEO */ | ||
343 | CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3, 7, 47); /* VOICE */ | ||
344 | CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023, 0); /* BACKGROUND */ | ||
345 | CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ | ||
346 | |||
347 | ar->current_factor = ar->current_density = -1; | ||
348 | /* "The first key is unique." */ | ||
349 | ar->usedkeys = 1; | ||
350 | ar->filter_state = 0; | ||
351 | ar->ps.last_action = jiffies; | ||
352 | ar->ps.last_slept = jiffies; | ||
353 | ar->erp_mode = CARL9170_ERP_AUTO; | ||
354 | ar->rx_software_decryption = false; | ||
355 | ar->disable_offload = false; | ||
356 | |||
357 | for (i = 0; i < ar->hw->queues; i++) { | ||
358 | ar->queue_stop_timeout[i] = jiffies; | ||
359 | ar->max_queue_stop_timeout[i] = 0; | ||
360 | } | ||
361 | |||
362 | atomic_set(&ar->mem_allocs, 0); | ||
363 | |||
364 | err = carl9170_usb_open(ar); | ||
365 | if (err) | ||
366 | goto out; | ||
367 | |||
368 | err = carl9170_init_mac(ar); | ||
369 | if (err) | ||
370 | goto out; | ||
371 | |||
372 | err = carl9170_set_qos(ar); | ||
373 | if (err) | ||
374 | goto out; | ||
375 | |||
376 | err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, | ||
377 | AR9170_DMA_TRIGGER_RXQ); | ||
378 | if (err) | ||
379 | goto out; | ||
380 | |||
381 | /* Clear key-cache */ | ||
382 | for (i = 0; i < AR9170_CAM_MAX_USER + 4; i++) { | ||
383 | err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE, | ||
384 | 0, NULL, 0); | ||
385 | if (err) | ||
386 | goto out; | ||
387 | |||
388 | err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE, | ||
389 | 1, NULL, 0); | ||
390 | if (err) | ||
391 | goto out; | ||
392 | |||
393 | if (i < AR9170_CAM_MAX_USER) { | ||
394 | err = carl9170_disable_key(ar, i); | ||
395 | if (err) | ||
396 | goto out; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); | ||
401 | |||
402 | ieee80211_wake_queues(ar->hw); | ||
403 | err = 0; | ||
404 | |||
405 | out: | ||
406 | mutex_unlock(&ar->mutex); | ||
407 | return err; | ||
408 | } | ||
409 | |||
410 | static void carl9170_cancel_worker(struct ar9170 *ar) | ||
411 | { | ||
412 | cancel_delayed_work_sync(&ar->tx_janitor); | ||
413 | #ifdef CONFIG_CARL9170_LEDS | ||
414 | cancel_delayed_work_sync(&ar->led_work); | ||
415 | #endif /* CONFIG_CARL9170_LEDS */ | ||
416 | cancel_work_sync(&ar->ps_work); | ||
417 | cancel_work_sync(&ar->ampdu_work); | ||
418 | } | ||
419 | |||
420 | static void carl9170_op_stop(struct ieee80211_hw *hw) | ||
421 | { | ||
422 | struct ar9170 *ar = hw->priv; | ||
423 | |||
424 | carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE); | ||
425 | |||
426 | ieee80211_stop_queues(ar->hw); | ||
427 | |||
428 | mutex_lock(&ar->mutex); | ||
429 | if (IS_ACCEPTING_CMD(ar)) { | ||
430 | rcu_assign_pointer(ar->beacon_iter, NULL); | ||
431 | |||
432 | carl9170_led_set_state(ar, 0); | ||
433 | |||
434 | /* stop DMA */ | ||
435 | carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, 0); | ||
436 | carl9170_usb_stop(ar); | ||
437 | } | ||
438 | |||
439 | carl9170_zap_queues(ar); | ||
440 | mutex_unlock(&ar->mutex); | ||
441 | |||
442 | carl9170_cancel_worker(ar); | ||
443 | } | ||
444 | |||
445 | static void carl9170_restart_work(struct work_struct *work) | ||
446 | { | ||
447 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
448 | restart_work); | ||
449 | int err; | ||
450 | |||
451 | ar->usedkeys = 0; | ||
452 | ar->filter_state = 0; | ||
453 | carl9170_cancel_worker(ar); | ||
454 | |||
455 | mutex_lock(&ar->mutex); | ||
456 | err = carl9170_usb_restart(ar); | ||
457 | if (net_ratelimit()) { | ||
458 | if (err) { | ||
459 | dev_err(&ar->udev->dev, "Failed to restart device " | ||
460 | " (%d).\n", err); | ||
461 | } else { | ||
462 | dev_info(&ar->udev->dev, "device restarted " | ||
463 | "successfully.\n"); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | carl9170_zap_queues(ar); | ||
468 | mutex_unlock(&ar->mutex); | ||
469 | if (!err) { | ||
470 | ar->restart_counter++; | ||
471 | atomic_set(&ar->pending_restarts, 0); | ||
472 | |||
473 | ieee80211_restart_hw(ar->hw); | ||
474 | } else { | ||
475 | /* | ||
476 | * The reset was unsuccessful and the device seems to | ||
477 | * be dead. But there's still one option: a low-level | ||
478 | * usb subsystem reset... | ||
479 | */ | ||
480 | |||
481 | carl9170_usb_reset(ar); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) | ||
486 | { | ||
487 | carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE); | ||
488 | |||
489 | /* | ||
490 | * Sometimes, an error can trigger several different reset events. | ||
491 | * By ignoring these *surplus* reset events, the device won't be | ||
492 | * killed again, right after it has recovered. | ||
493 | */ | ||
494 | if (atomic_inc_return(&ar->pending_restarts) > 1) { | ||
495 | dev_dbg(&ar->udev->dev, "ignoring restart (%d)\n", r); | ||
496 | return; | ||
497 | } | ||
498 | |||
499 | ieee80211_stop_queues(ar->hw); | ||
500 | |||
501 | dev_err(&ar->udev->dev, "restart device (%d)\n", r); | ||
502 | |||
503 | if (!WARN_ON(r == CARL9170_RR_NO_REASON) || | ||
504 | !WARN_ON(r >= __CARL9170_RR_LAST)) | ||
505 | ar->last_reason = r; | ||
506 | |||
507 | if (!ar->registered) | ||
508 | return; | ||
509 | |||
510 | if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset) | ||
511 | ieee80211_queue_work(ar->hw, &ar->restart_work); | ||
512 | else | ||
513 | carl9170_usb_reset(ar); | ||
514 | |||
515 | /* | ||
516 | * At this point, the device instance might have vanished/disabled. | ||
517 | * So, don't put any code which access the ar9170 struct | ||
518 | * without proper protection. | ||
519 | */ | ||
520 | } | ||
521 | |||
522 | static int carl9170_init_interface(struct ar9170 *ar, | ||
523 | struct ieee80211_vif *vif) | ||
524 | { | ||
525 | struct ath_common *common = &ar->common; | ||
526 | int err; | ||
527 | |||
528 | if (!vif) { | ||
529 | WARN_ON_ONCE(IS_STARTED(ar)); | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | memcpy(common->macaddr, vif->addr, ETH_ALEN); | ||
534 | |||
535 | if (modparam_nohwcrypt || | ||
536 | ((vif->type != NL80211_IFTYPE_STATION) && | ||
537 | (vif->type != NL80211_IFTYPE_AP))) { | ||
538 | ar->rx_software_decryption = true; | ||
539 | ar->disable_offload = true; | ||
540 | } | ||
541 | |||
542 | err = carl9170_set_operating_mode(ar); | ||
543 | return err; | ||
544 | } | ||
545 | |||
546 | static int carl9170_op_add_interface(struct ieee80211_hw *hw, | ||
547 | struct ieee80211_vif *vif) | ||
548 | { | ||
549 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; | ||
550 | struct ieee80211_vif *main_vif; | ||
551 | struct ar9170 *ar = hw->priv; | ||
552 | int vif_id = -1, err = 0; | ||
553 | |||
554 | mutex_lock(&ar->mutex); | ||
555 | rcu_read_lock(); | ||
556 | if (vif_priv->active) { | ||
557 | /* | ||
558 | * Skip the interface structure initialization, | ||
559 | * if the vif survived the _restart call. | ||
560 | */ | ||
561 | vif_id = vif_priv->id; | ||
562 | vif_priv->enable_beacon = false; | ||
563 | |||
564 | spin_lock_bh(&ar->beacon_lock); | ||
565 | dev_kfree_skb_any(vif_priv->beacon); | ||
566 | vif_priv->beacon = NULL; | ||
567 | spin_unlock_bh(&ar->beacon_lock); | ||
568 | |||
569 | goto init; | ||
570 | } | ||
571 | |||
572 | main_vif = carl9170_get_main_vif(ar); | ||
573 | |||
574 | if (main_vif) { | ||
575 | switch (main_vif->type) { | ||
576 | case NL80211_IFTYPE_STATION: | ||
577 | if (vif->type == NL80211_IFTYPE_STATION) | ||
578 | break; | ||
579 | |||
580 | err = -EBUSY; | ||
581 | rcu_read_unlock(); | ||
582 | |||
583 | goto unlock; | ||
584 | |||
585 | case NL80211_IFTYPE_AP: | ||
586 | if ((vif->type == NL80211_IFTYPE_STATION) || | ||
587 | (vif->type == NL80211_IFTYPE_WDS) || | ||
588 | (vif->type == NL80211_IFTYPE_AP)) | ||
589 | break; | ||
590 | |||
591 | err = -EBUSY; | ||
592 | rcu_read_unlock(); | ||
593 | goto unlock; | ||
594 | |||
595 | default: | ||
596 | rcu_read_unlock(); | ||
597 | goto unlock; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | vif_id = bitmap_find_free_region(&ar->vif_bitmap, ar->fw.vif_num, 0); | ||
602 | |||
603 | if (vif_id < 0) { | ||
604 | rcu_read_unlock(); | ||
605 | |||
606 | err = -ENOSPC; | ||
607 | goto unlock; | ||
608 | } | ||
609 | |||
610 | BUG_ON(ar->vif_priv[vif_id].id != vif_id); | ||
611 | |||
612 | vif_priv->active = true; | ||
613 | vif_priv->id = vif_id; | ||
614 | vif_priv->enable_beacon = false; | ||
615 | ar->vifs++; | ||
616 | list_add_tail_rcu(&vif_priv->list, &ar->vif_list); | ||
617 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); | ||
618 | |||
619 | init: | ||
620 | if (carl9170_get_main_vif(ar) == vif) { | ||
621 | rcu_assign_pointer(ar->beacon_iter, vif_priv); | ||
622 | rcu_read_unlock(); | ||
623 | |||
624 | err = carl9170_init_interface(ar, vif); | ||
625 | if (err) | ||
626 | goto unlock; | ||
627 | } else { | ||
628 | err = carl9170_mod_virtual_mac(ar, vif_id, vif->addr); | ||
629 | rcu_read_unlock(); | ||
630 | |||
631 | if (err) | ||
632 | goto unlock; | ||
633 | } | ||
634 | |||
635 | unlock: | ||
636 | if (err && (vif_id != -1)) { | ||
637 | vif_priv->active = false; | ||
638 | bitmap_release_region(&ar->vif_bitmap, vif_id, 0); | ||
639 | ar->vifs--; | ||
640 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, NULL); | ||
641 | list_del_rcu(&vif_priv->list); | ||
642 | mutex_unlock(&ar->mutex); | ||
643 | synchronize_rcu(); | ||
644 | } else { | ||
645 | if (ar->vifs > 1) | ||
646 | ar->ps.off_override |= PS_OFF_VIF; | ||
647 | |||
648 | mutex_unlock(&ar->mutex); | ||
649 | } | ||
650 | |||
651 | return err; | ||
652 | } | ||
653 | |||
654 | static void carl9170_op_remove_interface(struct ieee80211_hw *hw, | ||
655 | struct ieee80211_vif *vif) | ||
656 | { | ||
657 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; | ||
658 | struct ieee80211_vif *main_vif; | ||
659 | struct ar9170 *ar = hw->priv; | ||
660 | unsigned int id; | ||
661 | |||
662 | mutex_lock(&ar->mutex); | ||
663 | |||
664 | if (WARN_ON_ONCE(!vif_priv->active)) | ||
665 | goto unlock; | ||
666 | |||
667 | ar->vifs--; | ||
668 | |||
669 | rcu_read_lock(); | ||
670 | main_vif = carl9170_get_main_vif(ar); | ||
671 | |||
672 | id = vif_priv->id; | ||
673 | |||
674 | vif_priv->active = false; | ||
675 | WARN_ON(vif_priv->enable_beacon); | ||
676 | vif_priv->enable_beacon = false; | ||
677 | list_del_rcu(&vif_priv->list); | ||
678 | rcu_assign_pointer(ar->vif_priv[id].vif, NULL); | ||
679 | |||
680 | if (vif == main_vif) { | ||
681 | rcu_read_unlock(); | ||
682 | |||
683 | if (ar->vifs) { | ||
684 | WARN_ON(carl9170_init_interface(ar, | ||
685 | carl9170_get_main_vif(ar))); | ||
686 | } else { | ||
687 | carl9170_set_operating_mode(ar); | ||
688 | } | ||
689 | } else { | ||
690 | rcu_read_unlock(); | ||
691 | |||
692 | WARN_ON(carl9170_mod_virtual_mac(ar, id, NULL)); | ||
693 | } | ||
694 | |||
695 | carl9170_update_beacon(ar, false); | ||
696 | carl9170_flush_cab(ar, id); | ||
697 | |||
698 | spin_lock_bh(&ar->beacon_lock); | ||
699 | dev_kfree_skb_any(vif_priv->beacon); | ||
700 | vif_priv->beacon = NULL; | ||
701 | spin_unlock_bh(&ar->beacon_lock); | ||
702 | |||
703 | bitmap_release_region(&ar->vif_bitmap, id, 0); | ||
704 | |||
705 | carl9170_set_beacon_timers(ar); | ||
706 | |||
707 | if (ar->vifs == 1) | ||
708 | ar->ps.off_override &= ~PS_OFF_VIF; | ||
709 | |||
710 | unlock: | ||
711 | mutex_unlock(&ar->mutex); | ||
712 | |||
713 | synchronize_rcu(); | ||
714 | } | ||
715 | |||
716 | void carl9170_ps_check(struct ar9170 *ar) | ||
717 | { | ||
718 | ieee80211_queue_work(ar->hw, &ar->ps_work); | ||
719 | } | ||
720 | |||
721 | /* caller must hold ar->mutex */ | ||
722 | static int carl9170_ps_update(struct ar9170 *ar) | ||
723 | { | ||
724 | bool ps = false; | ||
725 | int err = 0; | ||
726 | |||
727 | if (!ar->ps.off_override) | ||
728 | ps = (ar->hw->conf.flags & IEEE80211_CONF_PS); | ||
729 | |||
730 | if (ps != ar->ps.state) { | ||
731 | err = carl9170_powersave(ar, ps); | ||
732 | if (err) | ||
733 | return err; | ||
734 | |||
735 | if (ar->ps.state && !ps) { | ||
736 | ar->ps.sleep_ms = jiffies_to_msecs(jiffies - | ||
737 | ar->ps.last_action); | ||
738 | } | ||
739 | |||
740 | if (ps) | ||
741 | ar->ps.last_slept = jiffies; | ||
742 | |||
743 | ar->ps.last_action = jiffies; | ||
744 | ar->ps.state = ps; | ||
745 | } | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void carl9170_ps_work(struct work_struct *work) | ||
751 | { | ||
752 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
753 | ps_work); | ||
754 | mutex_lock(&ar->mutex); | ||
755 | if (IS_STARTED(ar)) | ||
756 | WARN_ON_ONCE(carl9170_ps_update(ar) != 0); | ||
757 | mutex_unlock(&ar->mutex); | ||
758 | } | ||
759 | |||
760 | |||
761 | static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) | ||
762 | { | ||
763 | struct ar9170 *ar = hw->priv; | ||
764 | int err = 0; | ||
765 | |||
766 | mutex_lock(&ar->mutex); | ||
767 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { | ||
768 | /* TODO */ | ||
769 | err = 0; | ||
770 | } | ||
771 | |||
772 | if (changed & IEEE80211_CONF_CHANGE_PS) { | ||
773 | err = carl9170_ps_update(ar); | ||
774 | if (err) | ||
775 | goto out; | ||
776 | } | ||
777 | |||
778 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
779 | /* TODO */ | ||
780 | err = 0; | ||
781 | } | ||
782 | |||
783 | if (changed & IEEE80211_CONF_CHANGE_SMPS) { | ||
784 | /* TODO */ | ||
785 | err = 0; | ||
786 | } | ||
787 | |||
788 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
789 | /* adjust slot time for 5 GHz */ | ||
790 | err = carl9170_set_slot_time(ar); | ||
791 | if (err) | ||
792 | goto out; | ||
793 | |||
794 | err = carl9170_set_channel(ar, hw->conf.channel, | ||
795 | hw->conf.channel_type, CARL9170_RFI_NONE); | ||
796 | if (err) | ||
797 | goto out; | ||
798 | |||
799 | err = carl9170_set_dyn_sifs_ack(ar); | ||
800 | if (err) | ||
801 | goto out; | ||
802 | |||
803 | err = carl9170_set_rts_cts_rate(ar); | ||
804 | if (err) | ||
805 | goto out; | ||
806 | } | ||
807 | |||
808 | out: | ||
809 | mutex_unlock(&ar->mutex); | ||
810 | return err; | ||
811 | } | ||
812 | |||
813 | static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw, | ||
814 | struct netdev_hw_addr_list *mc_list) | ||
815 | { | ||
816 | struct netdev_hw_addr *ha; | ||
817 | u64 mchash; | ||
818 | |||
819 | /* always get broadcast frames */ | ||
820 | mchash = 1ULL << (0xff >> 2); | ||
821 | |||
822 | netdev_hw_addr_list_for_each(ha, mc_list) | ||
823 | mchash |= 1ULL << (ha->addr[5] >> 2); | ||
824 | |||
825 | return mchash; | ||
826 | } | ||
827 | |||
828 | static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | ||
829 | unsigned int changed_flags, | ||
830 | unsigned int *new_flags, | ||
831 | u64 multicast) | ||
832 | { | ||
833 | struct ar9170 *ar = hw->priv; | ||
834 | |||
835 | /* mask supported flags */ | ||
836 | *new_flags &= FIF_ALLMULTI | FIF_FCSFAIL | FIF_PLCPFAIL | | ||
837 | FIF_OTHER_BSS | FIF_PROMISC_IN_BSS; | ||
838 | |||
839 | if (!IS_ACCEPTING_CMD(ar)) | ||
840 | return; | ||
841 | |||
842 | mutex_lock(&ar->mutex); | ||
843 | |||
844 | ar->filter_state = *new_flags; | ||
845 | /* | ||
846 | * We can support more by setting the sniffer bit and | ||
847 | * then checking the error flags, later. | ||
848 | */ | ||
849 | |||
850 | if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) | ||
851 | multicast = ~0ULL; | ||
852 | |||
853 | if (multicast != ar->cur_mc_hash) | ||
854 | WARN_ON(carl9170_update_multicast(ar, multicast)); | ||
855 | |||
856 | if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { | ||
857 | ar->sniffer_enabled = !!(*new_flags & | ||
858 | (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)); | ||
859 | |||
860 | WARN_ON(carl9170_set_operating_mode(ar)); | ||
861 | } | ||
862 | |||
863 | mutex_unlock(&ar->mutex); | ||
864 | } | ||
865 | |||
866 | |||
867 | static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw, | ||
868 | struct ieee80211_vif *vif, | ||
869 | struct ieee80211_bss_conf *bss_conf, | ||
870 | u32 changed) | ||
871 | { | ||
872 | struct ar9170 *ar = hw->priv; | ||
873 | struct ath_common *common = &ar->common; | ||
874 | int err = 0; | ||
875 | struct carl9170_vif_info *vif_priv; | ||
876 | struct ieee80211_vif *main_vif; | ||
877 | |||
878 | mutex_lock(&ar->mutex); | ||
879 | vif_priv = (void *) vif->drv_priv; | ||
880 | main_vif = carl9170_get_main_vif(ar); | ||
881 | if (WARN_ON(!main_vif)) | ||
882 | goto out; | ||
883 | |||
884 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
885 | struct carl9170_vif_info *iter; | ||
886 | int i = 0; | ||
887 | |||
888 | vif_priv->enable_beacon = bss_conf->enable_beacon; | ||
889 | rcu_read_lock(); | ||
890 | list_for_each_entry_rcu(iter, &ar->vif_list, list) { | ||
891 | if (iter->active && iter->enable_beacon) | ||
892 | i++; | ||
893 | |||
894 | } | ||
895 | rcu_read_unlock(); | ||
896 | |||
897 | ar->beacon_enabled = i; | ||
898 | } | ||
899 | |||
900 | if (changed & BSS_CHANGED_BEACON) { | ||
901 | err = carl9170_update_beacon(ar, false); | ||
902 | if (err) | ||
903 | goto out; | ||
904 | } | ||
905 | |||
906 | if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | | ||
907 | BSS_CHANGED_BEACON_INT)) { | ||
908 | |||
909 | if (main_vif != vif) { | ||
910 | bss_conf->beacon_int = main_vif->bss_conf.beacon_int; | ||
911 | bss_conf->dtim_period = main_vif->bss_conf.dtim_period; | ||
912 | } | ||
913 | |||
914 | /* | ||
915 | * Therefore a hard limit for the broadcast traffic should | ||
916 | * prevent false alarms. | ||
917 | */ | ||
918 | if (vif->type != NL80211_IFTYPE_STATION && | ||
919 | (bss_conf->beacon_int * bss_conf->dtim_period >= | ||
920 | (CARL9170_QUEUE_STUCK_TIMEOUT / 2))) { | ||
921 | err = -EINVAL; | ||
922 | goto out; | ||
923 | } | ||
924 | |||
925 | err = carl9170_set_beacon_timers(ar); | ||
926 | if (err) | ||
927 | goto out; | ||
928 | } | ||
929 | |||
930 | if (changed & BSS_CHANGED_HT) { | ||
931 | /* TODO */ | ||
932 | err = 0; | ||
933 | if (err) | ||
934 | goto out; | ||
935 | } | ||
936 | |||
937 | if (main_vif != vif) | ||
938 | goto out; | ||
939 | |||
940 | /* | ||
941 | * The following settings can only be changed by the | ||
942 | * master interface. | ||
943 | */ | ||
944 | |||
945 | if (changed & BSS_CHANGED_BSSID) { | ||
946 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
947 | err = carl9170_set_operating_mode(ar); | ||
948 | if (err) | ||
949 | goto out; | ||
950 | } | ||
951 | |||
952 | if (changed & BSS_CHANGED_ASSOC) { | ||
953 | ar->common.curaid = bss_conf->aid; | ||
954 | err = carl9170_set_beacon_timers(ar); | ||
955 | if (err) | ||
956 | goto out; | ||
957 | } | ||
958 | |||
959 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
960 | err = carl9170_set_slot_time(ar); | ||
961 | if (err) | ||
962 | goto out; | ||
963 | } | ||
964 | |||
965 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
966 | err = carl9170_set_mac_rates(ar); | ||
967 | if (err) | ||
968 | goto out; | ||
969 | } | ||
970 | |||
971 | out: | ||
972 | WARN_ON_ONCE(err && IS_STARTED(ar)); | ||
973 | mutex_unlock(&ar->mutex); | ||
974 | } | ||
975 | |||
976 | static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw) | ||
977 | { | ||
978 | struct ar9170 *ar = hw->priv; | ||
979 | struct carl9170_tsf_rsp tsf; | ||
980 | int err; | ||
981 | |||
982 | mutex_lock(&ar->mutex); | ||
983 | err = carl9170_exec_cmd(ar, CARL9170_CMD_READ_TSF, | ||
984 | 0, NULL, sizeof(tsf), &tsf); | ||
985 | mutex_unlock(&ar->mutex); | ||
986 | if (WARN_ON(err)) | ||
987 | return 0; | ||
988 | |||
989 | return le64_to_cpu(tsf.tsf_64); | ||
990 | } | ||
991 | |||
992 | static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
993 | struct ieee80211_vif *vif, | ||
994 | struct ieee80211_sta *sta, | ||
995 | struct ieee80211_key_conf *key) | ||
996 | { | ||
997 | struct ar9170 *ar = hw->priv; | ||
998 | int err = 0, i; | ||
999 | u8 ktype; | ||
1000 | |||
1001 | if (ar->disable_offload || !vif) | ||
1002 | return -EOPNOTSUPP; | ||
1003 | |||
1004 | /* | ||
1005 | * We have to fall back to software encryption, whenever | ||
1006 | * the user choose to participates in an IBSS or is connected | ||
1007 | * to more than one network. | ||
1008 | * | ||
1009 | * This is very unfortunate, because some machines cannot handle | ||
1010 | * the high througput speed in 802.11n networks. | ||
1011 | */ | ||
1012 | |||
1013 | if (!is_main_vif(ar, vif)) | ||
1014 | goto err_softw; | ||
1015 | |||
1016 | /* | ||
1017 | * While the hardware supports *catch-all* key, for offloading | ||
1018 | * group-key en-/de-cryption. The way of how the hardware | ||
1019 | * decides which keyId maps to which key, remains a mystery... | ||
1020 | */ | ||
1021 | if ((vif->type != NL80211_IFTYPE_STATION && | ||
1022 | vif->type != NL80211_IFTYPE_ADHOC) && | ||
1023 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1024 | return -EOPNOTSUPP; | ||
1025 | |||
1026 | switch (key->cipher) { | ||
1027 | case WLAN_CIPHER_SUITE_WEP40: | ||
1028 | ktype = AR9170_ENC_ALG_WEP64; | ||
1029 | break; | ||
1030 | case WLAN_CIPHER_SUITE_WEP104: | ||
1031 | ktype = AR9170_ENC_ALG_WEP128; | ||
1032 | break; | ||
1033 | case WLAN_CIPHER_SUITE_TKIP: | ||
1034 | ktype = AR9170_ENC_ALG_TKIP; | ||
1035 | break; | ||
1036 | case WLAN_CIPHER_SUITE_CCMP: | ||
1037 | ktype = AR9170_ENC_ALG_AESCCMP; | ||
1038 | break; | ||
1039 | default: | ||
1040 | return -EOPNOTSUPP; | ||
1041 | } | ||
1042 | |||
1043 | mutex_lock(&ar->mutex); | ||
1044 | if (cmd == SET_KEY) { | ||
1045 | if (!IS_STARTED(ar)) { | ||
1046 | err = -EOPNOTSUPP; | ||
1047 | goto out; | ||
1048 | } | ||
1049 | |||
1050 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
1051 | sta = NULL; | ||
1052 | |||
1053 | i = 64 + key->keyidx; | ||
1054 | } else { | ||
1055 | for (i = 0; i < 64; i++) | ||
1056 | if (!(ar->usedkeys & BIT(i))) | ||
1057 | break; | ||
1058 | if (i == 64) | ||
1059 | goto err_softw; | ||
1060 | } | ||
1061 | |||
1062 | key->hw_key_idx = i; | ||
1063 | |||
1064 | err = carl9170_upload_key(ar, i, sta ? sta->addr : NULL, | ||
1065 | ktype, 0, key->key, | ||
1066 | min_t(u8, 16, key->keylen)); | ||
1067 | if (err) | ||
1068 | goto out; | ||
1069 | |||
1070 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1071 | err = carl9170_upload_key(ar, i, sta ? sta->addr : | ||
1072 | NULL, ktype, 1, | ||
1073 | key->key + 16, 16); | ||
1074 | if (err) | ||
1075 | goto out; | ||
1076 | |||
1077 | /* | ||
1078 | * hardware is not capable generating MMIC | ||
1079 | * of fragmented frames! | ||
1080 | */ | ||
1081 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
1082 | } | ||
1083 | |||
1084 | if (i < 64) | ||
1085 | ar->usedkeys |= BIT(i); | ||
1086 | |||
1087 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1088 | } else { | ||
1089 | if (!IS_STARTED(ar)) { | ||
1090 | /* The device is gone... together with the key ;-) */ | ||
1091 | err = 0; | ||
1092 | goto out; | ||
1093 | } | ||
1094 | |||
1095 | if (key->hw_key_idx < 64) { | ||
1096 | ar->usedkeys &= ~BIT(key->hw_key_idx); | ||
1097 | } else { | ||
1098 | err = carl9170_upload_key(ar, key->hw_key_idx, NULL, | ||
1099 | AR9170_ENC_ALG_NONE, 0, | ||
1100 | NULL, 0); | ||
1101 | if (err) | ||
1102 | goto out; | ||
1103 | |||
1104 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1105 | err = carl9170_upload_key(ar, key->hw_key_idx, | ||
1106 | NULL, | ||
1107 | AR9170_ENC_ALG_NONE, | ||
1108 | 1, NULL, 0); | ||
1109 | if (err) | ||
1110 | goto out; | ||
1111 | } | ||
1112 | |||
1113 | } | ||
1114 | |||
1115 | err = carl9170_disable_key(ar, key->hw_key_idx); | ||
1116 | if (err) | ||
1117 | goto out; | ||
1118 | } | ||
1119 | |||
1120 | out: | ||
1121 | mutex_unlock(&ar->mutex); | ||
1122 | return err; | ||
1123 | |||
1124 | err_softw: | ||
1125 | if (!ar->rx_software_decryption) { | ||
1126 | ar->rx_software_decryption = true; | ||
1127 | carl9170_set_operating_mode(ar); | ||
1128 | } | ||
1129 | mutex_unlock(&ar->mutex); | ||
1130 | return -ENOSPC; | ||
1131 | } | ||
1132 | |||
1133 | static int carl9170_op_sta_add(struct ieee80211_hw *hw, | ||
1134 | struct ieee80211_vif *vif, | ||
1135 | struct ieee80211_sta *sta) | ||
1136 | { | ||
1137 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1138 | unsigned int i; | ||
1139 | |||
1140 | if (sta->ht_cap.ht_supported) { | ||
1141 | if (sta->ht_cap.ampdu_density > 6) { | ||
1142 | /* | ||
1143 | * HW does support 16us AMPDU density. | ||
1144 | * No HT-Xmit for station. | ||
1145 | */ | ||
1146 | |||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | for (i = 0; i < CARL9170_NUM_TID; i++) | ||
1151 | rcu_assign_pointer(sta_info->agg[i], NULL); | ||
1152 | |||
1153 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | ||
1154 | sta_info->ht_sta = true; | ||
1155 | } | ||
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | static int carl9170_op_sta_remove(struct ieee80211_hw *hw, | ||
1161 | struct ieee80211_vif *vif, | ||
1162 | struct ieee80211_sta *sta) | ||
1163 | { | ||
1164 | struct ar9170 *ar = hw->priv; | ||
1165 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1166 | unsigned int i; | ||
1167 | bool cleanup = false; | ||
1168 | |||
1169 | if (sta->ht_cap.ht_supported) { | ||
1170 | |||
1171 | sta_info->ht_sta = false; | ||
1172 | |||
1173 | rcu_read_lock(); | ||
1174 | for (i = 0; i < CARL9170_NUM_TID; i++) { | ||
1175 | struct carl9170_sta_tid *tid_info; | ||
1176 | |||
1177 | tid_info = rcu_dereference(sta_info->agg[i]); | ||
1178 | rcu_assign_pointer(sta_info->agg[i], NULL); | ||
1179 | |||
1180 | if (!tid_info) | ||
1181 | continue; | ||
1182 | |||
1183 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1184 | if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN) | ||
1185 | tid_info->state = CARL9170_TID_STATE_SHUTDOWN; | ||
1186 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1187 | cleanup = true; | ||
1188 | } | ||
1189 | rcu_read_unlock(); | ||
1190 | |||
1191 | if (cleanup) | ||
1192 | carl9170_ampdu_gc(ar); | ||
1193 | } | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1199 | const struct ieee80211_tx_queue_params *param) | ||
1200 | { | ||
1201 | struct ar9170 *ar = hw->priv; | ||
1202 | int ret; | ||
1203 | |||
1204 | mutex_lock(&ar->mutex); | ||
1205 | if (queue < ar->hw->queues) { | ||
1206 | memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param)); | ||
1207 | ret = carl9170_set_qos(ar); | ||
1208 | } else { | ||
1209 | ret = -EINVAL; | ||
1210 | } | ||
1211 | |||
1212 | mutex_unlock(&ar->mutex); | ||
1213 | return ret; | ||
1214 | } | ||
1215 | |||
1216 | static void carl9170_ampdu_work(struct work_struct *work) | ||
1217 | { | ||
1218 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
1219 | ampdu_work); | ||
1220 | |||
1221 | if (!IS_STARTED(ar)) | ||
1222 | return; | ||
1223 | |||
1224 | mutex_lock(&ar->mutex); | ||
1225 | carl9170_ampdu_gc(ar); | ||
1226 | mutex_unlock(&ar->mutex); | ||
1227 | } | ||
1228 | |||
1229 | static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, | ||
1230 | struct ieee80211_vif *vif, | ||
1231 | enum ieee80211_ampdu_mlme_action action, | ||
1232 | struct ieee80211_sta *sta, | ||
1233 | u16 tid, u16 *ssn) | ||
1234 | { | ||
1235 | struct ar9170 *ar = hw->priv; | ||
1236 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1237 | struct carl9170_sta_tid *tid_info; | ||
1238 | |||
1239 | if (modparam_noht) | ||
1240 | return -EOPNOTSUPP; | ||
1241 | |||
1242 | switch (action) { | ||
1243 | case IEEE80211_AMPDU_TX_START: | ||
1244 | if (WARN_ON_ONCE(!sta_info->ht_sta)) | ||
1245 | return -EOPNOTSUPP; | ||
1246 | |||
1247 | rcu_read_lock(); | ||
1248 | if (rcu_dereference(sta_info->agg[tid])) { | ||
1249 | rcu_read_unlock(); | ||
1250 | return -EBUSY; | ||
1251 | } | ||
1252 | |||
1253 | tid_info = kzalloc(sizeof(struct carl9170_sta_tid), | ||
1254 | GFP_ATOMIC); | ||
1255 | if (!tid_info) { | ||
1256 | rcu_read_unlock(); | ||
1257 | return -ENOMEM; | ||
1258 | } | ||
1259 | |||
1260 | tid_info->hsn = tid_info->bsn = tid_info->snx = (*ssn); | ||
1261 | tid_info->state = CARL9170_TID_STATE_PROGRESS; | ||
1262 | tid_info->tid = tid; | ||
1263 | tid_info->max = sta_info->ampdu_max_len; | ||
1264 | |||
1265 | INIT_LIST_HEAD(&tid_info->list); | ||
1266 | INIT_LIST_HEAD(&tid_info->tmp_list); | ||
1267 | skb_queue_head_init(&tid_info->queue); | ||
1268 | spin_lock_init(&tid_info->lock); | ||
1269 | |||
1270 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1271 | ar->tx_ampdu_list_len++; | ||
1272 | list_add_tail_rcu(&tid_info->list, &ar->tx_ampdu_list); | ||
1273 | rcu_assign_pointer(sta_info->agg[tid], tid_info); | ||
1274 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1275 | rcu_read_unlock(); | ||
1276 | |||
1277 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1278 | break; | ||
1279 | |||
1280 | case IEEE80211_AMPDU_TX_STOP: | ||
1281 | rcu_read_lock(); | ||
1282 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
1283 | if (tid_info) { | ||
1284 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1285 | if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN) | ||
1286 | tid_info->state = CARL9170_TID_STATE_SHUTDOWN; | ||
1287 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1288 | } | ||
1289 | |||
1290 | rcu_assign_pointer(sta_info->agg[tid], NULL); | ||
1291 | rcu_read_unlock(); | ||
1292 | |||
1293 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1294 | ieee80211_queue_work(ar->hw, &ar->ampdu_work); | ||
1295 | break; | ||
1296 | |||
1297 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
1298 | rcu_read_lock(); | ||
1299 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
1300 | |||
1301 | sta_info->stats[tid].clear = true; | ||
1302 | |||
1303 | if (tid_info) { | ||
1304 | bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE); | ||
1305 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1306 | } | ||
1307 | rcu_read_unlock(); | ||
1308 | |||
1309 | if (WARN_ON_ONCE(!tid_info)) | ||
1310 | return -EFAULT; | ||
1311 | |||
1312 | break; | ||
1313 | |||
1314 | case IEEE80211_AMPDU_RX_START: | ||
1315 | case IEEE80211_AMPDU_RX_STOP: | ||
1316 | /* Handled by hardware */ | ||
1317 | break; | ||
1318 | |||
1319 | default: | ||
1320 | return -EOPNOTSUPP; | ||
1321 | } | ||
1322 | |||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | #ifdef CONFIG_CARL9170_WPC | ||
1327 | static int carl9170_register_wps_button(struct ar9170 *ar) | ||
1328 | { | ||
1329 | struct input_dev *input; | ||
1330 | int err; | ||
1331 | |||
1332 | if (!(ar->features & CARL9170_WPS_BUTTON)) | ||
1333 | return 0; | ||
1334 | |||
1335 | input = input_allocate_device(); | ||
1336 | if (!input) | ||
1337 | return -ENOMEM; | ||
1338 | |||
1339 | snprintf(ar->wps.name, sizeof(ar->wps.name), "%s WPS Button", | ||
1340 | wiphy_name(ar->hw->wiphy)); | ||
1341 | |||
1342 | snprintf(ar->wps.phys, sizeof(ar->wps.phys), | ||
1343 | "ieee80211/%s/input0", wiphy_name(ar->hw->wiphy)); | ||
1344 | |||
1345 | input->name = ar->wps.name; | ||
1346 | input->phys = ar->wps.phys; | ||
1347 | input->id.bustype = BUS_USB; | ||
1348 | input->dev.parent = &ar->hw->wiphy->dev; | ||
1349 | |||
1350 | input_set_capability(input, EV_KEY, KEY_WPS_BUTTON); | ||
1351 | |||
1352 | err = input_register_device(input); | ||
1353 | if (err) { | ||
1354 | input_free_device(input); | ||
1355 | return err; | ||
1356 | } | ||
1357 | |||
1358 | ar->wps.pbc = input; | ||
1359 | return 0; | ||
1360 | } | ||
1361 | #endif /* CONFIG_CARL9170_WPC */ | ||
1362 | |||
1363 | static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, | ||
1364 | struct survey_info *survey) | ||
1365 | { | ||
1366 | struct ar9170 *ar = hw->priv; | ||
1367 | int err; | ||
1368 | |||
1369 | if (idx != 0) | ||
1370 | return -ENOENT; | ||
1371 | |||
1372 | mutex_lock(&ar->mutex); | ||
1373 | err = carl9170_get_noisefloor(ar); | ||
1374 | mutex_unlock(&ar->mutex); | ||
1375 | if (err) | ||
1376 | return err; | ||
1377 | |||
1378 | survey->channel = ar->channel; | ||
1379 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1380 | survey->noise = ar->noise[0]; | ||
1381 | return 0; | ||
1382 | } | ||
1383 | |||
1384 | static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop) | ||
1385 | { | ||
1386 | struct ar9170 *ar = hw->priv; | ||
1387 | unsigned int vid; | ||
1388 | |||
1389 | mutex_lock(&ar->mutex); | ||
1390 | for_each_set_bit(vid, &ar->vif_bitmap, ar->fw.vif_num) | ||
1391 | carl9170_flush_cab(ar, vid); | ||
1392 | |||
1393 | carl9170_flush(ar, drop); | ||
1394 | mutex_unlock(&ar->mutex); | ||
1395 | } | ||
1396 | |||
1397 | static int carl9170_op_get_stats(struct ieee80211_hw *hw, | ||
1398 | struct ieee80211_low_level_stats *stats) | ||
1399 | { | ||
1400 | struct ar9170 *ar = hw->priv; | ||
1401 | |||
1402 | memset(stats, 0, sizeof(*stats)); | ||
1403 | stats->dot11ACKFailureCount = ar->tx_ack_failures; | ||
1404 | stats->dot11FCSErrorCount = ar->tx_fcs_errors; | ||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | static void carl9170_op_sta_notify(struct ieee80211_hw *hw, | ||
1409 | struct ieee80211_vif *vif, | ||
1410 | enum sta_notify_cmd cmd, | ||
1411 | struct ieee80211_sta *sta) | ||
1412 | { | ||
1413 | struct ar9170 *ar = hw->priv; | ||
1414 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1415 | struct sk_buff *skb, *tmp; | ||
1416 | struct sk_buff_head free; | ||
1417 | int i; | ||
1418 | |||
1419 | switch (cmd) { | ||
1420 | case STA_NOTIFY_SLEEP: | ||
1421 | /* | ||
1422 | * Since the peer is no longer listening, we have to return | ||
1423 | * as many SKBs as possible back to the mac80211 stack. | ||
1424 | * It will deal with the retry procedure, once the peer | ||
1425 | * has become available again. | ||
1426 | * | ||
1427 | * NB: Ideally, the driver should return the all frames in | ||
1428 | * the correct, ascending order. However, I think that this | ||
1429 | * functionality should be implemented in the stack and not | ||
1430 | * here... | ||
1431 | */ | ||
1432 | |||
1433 | __skb_queue_head_init(&free); | ||
1434 | |||
1435 | if (sta->ht_cap.ht_supported) { | ||
1436 | rcu_read_lock(); | ||
1437 | for (i = 0; i < CARL9170_NUM_TID; i++) { | ||
1438 | struct carl9170_sta_tid *tid_info; | ||
1439 | |||
1440 | tid_info = rcu_dereference(sta_info->agg[i]); | ||
1441 | |||
1442 | if (!tid_info) | ||
1443 | continue; | ||
1444 | |||
1445 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1446 | if (tid_info->state > | ||
1447 | CARL9170_TID_STATE_SUSPEND) | ||
1448 | tid_info->state = | ||
1449 | CARL9170_TID_STATE_SUSPEND; | ||
1450 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1451 | |||
1452 | spin_lock_bh(&tid_info->lock); | ||
1453 | while ((skb = __skb_dequeue(&tid_info->queue))) | ||
1454 | __skb_queue_tail(&free, skb); | ||
1455 | spin_unlock_bh(&tid_info->lock); | ||
1456 | |||
1457 | ieee80211_stop_tx_ba_session(sta, | ||
1458 | tid_info->tid); | ||
1459 | } | ||
1460 | rcu_read_unlock(); | ||
1461 | } | ||
1462 | |||
1463 | for (i = 0; i < ar->hw->queues; i++) { | ||
1464 | spin_lock_bh(&ar->tx_pending[i].lock); | ||
1465 | skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) { | ||
1466 | struct _carl9170_tx_superframe *super; | ||
1467 | struct ieee80211_hdr *hdr; | ||
1468 | |||
1469 | super = (void *) skb->data; | ||
1470 | hdr = (void *) super->frame_data; | ||
1471 | |||
1472 | if (compare_ether_addr(hdr->addr1, sta->addr)) | ||
1473 | continue; | ||
1474 | |||
1475 | __skb_unlink(skb, &ar->tx_pending[i]); | ||
1476 | carl9170_tx_status(ar, skb, false); | ||
1477 | } | ||
1478 | spin_unlock_bh(&ar->tx_pending[i].lock); | ||
1479 | } | ||
1480 | |||
1481 | while ((skb = __skb_dequeue(&free))) | ||
1482 | carl9170_tx_status(ar, skb, false); | ||
1483 | |||
1484 | break; | ||
1485 | |||
1486 | case STA_NOTIFY_AWAKE: | ||
1487 | if (!sta->ht_cap.ht_supported) | ||
1488 | return; | ||
1489 | |||
1490 | rcu_read_lock(); | ||
1491 | for (i = 0; i < CARL9170_NUM_TID; i++) { | ||
1492 | struct carl9170_sta_tid *tid_info; | ||
1493 | |||
1494 | tid_info = rcu_dereference(sta_info->agg[i]); | ||
1495 | |||
1496 | if (!tid_info) | ||
1497 | continue; | ||
1498 | |||
1499 | if ((tid_info->state == CARL9170_TID_STATE_SUSPEND)) | ||
1500 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1501 | } | ||
1502 | rcu_read_unlock(); | ||
1503 | break; | ||
1504 | } | ||
1505 | } | ||
1506 | |||
1507 | static const struct ieee80211_ops carl9170_ops = { | ||
1508 | .start = carl9170_op_start, | ||
1509 | .stop = carl9170_op_stop, | ||
1510 | .tx = carl9170_op_tx, | ||
1511 | .flush = carl9170_op_flush, | ||
1512 | .add_interface = carl9170_op_add_interface, | ||
1513 | .remove_interface = carl9170_op_remove_interface, | ||
1514 | .config = carl9170_op_config, | ||
1515 | .prepare_multicast = carl9170_op_prepare_multicast, | ||
1516 | .configure_filter = carl9170_op_configure_filter, | ||
1517 | .conf_tx = carl9170_op_conf_tx, | ||
1518 | .bss_info_changed = carl9170_op_bss_info_changed, | ||
1519 | .get_tsf = carl9170_op_get_tsf, | ||
1520 | .set_key = carl9170_op_set_key, | ||
1521 | .sta_add = carl9170_op_sta_add, | ||
1522 | .sta_remove = carl9170_op_sta_remove, | ||
1523 | .sta_notify = carl9170_op_sta_notify, | ||
1524 | .get_survey = carl9170_op_get_survey, | ||
1525 | .get_stats = carl9170_op_get_stats, | ||
1526 | .ampdu_action = carl9170_op_ampdu_action, | ||
1527 | }; | ||
1528 | |||
1529 | void *carl9170_alloc(size_t priv_size) | ||
1530 | { | ||
1531 | struct ieee80211_hw *hw; | ||
1532 | struct ar9170 *ar; | ||
1533 | struct sk_buff *skb; | ||
1534 | int i; | ||
1535 | |||
1536 | /* | ||
1537 | * this buffer is used for rx stream reconstruction. | ||
1538 | * Under heavy load this device (or the transport layer?) | ||
1539 | * tends to split the streams into separate rx descriptors. | ||
1540 | */ | ||
1541 | |||
1542 | skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); | ||
1543 | if (!skb) | ||
1544 | goto err_nomem; | ||
1545 | |||
1546 | hw = ieee80211_alloc_hw(priv_size, &carl9170_ops); | ||
1547 | if (!hw) | ||
1548 | goto err_nomem; | ||
1549 | |||
1550 | ar = hw->priv; | ||
1551 | ar->hw = hw; | ||
1552 | ar->rx_failover = skb; | ||
1553 | |||
1554 | memset(&ar->rx_plcp, 0, sizeof(struct ar9170_rx_head)); | ||
1555 | ar->rx_has_plcp = false; | ||
1556 | |||
1557 | /* | ||
1558 | * Here's a hidden pitfall! | ||
1559 | * | ||
1560 | * All 4 AC queues work perfectly well under _legacy_ operation. | ||
1561 | * However as soon as aggregation is enabled, the traffic flow | ||
1562 | * gets very bumpy. Therefore we have to _switch_ to a | ||
1563 | * software AC with a single HW queue. | ||
1564 | */ | ||
1565 | hw->queues = __AR9170_NUM_TXQ; | ||
1566 | |||
1567 | mutex_init(&ar->mutex); | ||
1568 | spin_lock_init(&ar->beacon_lock); | ||
1569 | spin_lock_init(&ar->cmd_lock); | ||
1570 | spin_lock_init(&ar->tx_stats_lock); | ||
1571 | spin_lock_init(&ar->tx_ampdu_list_lock); | ||
1572 | spin_lock_init(&ar->mem_lock); | ||
1573 | spin_lock_init(&ar->state_lock); | ||
1574 | atomic_set(&ar->pending_restarts, 0); | ||
1575 | ar->vifs = 0; | ||
1576 | for (i = 0; i < ar->hw->queues; i++) { | ||
1577 | skb_queue_head_init(&ar->tx_status[i]); | ||
1578 | skb_queue_head_init(&ar->tx_pending[i]); | ||
1579 | } | ||
1580 | INIT_WORK(&ar->ps_work, carl9170_ps_work); | ||
1581 | INIT_WORK(&ar->restart_work, carl9170_restart_work); | ||
1582 | INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); | ||
1583 | INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); | ||
1584 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | ||
1585 | rcu_assign_pointer(ar->tx_ampdu_iter, | ||
1586 | (struct carl9170_sta_tid *) &ar->tx_ampdu_list); | ||
1587 | |||
1588 | bitmap_zero(&ar->vif_bitmap, ar->fw.vif_num); | ||
1589 | INIT_LIST_HEAD(&ar->vif_list); | ||
1590 | init_completion(&ar->tx_flush); | ||
1591 | |||
1592 | /* | ||
1593 | * Note: | ||
1594 | * IBSS/ADHOC and AP mode are only enabled, if the firmware | ||
1595 | * supports these modes. The code which will add the | ||
1596 | * additional interface_modes is in fw.c. | ||
1597 | */ | ||
1598 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
1599 | |||
1600 | hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | | ||
1601 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
1602 | IEEE80211_HW_SUPPORTS_PS | | ||
1603 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
1604 | IEEE80211_HW_SIGNAL_DBM; | ||
1605 | |||
1606 | if (!modparam_noht) { | ||
1607 | /* | ||
1608 | * see the comment above, why we allow the user | ||
1609 | * to disable HT by a module parameter. | ||
1610 | */ | ||
1611 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
1612 | } | ||
1613 | |||
1614 | hw->extra_tx_headroom = sizeof(struct _carl9170_tx_superframe); | ||
1615 | hw->sta_data_size = sizeof(struct carl9170_sta_info); | ||
1616 | hw->vif_data_size = sizeof(struct carl9170_vif_info); | ||
1617 | |||
1618 | hw->max_rates = CARL9170_TX_MAX_RATES; | ||
1619 | hw->max_rate_tries = CARL9170_TX_USER_RATE_TRIES; | ||
1620 | |||
1621 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | ||
1622 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | ||
1623 | |||
1624 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1625 | return ar; | ||
1626 | |||
1627 | err_nomem: | ||
1628 | kfree_skb(skb); | ||
1629 | return ERR_PTR(-ENOMEM); | ||
1630 | } | ||
1631 | |||
1632 | static int carl9170_read_eeprom(struct ar9170 *ar) | ||
1633 | { | ||
1634 | #define RW 8 /* number of words to read at once */ | ||
1635 | #define RB (sizeof(u32) * RW) | ||
1636 | u8 *eeprom = (void *)&ar->eeprom; | ||
1637 | __le32 offsets[RW]; | ||
1638 | int i, j, err; | ||
1639 | |||
1640 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); | ||
1641 | |||
1642 | BUILD_BUG_ON(RB > CARL9170_MAX_CMD_LEN - 4); | ||
1643 | #ifndef __CHECKER__ | ||
1644 | /* don't want to handle trailing remains */ | ||
1645 | BUILD_BUG_ON(sizeof(ar->eeprom) % RB); | ||
1646 | #endif | ||
1647 | |||
1648 | for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { | ||
1649 | for (j = 0; j < RW; j++) | ||
1650 | offsets[j] = cpu_to_le32(AR9170_EEPROM_START + | ||
1651 | RB * i + 4 * j); | ||
1652 | |||
1653 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, | ||
1654 | RB, (u8 *) &offsets, | ||
1655 | RB, eeprom + RB * i); | ||
1656 | if (err) | ||
1657 | return err; | ||
1658 | } | ||
1659 | |||
1660 | #undef RW | ||
1661 | #undef RB | ||
1662 | return 0; | ||
1663 | } | ||
1664 | |||
1665 | static int carl9170_parse_eeprom(struct ar9170 *ar) | ||
1666 | { | ||
1667 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
1668 | unsigned int rx_streams, tx_streams, tx_params = 0; | ||
1669 | int bands = 0; | ||
1670 | |||
1671 | if (ar->eeprom.length == cpu_to_le16(0xffff)) | ||
1672 | return -ENODATA; | ||
1673 | |||
1674 | rx_streams = hweight8(ar->eeprom.rx_mask); | ||
1675 | tx_streams = hweight8(ar->eeprom.tx_mask); | ||
1676 | |||
1677 | if (rx_streams != tx_streams) { | ||
1678 | tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1679 | |||
1680 | WARN_ON(!(tx_streams >= 1 && tx_streams <= | ||
1681 | IEEE80211_HT_MCS_TX_MAX_STREAMS)); | ||
1682 | |||
1683 | tx_params = (tx_streams - 1) << | ||
1684 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
1685 | |||
1686 | carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; | ||
1687 | carl9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; | ||
1688 | } | ||
1689 | |||
1690 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { | ||
1691 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1692 | &carl9170_band_2GHz; | ||
1693 | bands++; | ||
1694 | } | ||
1695 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { | ||
1696 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1697 | &carl9170_band_5GHz; | ||
1698 | bands++; | ||
1699 | } | ||
1700 | |||
1701 | /* | ||
1702 | * I measured this, a bandswitch takes roughly | ||
1703 | * 135 ms and a frequency switch about 80. | ||
1704 | * | ||
1705 | * FIXME: measure these values again once EEPROM settings | ||
1706 | * are used, that will influence them! | ||
1707 | */ | ||
1708 | if (bands == 2) | ||
1709 | ar->hw->channel_change_time = 135 * 1000; | ||
1710 | else | ||
1711 | ar->hw->channel_change_time = 80 * 1000; | ||
1712 | |||
1713 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); | ||
1714 | regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); | ||
1715 | |||
1716 | /* second part of wiphy init */ | ||
1717 | SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); | ||
1718 | |||
1719 | return bands ? 0 : -EINVAL; | ||
1720 | } | ||
1721 | |||
1722 | static int carl9170_reg_notifier(struct wiphy *wiphy, | ||
1723 | struct regulatory_request *request) | ||
1724 | { | ||
1725 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
1726 | struct ar9170 *ar = hw->priv; | ||
1727 | |||
1728 | return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); | ||
1729 | } | ||
1730 | |||
1731 | int carl9170_register(struct ar9170 *ar) | ||
1732 | { | ||
1733 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
1734 | int err = 0, i; | ||
1735 | |||
1736 | if (WARN_ON(ar->mem_bitmap)) | ||
1737 | return -EINVAL; | ||
1738 | |||
1739 | ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) * | ||
1740 | sizeof(unsigned long), GFP_KERNEL); | ||
1741 | |||
1742 | if (!ar->mem_bitmap) | ||
1743 | return -ENOMEM; | ||
1744 | |||
1745 | /* try to read EEPROM, init MAC addr */ | ||
1746 | err = carl9170_read_eeprom(ar); | ||
1747 | if (err) | ||
1748 | return err; | ||
1749 | |||
1750 | err = carl9170_fw_fix_eeprom(ar); | ||
1751 | if (err) | ||
1752 | return err; | ||
1753 | |||
1754 | err = carl9170_parse_eeprom(ar); | ||
1755 | if (err) | ||
1756 | return err; | ||
1757 | |||
1758 | err = ath_regd_init(regulatory, ar->hw->wiphy, | ||
1759 | carl9170_reg_notifier); | ||
1760 | if (err) | ||
1761 | return err; | ||
1762 | |||
1763 | if (modparam_noht) { | ||
1764 | carl9170_band_2GHz.ht_cap.ht_supported = false; | ||
1765 | carl9170_band_5GHz.ht_cap.ht_supported = false; | ||
1766 | } | ||
1767 | |||
1768 | for (i = 0; i < ar->fw.vif_num; i++) { | ||
1769 | ar->vif_priv[i].id = i; | ||
1770 | ar->vif_priv[i].vif = NULL; | ||
1771 | } | ||
1772 | |||
1773 | err = ieee80211_register_hw(ar->hw); | ||
1774 | if (err) | ||
1775 | return err; | ||
1776 | |||
1777 | /* mac80211 interface is now registered */ | ||
1778 | ar->registered = true; | ||
1779 | |||
1780 | if (!ath_is_world_regd(regulatory)) | ||
1781 | regulatory_hint(ar->hw->wiphy, regulatory->alpha2); | ||
1782 | |||
1783 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
1784 | carl9170_debugfs_register(ar); | ||
1785 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
1786 | |||
1787 | err = carl9170_led_init(ar); | ||
1788 | if (err) | ||
1789 | goto err_unreg; | ||
1790 | |||
1791 | #ifdef CONFIG_CARL9170_LEDS | ||
1792 | err = carl9170_led_register(ar); | ||
1793 | if (err) | ||
1794 | goto err_unreg; | ||
1795 | #endif /* CONFIG_CAR9L170_LEDS */ | ||
1796 | |||
1797 | #ifdef CONFIG_CARL9170_WPC | ||
1798 | err = carl9170_register_wps_button(ar); | ||
1799 | if (err) | ||
1800 | goto err_unreg; | ||
1801 | #endif /* CONFIG_CARL9170_WPC */ | ||
1802 | |||
1803 | dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n", | ||
1804 | wiphy_name(ar->hw->wiphy)); | ||
1805 | |||
1806 | return 0; | ||
1807 | |||
1808 | err_unreg: | ||
1809 | carl9170_unregister(ar); | ||
1810 | return err; | ||
1811 | } | ||
1812 | |||
1813 | void carl9170_unregister(struct ar9170 *ar) | ||
1814 | { | ||
1815 | if (!ar->registered) | ||
1816 | return; | ||
1817 | |||
1818 | ar->registered = false; | ||
1819 | |||
1820 | #ifdef CONFIG_CARL9170_LEDS | ||
1821 | carl9170_led_unregister(ar); | ||
1822 | #endif /* CONFIG_CARL9170_LEDS */ | ||
1823 | |||
1824 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
1825 | carl9170_debugfs_unregister(ar); | ||
1826 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
1827 | |||
1828 | #ifdef CONFIG_CARL9170_WPC | ||
1829 | if (ar->wps.pbc) { | ||
1830 | input_unregister_device(ar->wps.pbc); | ||
1831 | ar->wps.pbc = NULL; | ||
1832 | } | ||
1833 | #endif /* CONFIG_CARL9170_WPC */ | ||
1834 | |||
1835 | carl9170_cancel_worker(ar); | ||
1836 | cancel_work_sync(&ar->restart_work); | ||
1837 | |||
1838 | ieee80211_unregister_hw(ar->hw); | ||
1839 | } | ||
1840 | |||
1841 | void carl9170_free(struct ar9170 *ar) | ||
1842 | { | ||
1843 | WARN_ON(ar->registered); | ||
1844 | WARN_ON(IS_INITIALIZED(ar)); | ||
1845 | |||
1846 | kfree_skb(ar->rx_failover); | ||
1847 | ar->rx_failover = NULL; | ||
1848 | |||
1849 | kfree(ar->mem_bitmap); | ||
1850 | ar->mem_bitmap = NULL; | ||
1851 | |||
1852 | mutex_destroy(&ar->mutex); | ||
1853 | |||
1854 | ieee80211_free_hw(ar->hw); | ||
1855 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c new file mode 100644 index 000000000000..89deca37a988 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/phy.c | |||
@@ -0,0 +1,1810 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * PHY and RF code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <linux/bitrev.h> | ||
40 | #include "carl9170.h" | ||
41 | #include "cmd.h" | ||
42 | #include "phy.h" | ||
43 | |||
44 | static int carl9170_init_power_cal(struct ar9170 *ar) | ||
45 | { | ||
46 | carl9170_regwrite_begin(ar); | ||
47 | |||
48 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE_MAX, 0x7f); | ||
49 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE1, 0x3f3f3f3f); | ||
50 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE2, 0x3f3f3f3f); | ||
51 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE3, 0x3f3f3f3f); | ||
52 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE4, 0x3f3f3f3f); | ||
53 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE5, 0x3f3f3f3f); | ||
54 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE6, 0x3f3f3f3f); | ||
55 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE7, 0x3f3f3f3f); | ||
56 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE8, 0x3f3f3f3f); | ||
57 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE9, 0x3f3f3f3f); | ||
58 | |||
59 | carl9170_regwrite_finish(); | ||
60 | return carl9170_regwrite_result(); | ||
61 | } | ||
62 | |||
63 | struct carl9170_phy_init { | ||
64 | u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; | ||
65 | }; | ||
66 | |||
67 | static struct carl9170_phy_init ar5416_phy_init[] = { | ||
68 | { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
69 | { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, | ||
70 | { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
71 | { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, | ||
72 | { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, | ||
73 | { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, | ||
74 | { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, | ||
75 | { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
76 | { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, | ||
77 | { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
78 | { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, | ||
79 | { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
80 | { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
81 | { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
82 | { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
83 | { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, | ||
84 | { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, | ||
85 | { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, | ||
86 | { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, | ||
87 | { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, | ||
88 | { 0x1c5850, 0x6c48b4e4, 0x6d48b4e4, 0x6d48b0e4, 0x6c48b0e4, }, | ||
89 | { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, | ||
90 | { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, | ||
91 | { 0x1c585c, 0x31395c5e, 0x3139605e, 0x3139605e, 0x31395c5e, }, | ||
92 | { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, | ||
93 | { 0x1c5864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, | ||
94 | { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, | ||
95 | { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, | ||
96 | { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
97 | { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
98 | { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
99 | { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
100 | { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, | ||
101 | { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, | ||
102 | { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, | ||
103 | { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, | ||
104 | { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, | ||
105 | { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
106 | { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
107 | { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
108 | { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
109 | { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, | ||
110 | { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, | ||
111 | { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, | ||
112 | { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, | ||
113 | { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, | ||
114 | { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, | ||
115 | { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
116 | { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, | ||
117 | { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, | ||
118 | { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
119 | { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
120 | { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
121 | { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
122 | { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
123 | { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
124 | { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
125 | { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
126 | { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
127 | { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
128 | { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
129 | { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
130 | { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
131 | { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, | ||
132 | { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, | ||
133 | { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, | ||
134 | { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, | ||
135 | { 0x1c59bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, | ||
136 | { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, | ||
137 | { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, | ||
138 | { 0x1c59c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, }, | ||
139 | { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, | ||
140 | { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, | ||
141 | { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
142 | { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
143 | { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
144 | { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, | ||
145 | { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, | ||
146 | { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, | ||
147 | { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, | ||
148 | { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
149 | { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, | ||
150 | { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
151 | { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, | ||
152 | { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, | ||
153 | { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, | ||
154 | { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, | ||
155 | { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, | ||
156 | { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, | ||
157 | { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, | ||
158 | { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, | ||
159 | { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, | ||
160 | { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
161 | { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, | ||
162 | { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, | ||
163 | { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, | ||
164 | { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, | ||
165 | { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, | ||
166 | { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, | ||
167 | { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, | ||
168 | { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, | ||
169 | { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, | ||
170 | { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, | ||
171 | { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, | ||
172 | { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, | ||
173 | { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, | ||
174 | { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, | ||
175 | { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, | ||
176 | { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, | ||
177 | { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, | ||
178 | { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, | ||
179 | { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, | ||
180 | { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, | ||
181 | { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, | ||
182 | { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, | ||
183 | { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, | ||
184 | { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, | ||
185 | { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, | ||
186 | { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, | ||
187 | { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, | ||
188 | { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, | ||
189 | { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, | ||
190 | { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
191 | { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
192 | { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
193 | { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
194 | { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
195 | { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
196 | { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
197 | { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
198 | { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
199 | { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
200 | { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
201 | { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
202 | { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
203 | { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
204 | { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
205 | { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
206 | { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
207 | { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
208 | { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
209 | { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
210 | { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
211 | { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
212 | { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
213 | { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
214 | { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
215 | { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
216 | { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, | ||
217 | { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, | ||
218 | { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
219 | { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, | ||
220 | { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, | ||
221 | { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, | ||
222 | { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, | ||
223 | { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, | ||
224 | { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, | ||
225 | { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, | ||
226 | { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
227 | { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, | ||
228 | { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, | ||
229 | { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, | ||
230 | { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, | ||
231 | { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, | ||
232 | { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, | ||
233 | { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, | ||
234 | { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
235 | { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, | ||
236 | { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, | ||
237 | { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, | ||
238 | { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, | ||
239 | { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, | ||
240 | { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, | ||
241 | { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, | ||
242 | { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, | ||
243 | { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, | ||
244 | { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
245 | { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, | ||
246 | { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, | ||
247 | { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, | ||
248 | { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, | ||
249 | { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, | ||
250 | { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, | ||
251 | { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, | ||
252 | { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, | ||
253 | { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, | ||
254 | { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, | ||
255 | { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
256 | { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
257 | { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
258 | { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
259 | { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
260 | { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
261 | { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
262 | { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
263 | { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
264 | { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
265 | { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
266 | { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
267 | { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
268 | { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
269 | { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
270 | { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
271 | { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
272 | { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
273 | { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
274 | { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
275 | { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
276 | { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
277 | { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
278 | { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
279 | { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
280 | { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
281 | { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
282 | { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
283 | { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
284 | { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
285 | { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
286 | { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
287 | { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
288 | { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
289 | { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
290 | { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
291 | { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
292 | { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
293 | { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
294 | { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
295 | { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
296 | { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, | ||
297 | { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, | ||
298 | { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, | ||
299 | { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
300 | { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, | ||
301 | { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, | ||
302 | { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, | ||
303 | { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, | ||
304 | { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, | ||
305 | { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, | ||
306 | { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, | ||
307 | { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
308 | { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, | ||
309 | { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
310 | { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
311 | { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, | ||
312 | { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, | ||
313 | { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, | ||
314 | { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, | ||
315 | { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
316 | { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
317 | { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
318 | { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, | ||
319 | { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, | ||
320 | { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, | ||
321 | { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, | ||
322 | { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
323 | { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
324 | { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, | ||
325 | { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
326 | { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, | ||
327 | { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, | ||
328 | { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, | ||
329 | { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, | ||
330 | { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, | ||
331 | { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, | ||
332 | { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, | ||
333 | { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, | ||
334 | { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, | ||
335 | { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, | ||
336 | { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, | ||
337 | { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, | ||
338 | { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
339 | { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
340 | { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
341 | { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
342 | { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
343 | { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
344 | { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
345 | { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
346 | { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
347 | { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
348 | { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, | ||
349 | { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, | ||
350 | { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, | ||
351 | { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
352 | { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
353 | { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
354 | { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, | ||
355 | { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
356 | { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
357 | { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
358 | { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
359 | { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
360 | { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
361 | { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
362 | { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
363 | { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
364 | { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
365 | { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
366 | { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
367 | { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
368 | { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
369 | { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
370 | { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
371 | { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
372 | { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, | ||
373 | { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
374 | { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
375 | { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
376 | { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
377 | { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
378 | { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
379 | { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
380 | { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
381 | { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
382 | { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
383 | /* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ | ||
384 | { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, | ||
385 | { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, | ||
386 | { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, | ||
387 | { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, | ||
388 | { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, | ||
389 | { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, | ||
390 | { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, | ||
391 | { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, | ||
392 | { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, | ||
393 | { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, | ||
394 | { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, | ||
395 | { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, | ||
396 | { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, | ||
397 | { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, | ||
398 | { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, | ||
399 | { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } | ||
400 | }; | ||
401 | |||
402 | /* | ||
403 | * look up a certain register in ar5416_phy_init[] and return the init. value | ||
404 | * for the band and bandwidth given. Return 0 if register address not found. | ||
405 | */ | ||
406 | static u32 carl9170_def_val(u32 reg, bool is_2ghz, bool is_40mhz) | ||
407 | { | ||
408 | unsigned int i; | ||
409 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
410 | if (ar5416_phy_init[i].reg != reg) | ||
411 | continue; | ||
412 | |||
413 | if (is_2ghz) { | ||
414 | if (is_40mhz) | ||
415 | return ar5416_phy_init[i]._2ghz_40; | ||
416 | else | ||
417 | return ar5416_phy_init[i]._2ghz_20; | ||
418 | } else { | ||
419 | if (is_40mhz) | ||
420 | return ar5416_phy_init[i]._5ghz_40; | ||
421 | else | ||
422 | return ar5416_phy_init[i]._5ghz_20; | ||
423 | } | ||
424 | } | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * initialize some phy regs from eeprom values in modal_header[] | ||
430 | * acc. to band and bandwith | ||
431 | */ | ||
432 | static int carl9170_init_phy_from_eeprom(struct ar9170 *ar, | ||
433 | bool is_2ghz, bool is_40mhz) | ||
434 | { | ||
435 | static const u8 xpd2pd[16] = { | ||
436 | 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, | ||
437 | 0x2, 0x3, 0x7, 0x2, 0xb, 0x2, 0x2, 0x2 | ||
438 | }; | ||
439 | /* pointer to the modal_header acc. to band */ | ||
440 | struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; | ||
441 | u32 val; | ||
442 | |||
443 | carl9170_regwrite_begin(ar); | ||
444 | |||
445 | /* ant common control (index 0) */ | ||
446 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_COM, | ||
447 | le32_to_cpu(m->antCtrlCommon)); | ||
448 | |||
449 | /* ant control chain 0 (index 1) */ | ||
450 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_0, | ||
451 | le32_to_cpu(m->antCtrlChain[0])); | ||
452 | |||
453 | /* ant control chain 2 (index 2) */ | ||
454 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_2, | ||
455 | le32_to_cpu(m->antCtrlChain[1])); | ||
456 | |||
457 | /* SwSettle (index 3) */ | ||
458 | if (!is_40mhz) { | ||
459 | val = carl9170_def_val(AR9170_PHY_REG_SETTLING, | ||
460 | is_2ghz, is_40mhz); | ||
461 | SET_VAL(AR9170_PHY_SETTLING_SWITCH, val, m->switchSettling); | ||
462 | carl9170_regwrite(AR9170_PHY_REG_SETTLING, val); | ||
463 | } | ||
464 | |||
465 | /* adcDesired, pdaDesired (index 4) */ | ||
466 | val = carl9170_def_val(AR9170_PHY_REG_DESIRED_SZ, is_2ghz, is_40mhz); | ||
467 | SET_VAL(AR9170_PHY_DESIRED_SZ_PGA, val, m->pgaDesiredSize); | ||
468 | SET_VAL(AR9170_PHY_DESIRED_SZ_ADC, val, m->adcDesiredSize); | ||
469 | carl9170_regwrite(AR9170_PHY_REG_DESIRED_SZ, val); | ||
470 | |||
471 | /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ | ||
472 | val = carl9170_def_val(AR9170_PHY_REG_RF_CTL4, is_2ghz, is_40mhz); | ||
473 | SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF, val, m->txEndToXpaOff); | ||
474 | SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF, val, m->txEndToXpaOff); | ||
475 | SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAB_ON, val, m->txFrameToXpaOn); | ||
476 | SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAA_ON, val, m->txFrameToXpaOn); | ||
477 | carl9170_regwrite(AR9170_PHY_REG_RF_CTL4, val); | ||
478 | |||
479 | /* TxEndToRxOn (index 6) */ | ||
480 | val = carl9170_def_val(AR9170_PHY_REG_RF_CTL3, is_2ghz, is_40mhz); | ||
481 | SET_VAL(AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON, val, m->txEndToRxOn); | ||
482 | carl9170_regwrite(AR9170_PHY_REG_RF_CTL3, val); | ||
483 | |||
484 | /* thresh62 (index 7) */ | ||
485 | val = carl9170_def_val(0x1c8864, is_2ghz, is_40mhz); | ||
486 | val = (val & ~0x7f000) | (m->thresh62 << 12); | ||
487 | carl9170_regwrite(0x1c8864, val); | ||
488 | |||
489 | /* tx/rx attenuation chain 0 (index 8) */ | ||
490 | val = carl9170_def_val(AR9170_PHY_REG_RXGAIN, is_2ghz, is_40mhz); | ||
491 | SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[0]); | ||
492 | carl9170_regwrite(AR9170_PHY_REG_RXGAIN, val); | ||
493 | |||
494 | /* tx/rx attenuation chain 2 (index 9) */ | ||
495 | val = carl9170_def_val(AR9170_PHY_REG_RXGAIN_CHAIN_2, | ||
496 | is_2ghz, is_40mhz); | ||
497 | SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[1]); | ||
498 | carl9170_regwrite(AR9170_PHY_REG_RXGAIN_CHAIN_2, val); | ||
499 | |||
500 | /* tx/rx margin chain 0 (index 10) */ | ||
501 | val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ, is_2ghz, is_40mhz); | ||
502 | SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[0]); | ||
503 | /* bsw margin chain 0 for 5GHz only */ | ||
504 | if (!is_2ghz) | ||
505 | SET_VAL(AR9170_PHY_GAIN_2GHZ_BSW_MARGIN, val, m->bswMargin[0]); | ||
506 | carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ, val); | ||
507 | |||
508 | /* tx/rx margin chain 2 (index 11) */ | ||
509 | val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, | ||
510 | is_2ghz, is_40mhz); | ||
511 | SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[1]); | ||
512 | carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, val); | ||
513 | |||
514 | /* iqCall, iqCallq chain 0 (index 12) */ | ||
515 | val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(0), | ||
516 | is_2ghz, is_40mhz); | ||
517 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[0]); | ||
518 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[0]); | ||
519 | carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(0), val); | ||
520 | |||
521 | /* iqCall, iqCallq chain 2 (index 13) */ | ||
522 | val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(2), | ||
523 | is_2ghz, is_40mhz); | ||
524 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[1]); | ||
525 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[1]); | ||
526 | carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(2), val); | ||
527 | |||
528 | /* xpd gain mask (index 14) */ | ||
529 | val = carl9170_def_val(AR9170_PHY_REG_TPCRG1, is_2ghz, is_40mhz); | ||
530 | SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_1, val, | ||
531 | xpd2pd[m->xpdGain & 0xf] & 3); | ||
532 | SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_2, val, | ||
533 | xpd2pd[m->xpdGain & 0xf] >> 2); | ||
534 | carl9170_regwrite(AR9170_PHY_REG_TPCRG1, val); | ||
535 | |||
536 | carl9170_regwrite(AR9170_PHY_REG_RX_CHAINMASK, ar->eeprom.rx_mask); | ||
537 | carl9170_regwrite(AR9170_PHY_REG_CAL_CHAINMASK, ar->eeprom.rx_mask); | ||
538 | |||
539 | carl9170_regwrite_finish(); | ||
540 | return carl9170_regwrite_result(); | ||
541 | } | ||
542 | |||
543 | static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) | ||
544 | { | ||
545 | int i, err; | ||
546 | u32 val; | ||
547 | bool is_2ghz = band == IEEE80211_BAND_2GHZ; | ||
548 | bool is_40mhz = conf_is_ht40(&ar->hw->conf); | ||
549 | |||
550 | carl9170_regwrite_begin(ar); | ||
551 | |||
552 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
553 | if (is_40mhz) { | ||
554 | if (is_2ghz) | ||
555 | val = ar5416_phy_init[i]._2ghz_40; | ||
556 | else | ||
557 | val = ar5416_phy_init[i]._5ghz_40; | ||
558 | } else { | ||
559 | if (is_2ghz) | ||
560 | val = ar5416_phy_init[i]._2ghz_20; | ||
561 | else | ||
562 | val = ar5416_phy_init[i]._5ghz_20; | ||
563 | } | ||
564 | |||
565 | carl9170_regwrite(ar5416_phy_init[i].reg, val); | ||
566 | } | ||
567 | |||
568 | carl9170_regwrite_finish(); | ||
569 | err = carl9170_regwrite_result(); | ||
570 | if (err) | ||
571 | return err; | ||
572 | |||
573 | err = carl9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); | ||
574 | if (err) | ||
575 | return err; | ||
576 | |||
577 | err = carl9170_init_power_cal(ar); | ||
578 | if (err) | ||
579 | return err; | ||
580 | |||
581 | /* XXX: remove magic! */ | ||
582 | if (is_2ghz) | ||
583 | err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163); | ||
584 | else | ||
585 | err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143); | ||
586 | |||
587 | return err; | ||
588 | } | ||
589 | |||
590 | struct carl9170_rf_initvals { | ||
591 | u32 reg, _5ghz, _2ghz; | ||
592 | }; | ||
593 | |||
594 | static struct carl9170_rf_initvals carl9170_rf_initval[] = { | ||
595 | /* bank 0 */ | ||
596 | { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, | ||
597 | { 0x1c58e0, 0x02008020, 0x02008020}, | ||
598 | /* bank 1 */ | ||
599 | { 0x1c58b0, 0x02108421, 0x02108421}, | ||
600 | { 0x1c58ec, 0x00000008, 0x00000008}, | ||
601 | /* bank 2 */ | ||
602 | { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, | ||
603 | { 0x1c58e0, 0x00000420, 0x00000420}, | ||
604 | /* bank 3 */ | ||
605 | { 0x1c58f0, 0x01400018, 0x01c00018}, | ||
606 | /* bank 4 */ | ||
607 | { 0x1c58b0, 0x000001a1, 0x000001a1}, | ||
608 | { 0x1c58e8, 0x00000001, 0x00000001}, | ||
609 | /* bank 5 */ | ||
610 | { 0x1c58b0, 0x00000013, 0x00000013}, | ||
611 | { 0x1c58e4, 0x00000002, 0x00000002}, | ||
612 | /* bank 6 */ | ||
613 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
614 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
615 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
616 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
617 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
618 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
619 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
620 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
621 | { 0x1c58b0, 0x00004800, 0x00004800}, | ||
622 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
623 | { 0x1c58b0, 0x00006000, 0x00006000}, | ||
624 | { 0x1c58b0, 0x00001000, 0x00001000}, | ||
625 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
626 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
627 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
628 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
629 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
630 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
631 | { 0x1c58b0, 0x00087c00, 0x00087c00}, | ||
632 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
633 | { 0x1c58b0, 0x00005400, 0x00005400}, | ||
634 | { 0x1c58b0, 0x00000c00, 0x00000c00}, | ||
635 | { 0x1c58b0, 0x00001800, 0x00001800}, | ||
636 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
637 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
638 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
639 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
640 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
641 | { 0x1c58b0, 0x00003c00, 0x00003c00}, | ||
642 | { 0x1c58b0, 0x00003800, 0x00003800}, | ||
643 | { 0x1c58b0, 0x00001c00, 0x00001c00}, | ||
644 | { 0x1c58b0, 0x00000800, 0x00000800}, | ||
645 | { 0x1c58b0, 0x00000408, 0x00000408}, | ||
646 | { 0x1c58b0, 0x00004c15, 0x00004c15}, | ||
647 | { 0x1c58b0, 0x00004188, 0x00004188}, | ||
648 | { 0x1c58b0, 0x0000201e, 0x0000201e}, | ||
649 | { 0x1c58b0, 0x00010408, 0x00010408}, | ||
650 | { 0x1c58b0, 0x00000801, 0x00000801}, | ||
651 | { 0x1c58b0, 0x00000c08, 0x00000c08}, | ||
652 | { 0x1c58b0, 0x0000181e, 0x0000181e}, | ||
653 | { 0x1c58b0, 0x00001016, 0x00001016}, | ||
654 | { 0x1c58b0, 0x00002800, 0x00002800}, | ||
655 | { 0x1c58b0, 0x00004010, 0x00004010}, | ||
656 | { 0x1c58b0, 0x0000081c, 0x0000081c}, | ||
657 | { 0x1c58b0, 0x00000115, 0x00000115}, | ||
658 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
659 | { 0x1c58b0, 0x00000066, 0x00000066}, | ||
660 | { 0x1c58b0, 0x0000001c, 0x0000001c}, | ||
661 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
662 | { 0x1c58b0, 0x00000004, 0x00000004}, | ||
663 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
664 | { 0x1c58b0, 0x0000001f, 0x0000001f}, | ||
665 | { 0x1c58e0, 0x00000000, 0x00000400}, | ||
666 | /* bank 7 */ | ||
667 | { 0x1c58b0, 0x000000a0, 0x000000a0}, | ||
668 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
669 | { 0x1c58b0, 0x00000040, 0x00000040}, | ||
670 | { 0x1c58f0, 0x0000001c, 0x0000001c}, | ||
671 | }; | ||
672 | |||
673 | static int carl9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) | ||
674 | { | ||
675 | int err, i; | ||
676 | |||
677 | carl9170_regwrite_begin(ar); | ||
678 | |||
679 | for (i = 0; i < ARRAY_SIZE(carl9170_rf_initval); i++) | ||
680 | carl9170_regwrite(carl9170_rf_initval[i].reg, | ||
681 | band5ghz ? carl9170_rf_initval[i]._5ghz | ||
682 | : carl9170_rf_initval[i]._2ghz); | ||
683 | |||
684 | carl9170_regwrite_finish(); | ||
685 | err = carl9170_regwrite_result(); | ||
686 | if (err) | ||
687 | wiphy_err(ar->hw->wiphy, "rf init failed\n"); | ||
688 | |||
689 | return err; | ||
690 | } | ||
691 | |||
692 | struct carl9170_phy_freq_params { | ||
693 | u8 coeff_exp; | ||
694 | u16 coeff_man; | ||
695 | u8 coeff_exp_shgi; | ||
696 | u16 coeff_man_shgi; | ||
697 | }; | ||
698 | |||
699 | enum carl9170_bw { | ||
700 | CARL9170_BW_20, | ||
701 | CARL9170_BW_40_BELOW, | ||
702 | CARL9170_BW_40_ABOVE, | ||
703 | |||
704 | __CARL9170_NUM_BW, | ||
705 | }; | ||
706 | |||
707 | struct carl9170_phy_freq_entry { | ||
708 | u16 freq; | ||
709 | struct carl9170_phy_freq_params params[__CARL9170_NUM_BW]; | ||
710 | }; | ||
711 | |||
712 | /* NB: must be in sync with channel tables in main! */ | ||
713 | static const struct carl9170_phy_freq_entry carl9170_phy_freq_params[] = { | ||
714 | /* | ||
715 | * freq, | ||
716 | * 20MHz, | ||
717 | * 40MHz (below), | ||
718 | * 40Mhz (above), | ||
719 | */ | ||
720 | { 2412, { | ||
721 | { 3, 21737, 3, 19563, }, | ||
722 | { 3, 21827, 3, 19644, }, | ||
723 | { 3, 21647, 3, 19482, }, | ||
724 | } }, | ||
725 | { 2417, { | ||
726 | { 3, 21692, 3, 19523, }, | ||
727 | { 3, 21782, 3, 19604, }, | ||
728 | { 3, 21602, 3, 19442, }, | ||
729 | } }, | ||
730 | { 2422, { | ||
731 | { 3, 21647, 3, 19482, }, | ||
732 | { 3, 21737, 3, 19563, }, | ||
733 | { 3, 21558, 3, 19402, }, | ||
734 | } }, | ||
735 | { 2427, { | ||
736 | { 3, 21602, 3, 19442, }, | ||
737 | { 3, 21692, 3, 19523, }, | ||
738 | { 3, 21514, 3, 19362, }, | ||
739 | } }, | ||
740 | { 2432, { | ||
741 | { 3, 21558, 3, 19402, }, | ||
742 | { 3, 21647, 3, 19482, }, | ||
743 | { 3, 21470, 3, 19323, }, | ||
744 | } }, | ||
745 | { 2437, { | ||
746 | { 3, 21514, 3, 19362, }, | ||
747 | { 3, 21602, 3, 19442, }, | ||
748 | { 3, 21426, 3, 19283, }, | ||
749 | } }, | ||
750 | { 2442, { | ||
751 | { 3, 21470, 3, 19323, }, | ||
752 | { 3, 21558, 3, 19402, }, | ||
753 | { 3, 21382, 3, 19244, }, | ||
754 | } }, | ||
755 | { 2447, { | ||
756 | { 3, 21426, 3, 19283, }, | ||
757 | { 3, 21514, 3, 19362, }, | ||
758 | { 3, 21339, 3, 19205, }, | ||
759 | } }, | ||
760 | { 2452, { | ||
761 | { 3, 21382, 3, 19244, }, | ||
762 | { 3, 21470, 3, 19323, }, | ||
763 | { 3, 21295, 3, 19166, }, | ||
764 | } }, | ||
765 | { 2457, { | ||
766 | { 3, 21339, 3, 19205, }, | ||
767 | { 3, 21426, 3, 19283, }, | ||
768 | { 3, 21252, 3, 19127, }, | ||
769 | } }, | ||
770 | { 2462, { | ||
771 | { 3, 21295, 3, 19166, }, | ||
772 | { 3, 21382, 3, 19244, }, | ||
773 | { 3, 21209, 3, 19088, }, | ||
774 | } }, | ||
775 | { 2467, { | ||
776 | { 3, 21252, 3, 19127, }, | ||
777 | { 3, 21339, 3, 19205, }, | ||
778 | { 3, 21166, 3, 19050, }, | ||
779 | } }, | ||
780 | { 2472, { | ||
781 | { 3, 21209, 3, 19088, }, | ||
782 | { 3, 21295, 3, 19166, }, | ||
783 | { 3, 21124, 3, 19011, }, | ||
784 | } }, | ||
785 | { 2484, { | ||
786 | { 3, 21107, 3, 18996, }, | ||
787 | { 3, 21192, 3, 19073, }, | ||
788 | { 3, 21022, 3, 18920, }, | ||
789 | } }, | ||
790 | { 4920, { | ||
791 | { 4, 21313, 4, 19181, }, | ||
792 | { 4, 21356, 4, 19220, }, | ||
793 | { 4, 21269, 4, 19142, }, | ||
794 | } }, | ||
795 | { 4940, { | ||
796 | { 4, 21226, 4, 19104, }, | ||
797 | { 4, 21269, 4, 19142, }, | ||
798 | { 4, 21183, 4, 19065, }, | ||
799 | } }, | ||
800 | { 4960, { | ||
801 | { 4, 21141, 4, 19027, }, | ||
802 | { 4, 21183, 4, 19065, }, | ||
803 | { 4, 21098, 4, 18988, }, | ||
804 | } }, | ||
805 | { 4980, { | ||
806 | { 4, 21056, 4, 18950, }, | ||
807 | { 4, 21098, 4, 18988, }, | ||
808 | { 4, 21014, 4, 18912, }, | ||
809 | } }, | ||
810 | { 5040, { | ||
811 | { 4, 20805, 4, 18725, }, | ||
812 | { 4, 20846, 4, 18762, }, | ||
813 | { 4, 20764, 4, 18687, }, | ||
814 | } }, | ||
815 | { 5060, { | ||
816 | { 4, 20723, 4, 18651, }, | ||
817 | { 4, 20764, 4, 18687, }, | ||
818 | { 4, 20682, 4, 18614, }, | ||
819 | } }, | ||
820 | { 5080, { | ||
821 | { 4, 20641, 4, 18577, }, | ||
822 | { 4, 20682, 4, 18614, }, | ||
823 | { 4, 20601, 4, 18541, }, | ||
824 | } }, | ||
825 | { 5180, { | ||
826 | { 4, 20243, 4, 18219, }, | ||
827 | { 4, 20282, 4, 18254, }, | ||
828 | { 4, 20204, 4, 18183, }, | ||
829 | } }, | ||
830 | { 5200, { | ||
831 | { 4, 20165, 4, 18148, }, | ||
832 | { 4, 20204, 4, 18183, }, | ||
833 | { 4, 20126, 4, 18114, }, | ||
834 | } }, | ||
835 | { 5220, { | ||
836 | { 4, 20088, 4, 18079, }, | ||
837 | { 4, 20126, 4, 18114, }, | ||
838 | { 4, 20049, 4, 18044, }, | ||
839 | } }, | ||
840 | { 5240, { | ||
841 | { 4, 20011, 4, 18010, }, | ||
842 | { 4, 20049, 4, 18044, }, | ||
843 | { 4, 19973, 4, 17976, }, | ||
844 | } }, | ||
845 | { 5260, { | ||
846 | { 4, 19935, 4, 17941, }, | ||
847 | { 4, 19973, 4, 17976, }, | ||
848 | { 4, 19897, 4, 17907, }, | ||
849 | } }, | ||
850 | { 5280, { | ||
851 | { 4, 19859, 4, 17873, }, | ||
852 | { 4, 19897, 4, 17907, }, | ||
853 | { 4, 19822, 4, 17840, }, | ||
854 | } }, | ||
855 | { 5300, { | ||
856 | { 4, 19784, 4, 17806, }, | ||
857 | { 4, 19822, 4, 17840, }, | ||
858 | { 4, 19747, 4, 17772, }, | ||
859 | } }, | ||
860 | { 5320, { | ||
861 | { 4, 19710, 4, 17739, }, | ||
862 | { 4, 19747, 4, 17772, }, | ||
863 | { 4, 19673, 4, 17706, }, | ||
864 | } }, | ||
865 | { 5500, { | ||
866 | { 4, 19065, 4, 17159, }, | ||
867 | { 4, 19100, 4, 17190, }, | ||
868 | { 4, 19030, 4, 17127, }, | ||
869 | } }, | ||
870 | { 5520, { | ||
871 | { 4, 18996, 4, 17096, }, | ||
872 | { 4, 19030, 4, 17127, }, | ||
873 | { 4, 18962, 4, 17065, }, | ||
874 | } }, | ||
875 | { 5540, { | ||
876 | { 4, 18927, 4, 17035, }, | ||
877 | { 4, 18962, 4, 17065, }, | ||
878 | { 4, 18893, 4, 17004, }, | ||
879 | } }, | ||
880 | { 5560, { | ||
881 | { 4, 18859, 4, 16973, }, | ||
882 | { 4, 18893, 4, 17004, }, | ||
883 | { 4, 18825, 4, 16943, }, | ||
884 | } }, | ||
885 | { 5580, { | ||
886 | { 4, 18792, 4, 16913, }, | ||
887 | { 4, 18825, 4, 16943, }, | ||
888 | { 4, 18758, 4, 16882, }, | ||
889 | } }, | ||
890 | { 5600, { | ||
891 | { 4, 18725, 4, 16852, }, | ||
892 | { 4, 18758, 4, 16882, }, | ||
893 | { 4, 18691, 4, 16822, }, | ||
894 | } }, | ||
895 | { 5620, { | ||
896 | { 4, 18658, 4, 16792, }, | ||
897 | { 4, 18691, 4, 16822, }, | ||
898 | { 4, 18625, 4, 16762, }, | ||
899 | } }, | ||
900 | { 5640, { | ||
901 | { 4, 18592, 4, 16733, }, | ||
902 | { 4, 18625, 4, 16762, }, | ||
903 | { 4, 18559, 4, 16703, }, | ||
904 | } }, | ||
905 | { 5660, { | ||
906 | { 4, 18526, 4, 16673, }, | ||
907 | { 4, 18559, 4, 16703, }, | ||
908 | { 4, 18493, 4, 16644, }, | ||
909 | } }, | ||
910 | { 5680, { | ||
911 | { 4, 18461, 4, 16615, }, | ||
912 | { 4, 18493, 4, 16644, }, | ||
913 | { 4, 18428, 4, 16586, }, | ||
914 | } }, | ||
915 | { 5700, { | ||
916 | { 4, 18396, 4, 16556, }, | ||
917 | { 4, 18428, 4, 16586, }, | ||
918 | { 4, 18364, 4, 16527, }, | ||
919 | } }, | ||
920 | { 5745, { | ||
921 | { 4, 18252, 4, 16427, }, | ||
922 | { 4, 18284, 4, 16455, }, | ||
923 | { 4, 18220, 4, 16398, }, | ||
924 | } }, | ||
925 | { 5765, { | ||
926 | { 4, 18189, 5, 32740, }, | ||
927 | { 4, 18220, 4, 16398, }, | ||
928 | { 4, 18157, 5, 32683, }, | ||
929 | } }, | ||
930 | { 5785, { | ||
931 | { 4, 18126, 5, 32626, }, | ||
932 | { 4, 18157, 5, 32683, }, | ||
933 | { 4, 18094, 5, 32570, }, | ||
934 | } }, | ||
935 | { 5805, { | ||
936 | { 4, 18063, 5, 32514, }, | ||
937 | { 4, 18094, 5, 32570, }, | ||
938 | { 4, 18032, 5, 32458, }, | ||
939 | } }, | ||
940 | { 5825, { | ||
941 | { 4, 18001, 5, 32402, }, | ||
942 | { 4, 18032, 5, 32458, }, | ||
943 | { 4, 17970, 5, 32347, }, | ||
944 | } }, | ||
945 | { 5170, { | ||
946 | { 4, 20282, 4, 18254, }, | ||
947 | { 4, 20321, 4, 18289, }, | ||
948 | { 4, 20243, 4, 18219, }, | ||
949 | } }, | ||
950 | { 5190, { | ||
951 | { 4, 20204, 4, 18183, }, | ||
952 | { 4, 20243, 4, 18219, }, | ||
953 | { 4, 20165, 4, 18148, }, | ||
954 | } }, | ||
955 | { 5210, { | ||
956 | { 4, 20126, 4, 18114, }, | ||
957 | { 4, 20165, 4, 18148, }, | ||
958 | { 4, 20088, 4, 18079, }, | ||
959 | } }, | ||
960 | { 5230, { | ||
961 | { 4, 20049, 4, 18044, }, | ||
962 | { 4, 20088, 4, 18079, }, | ||
963 | { 4, 20011, 4, 18010, }, | ||
964 | } }, | ||
965 | }; | ||
966 | |||
967 | static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, | ||
968 | u32 freq, enum carl9170_bw bw) | ||
969 | { | ||
970 | int err; | ||
971 | u32 d0, d1, td0, td1, fd0, fd1; | ||
972 | u8 chansel; | ||
973 | u8 refsel0 = 1, refsel1 = 0; | ||
974 | u8 lf_synth = 0; | ||
975 | |||
976 | switch (bw) { | ||
977 | case CARL9170_BW_40_ABOVE: | ||
978 | freq += 10; | ||
979 | break; | ||
980 | case CARL9170_BW_40_BELOW: | ||
981 | freq -= 10; | ||
982 | break; | ||
983 | case CARL9170_BW_20: | ||
984 | break; | ||
985 | default: | ||
986 | BUG(); | ||
987 | return -ENOSYS; | ||
988 | } | ||
989 | |||
990 | if (band5ghz) { | ||
991 | if (freq % 10) { | ||
992 | chansel = (freq - 4800) / 5; | ||
993 | } else { | ||
994 | chansel = ((freq - 4800) / 10) * 2; | ||
995 | refsel0 = 0; | ||
996 | refsel1 = 1; | ||
997 | } | ||
998 | chansel = byte_rev_table[chansel]; | ||
999 | } else { | ||
1000 | if (freq == 2484) { | ||
1001 | chansel = 10 + (freq - 2274) / 5; | ||
1002 | lf_synth = 1; | ||
1003 | } else | ||
1004 | chansel = 16 + (freq - 2272) / 5; | ||
1005 | chansel *= 4; | ||
1006 | chansel = byte_rev_table[chansel]; | ||
1007 | } | ||
1008 | |||
1009 | d1 = chansel; | ||
1010 | d0 = 0x21 | | ||
1011 | refsel0 << 3 | | ||
1012 | refsel1 << 2 | | ||
1013 | lf_synth << 1; | ||
1014 | td0 = d0 & 0x1f; | ||
1015 | td1 = d1 & 0x1f; | ||
1016 | fd0 = td1 << 5 | td0; | ||
1017 | |||
1018 | td0 = (d0 >> 5) & 0x7; | ||
1019 | td1 = (d1 >> 5) & 0x7; | ||
1020 | fd1 = td1 << 5 | td0; | ||
1021 | |||
1022 | carl9170_regwrite_begin(ar); | ||
1023 | |||
1024 | carl9170_regwrite(0x1c58b0, fd0); | ||
1025 | carl9170_regwrite(0x1c58e8, fd1); | ||
1026 | |||
1027 | carl9170_regwrite_finish(); | ||
1028 | err = carl9170_regwrite_result(); | ||
1029 | if (err) | ||
1030 | return err; | ||
1031 | |||
1032 | msleep(20); | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static const struct carl9170_phy_freq_params * | ||
1038 | carl9170_get_hw_dyn_params(struct ieee80211_channel *channel, | ||
1039 | enum carl9170_bw bw) | ||
1040 | { | ||
1041 | unsigned int chanidx = 0; | ||
1042 | u16 freq = 2412; | ||
1043 | |||
1044 | if (channel) { | ||
1045 | chanidx = channel->hw_value; | ||
1046 | freq = channel->center_freq; | ||
1047 | } | ||
1048 | |||
1049 | BUG_ON(chanidx >= ARRAY_SIZE(carl9170_phy_freq_params)); | ||
1050 | |||
1051 | BUILD_BUG_ON(__CARL9170_NUM_BW != 3); | ||
1052 | |||
1053 | WARN_ON(carl9170_phy_freq_params[chanidx].freq != freq); | ||
1054 | |||
1055 | return &carl9170_phy_freq_params[chanidx].params[bw]; | ||
1056 | } | ||
1057 | |||
1058 | static int carl9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) | ||
1059 | { | ||
1060 | int idx = nfreqs - 2; | ||
1061 | |||
1062 | while (idx >= 0) { | ||
1063 | if (f >= freqs[idx]) | ||
1064 | return idx; | ||
1065 | idx--; | ||
1066 | } | ||
1067 | |||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static s32 carl9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) | ||
1072 | { | ||
1073 | /* nothing to interpolate, it's horizontal */ | ||
1074 | if (y2 == y1) | ||
1075 | return y1; | ||
1076 | |||
1077 | /* check if we hit one of the edges */ | ||
1078 | if (x == x1) | ||
1079 | return y1; | ||
1080 | if (x == x2) | ||
1081 | return y2; | ||
1082 | |||
1083 | /* x1 == x2 is bad, hopefully == x */ | ||
1084 | if (x2 == x1) | ||
1085 | return y1; | ||
1086 | |||
1087 | return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); | ||
1088 | } | ||
1089 | |||
1090 | static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) | ||
1091 | { | ||
1092 | #define SHIFT 8 | ||
1093 | s32 y; | ||
1094 | |||
1095 | y = carl9170_interpolate_s32(x << SHIFT, x1 << SHIFT, | ||
1096 | y1 << SHIFT, x2 << SHIFT, y2 << SHIFT); | ||
1097 | |||
1098 | /* | ||
1099 | * XXX: unwrap this expression | ||
1100 | * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)? | ||
1101 | * Can we rely on the compiler to optimise away the div? | ||
1102 | */ | ||
1103 | return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); | ||
1104 | #undef SHIFT | ||
1105 | } | ||
1106 | |||
1107 | static u8 carl9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) | ||
1108 | { | ||
1109 | int i; | ||
1110 | |||
1111 | for (i = 0; i < 3; i++) { | ||
1112 | if (x <= x_array[i + 1]) | ||
1113 | break; | ||
1114 | } | ||
1115 | |||
1116 | return carl9170_interpolate_u8(x, x_array[i], y_array[i], | ||
1117 | x_array[i + 1], y_array[i + 1]); | ||
1118 | } | ||
1119 | |||
1120 | static int carl9170_set_freq_cal_data(struct ar9170 *ar, | ||
1121 | struct ieee80211_channel *channel) | ||
1122 | { | ||
1123 | u8 *cal_freq_pier; | ||
1124 | u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; | ||
1125 | u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; | ||
1126 | int chain, idx, i; | ||
1127 | u32 phy_data = 0; | ||
1128 | u8 f, tmp; | ||
1129 | |||
1130 | switch (channel->band) { | ||
1131 | case IEEE80211_BAND_2GHZ: | ||
1132 | f = channel->center_freq - 2300; | ||
1133 | cal_freq_pier = ar->eeprom.cal_freq_pier_2G; | ||
1134 | i = AR5416_NUM_2G_CAL_PIERS - 1; | ||
1135 | break; | ||
1136 | |||
1137 | case IEEE80211_BAND_5GHZ: | ||
1138 | f = (channel->center_freq - 4800) / 5; | ||
1139 | cal_freq_pier = ar->eeprom.cal_freq_pier_5G; | ||
1140 | i = AR5416_NUM_5G_CAL_PIERS - 1; | ||
1141 | break; | ||
1142 | |||
1143 | default: | ||
1144 | return -EINVAL; | ||
1145 | break; | ||
1146 | } | ||
1147 | |||
1148 | for (; i >= 0; i--) { | ||
1149 | if (cal_freq_pier[i] != 0xff) | ||
1150 | break; | ||
1151 | } | ||
1152 | if (i < 0) | ||
1153 | return -EINVAL; | ||
1154 | |||
1155 | idx = carl9170_find_freq_idx(i, cal_freq_pier, f); | ||
1156 | |||
1157 | carl9170_regwrite_begin(ar); | ||
1158 | |||
1159 | for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { | ||
1160 | for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { | ||
1161 | struct ar9170_calibration_data_per_freq *cal_pier_data; | ||
1162 | int j; | ||
1163 | |||
1164 | switch (channel->band) { | ||
1165 | case IEEE80211_BAND_2GHZ: | ||
1166 | cal_pier_data = &ar->eeprom. | ||
1167 | cal_pier_data_2G[chain][idx]; | ||
1168 | break; | ||
1169 | |||
1170 | case IEEE80211_BAND_5GHZ: | ||
1171 | cal_pier_data = &ar->eeprom. | ||
1172 | cal_pier_data_5G[chain][idx]; | ||
1173 | break; | ||
1174 | |||
1175 | default: | ||
1176 | return -EINVAL; | ||
1177 | } | ||
1178 | |||
1179 | for (j = 0; j < 2; j++) { | ||
1180 | vpds[j][i] = carl9170_interpolate_u8(f, | ||
1181 | cal_freq_pier[idx], | ||
1182 | cal_pier_data->vpd_pdg[j][i], | ||
1183 | cal_freq_pier[idx + 1], | ||
1184 | cal_pier_data[1].vpd_pdg[j][i]); | ||
1185 | |||
1186 | pwrs[j][i] = carl9170_interpolate_u8(f, | ||
1187 | cal_freq_pier[idx], | ||
1188 | cal_pier_data->pwr_pdg[j][i], | ||
1189 | cal_freq_pier[idx + 1], | ||
1190 | cal_pier_data[1].pwr_pdg[j][i]) / 2; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | for (i = 0; i < 76; i++) { | ||
1195 | if (i < 25) { | ||
1196 | tmp = carl9170_interpolate_val(i, &pwrs[0][0], | ||
1197 | &vpds[0][0]); | ||
1198 | } else { | ||
1199 | tmp = carl9170_interpolate_val(i - 12, | ||
1200 | &pwrs[1][0], | ||
1201 | &vpds[1][0]); | ||
1202 | } | ||
1203 | |||
1204 | phy_data |= tmp << ((i & 3) << 3); | ||
1205 | if ((i & 3) == 3) { | ||
1206 | carl9170_regwrite(0x1c6280 + chain * 0x1000 + | ||
1207 | (i & ~3), phy_data); | ||
1208 | phy_data = 0; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | for (i = 19; i < 32; i++) | ||
1213 | carl9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), | ||
1214 | 0x0); | ||
1215 | } | ||
1216 | |||
1217 | carl9170_regwrite_finish(); | ||
1218 | return carl9170_regwrite_result(); | ||
1219 | } | ||
1220 | |||
1221 | static u8 carl9170_get_max_edge_power(struct ar9170 *ar, | ||
1222 | u32 freq, struct ar9170_calctl_edges edges[]) | ||
1223 | { | ||
1224 | int i; | ||
1225 | u8 rc = AR5416_MAX_RATE_POWER; | ||
1226 | u8 f; | ||
1227 | if (freq < 3000) | ||
1228 | f = freq - 2300; | ||
1229 | else | ||
1230 | f = (freq - 4800) / 5; | ||
1231 | |||
1232 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1233 | if (edges[i].channel == 0xff) | ||
1234 | break; | ||
1235 | if (f == edges[i].channel) { | ||
1236 | /* exact freq match */ | ||
1237 | rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; | ||
1238 | break; | ||
1239 | } | ||
1240 | if (i > 0 && f < edges[i].channel) { | ||
1241 | if (f > edges[i - 1].channel && | ||
1242 | edges[i - 1].power_flags & | ||
1243 | AR9170_CALCTL_EDGE_FLAGS) { | ||
1244 | /* lower channel has the inband flag set */ | ||
1245 | rc = edges[i - 1].power_flags & | ||
1246 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1247 | } | ||
1248 | break; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | if (i == AR5416_NUM_BAND_EDGES) { | ||
1253 | if (f > edges[i - 1].channel && | ||
1254 | edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | ||
1255 | /* lower channel has the inband flag set */ | ||
1256 | rc = edges[i - 1].power_flags & | ||
1257 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1258 | } | ||
1259 | } | ||
1260 | return rc; | ||
1261 | } | ||
1262 | |||
1263 | static u8 carl9170_get_heavy_clip(struct ar9170 *ar, u32 freq, | ||
1264 | enum carl9170_bw bw, struct ar9170_calctl_edges edges[]) | ||
1265 | { | ||
1266 | u8 f; | ||
1267 | int i; | ||
1268 | u8 rc = 0; | ||
1269 | |||
1270 | if (freq < 3000) | ||
1271 | f = freq - 2300; | ||
1272 | else | ||
1273 | f = (freq - 4800) / 5; | ||
1274 | |||
1275 | if (bw == CARL9170_BW_40_BELOW || bw == CARL9170_BW_40_ABOVE) | ||
1276 | rc |= 0xf0; | ||
1277 | |||
1278 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1279 | if (edges[i].channel == 0xff) | ||
1280 | break; | ||
1281 | if (f == edges[i].channel) { | ||
1282 | if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) | ||
1283 | rc |= 0x0f; | ||
1284 | break; | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | return rc; | ||
1289 | } | ||
1290 | |||
1291 | /* | ||
1292 | * calculate the conformance test limits and the heavy clip parameter | ||
1293 | * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) | ||
1294 | */ | ||
1295 | static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) | ||
1296 | { | ||
1297 | u8 ctl_grp; /* CTL group */ | ||
1298 | u8 ctl_idx; /* CTL index */ | ||
1299 | int i, j; | ||
1300 | struct ctl_modes { | ||
1301 | u8 ctl_mode; | ||
1302 | u8 max_power; | ||
1303 | u8 *pwr_cal_data; | ||
1304 | int pwr_cal_len; | ||
1305 | } *modes; | ||
1306 | |||
1307 | /* | ||
1308 | * order is relevant in the mode_list_*: we fall back to the | ||
1309 | * lower indices if any mode is missed in the EEPROM. | ||
1310 | */ | ||
1311 | struct ctl_modes mode_list_2ghz[] = { | ||
1312 | { CTL_11B, 0, ar->power_2G_cck, 4 }, | ||
1313 | { CTL_11G, 0, ar->power_2G_ofdm, 4 }, | ||
1314 | { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, | ||
1315 | { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, | ||
1316 | }; | ||
1317 | struct ctl_modes mode_list_5ghz[] = { | ||
1318 | { CTL_11A, 0, ar->power_5G_leg, 4 }, | ||
1319 | { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, | ||
1320 | { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, | ||
1321 | }; | ||
1322 | int nr_modes; | ||
1323 | |||
1324 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) | ||
1325 | |||
1326 | ar->heavy_clip = 0; | ||
1327 | |||
1328 | /* | ||
1329 | * TODO: investigate the differences between OTUS' | ||
1330 | * hpreg.c::zfHpGetRegulatoryDomain() and | ||
1331 | * ath/regd.c::ath_regd_get_band_ctl() - | ||
1332 | * e.g. for FCC3_WORLD the OTUS procedure | ||
1333 | * always returns CTL_FCC, while the one in ath/ delivers | ||
1334 | * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. | ||
1335 | */ | ||
1336 | ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, | ||
1337 | ar->hw->conf.channel->band); | ||
1338 | |||
1339 | /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ | ||
1340 | if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) | ||
1341 | ctl_grp = CTL_FCC; | ||
1342 | |||
1343 | if (ctl_grp != CTL_FCC) | ||
1344 | /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ | ||
1345 | return; | ||
1346 | |||
1347 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
1348 | modes = mode_list_2ghz; | ||
1349 | nr_modes = ARRAY_SIZE(mode_list_2ghz); | ||
1350 | } else { | ||
1351 | modes = mode_list_5ghz; | ||
1352 | nr_modes = ARRAY_SIZE(mode_list_5ghz); | ||
1353 | } | ||
1354 | |||
1355 | for (i = 0; i < nr_modes; i++) { | ||
1356 | u8 c = ctl_grp | modes[i].ctl_mode; | ||
1357 | for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) | ||
1358 | if (c == ar->eeprom.ctl_index[ctl_idx]) | ||
1359 | break; | ||
1360 | if (ctl_idx < AR5416_NUM_CTLS) { | ||
1361 | int f_off = 0; | ||
1362 | |||
1363 | /* | ||
1364 | * determine heavy clip parameter | ||
1365 | * from the 11G edges array | ||
1366 | */ | ||
1367 | if (modes[i].ctl_mode == CTL_11G) { | ||
1368 | ar->heavy_clip = | ||
1369 | carl9170_get_heavy_clip(ar, | ||
1370 | freq, bw, EDGES(ctl_idx, 1)); | ||
1371 | } | ||
1372 | |||
1373 | /* adjust freq for 40MHz */ | ||
1374 | if (modes[i].ctl_mode == CTL_2GHT40 || | ||
1375 | modes[i].ctl_mode == CTL_5GHT40) { | ||
1376 | if (bw == CARL9170_BW_40_BELOW) | ||
1377 | f_off = -10; | ||
1378 | else | ||
1379 | f_off = 10; | ||
1380 | } | ||
1381 | |||
1382 | modes[i].max_power = | ||
1383 | carl9170_get_max_edge_power(ar, | ||
1384 | freq+f_off, EDGES(ctl_idx, 1)); | ||
1385 | |||
1386 | /* | ||
1387 | * TODO: check if the regulatory max. power is | ||
1388 | * controlled by cfg80211 for DFS. | ||
1389 | * (hpmain applies it to max_power itself for DFS freq) | ||
1390 | */ | ||
1391 | |||
1392 | } else { | ||
1393 | /* | ||
1394 | * Workaround in otus driver, hpmain.c, line 3906: | ||
1395 | * if no data for 5GHT20 are found, take the | ||
1396 | * legacy 5G value. We extend this here to fallback | ||
1397 | * from any other HT* or 11G, too. | ||
1398 | */ | ||
1399 | int k = i; | ||
1400 | |||
1401 | modes[i].max_power = AR5416_MAX_RATE_POWER; | ||
1402 | while (k-- > 0) { | ||
1403 | if (modes[k].max_power != | ||
1404 | AR5416_MAX_RATE_POWER) { | ||
1405 | modes[i].max_power = modes[k].max_power; | ||
1406 | break; | ||
1407 | } | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | /* apply max power to pwr_cal_data (ar->power_*) */ | ||
1412 | for (j = 0; j < modes[i].pwr_cal_len; j++) { | ||
1413 | modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], | ||
1414 | modes[i].max_power); | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | if (ar->heavy_clip & 0xf0) { | ||
1419 | ar->power_2G_ht40[0]--; | ||
1420 | ar->power_2G_ht40[1]--; | ||
1421 | ar->power_2G_ht40[2]--; | ||
1422 | } | ||
1423 | if (ar->heavy_clip & 0xf) { | ||
1424 | ar->power_2G_ht20[0]++; | ||
1425 | ar->power_2G_ht20[1]++; | ||
1426 | ar->power_2G_ht20[2]++; | ||
1427 | } | ||
1428 | |||
1429 | #undef EDGES | ||
1430 | } | ||
1431 | |||
1432 | static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, | ||
1433 | enum carl9170_bw bw) | ||
1434 | { | ||
1435 | struct ar9170_calibration_target_power_legacy *ctpl; | ||
1436 | struct ar9170_calibration_target_power_ht *ctph; | ||
1437 | u8 *ctpres; | ||
1438 | int ntargets; | ||
1439 | int idx, i, n; | ||
1440 | u8 ackpower, ackchains, f; | ||
1441 | u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; | ||
1442 | |||
1443 | if (freq < 3000) | ||
1444 | f = freq - 2300; | ||
1445 | else | ||
1446 | f = (freq - 4800)/5; | ||
1447 | |||
1448 | /* | ||
1449 | * cycle through the various modes | ||
1450 | * | ||
1451 | * legacy modes first: 5G, 2G CCK, 2G OFDM | ||
1452 | */ | ||
1453 | for (i = 0; i < 3; i++) { | ||
1454 | switch (i) { | ||
1455 | case 0: /* 5 GHz legacy */ | ||
1456 | ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; | ||
1457 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1458 | ctpres = ar->power_5G_leg; | ||
1459 | break; | ||
1460 | case 1: /* 2.4 GHz CCK */ | ||
1461 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; | ||
1462 | ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; | ||
1463 | ctpres = ar->power_2G_cck; | ||
1464 | break; | ||
1465 | case 2: /* 2.4 GHz OFDM */ | ||
1466 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; | ||
1467 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1468 | ctpres = ar->power_2G_ofdm; | ||
1469 | break; | ||
1470 | default: | ||
1471 | BUG(); | ||
1472 | } | ||
1473 | |||
1474 | for (n = 0; n < ntargets; n++) { | ||
1475 | if (ctpl[n].freq == 0xff) | ||
1476 | break; | ||
1477 | pwr_freqs[n] = ctpl[n].freq; | ||
1478 | } | ||
1479 | ntargets = n; | ||
1480 | idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1481 | for (n = 0; n < 4; n++) | ||
1482 | ctpres[n] = carl9170_interpolate_u8(f, | ||
1483 | ctpl[idx + 0].freq, ctpl[idx + 0].power[n], | ||
1484 | ctpl[idx + 1].freq, ctpl[idx + 1].power[n]); | ||
1485 | } | ||
1486 | |||
1487 | /* HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 */ | ||
1488 | for (i = 0; i < 4; i++) { | ||
1489 | switch (i) { | ||
1490 | case 0: /* 5 GHz HT 20 */ | ||
1491 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; | ||
1492 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1493 | ctpres = ar->power_5G_ht20; | ||
1494 | break; | ||
1495 | case 1: /* 5 GHz HT 40 */ | ||
1496 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; | ||
1497 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1498 | ctpres = ar->power_5G_ht40; | ||
1499 | break; | ||
1500 | case 2: /* 2.4 GHz HT 20 */ | ||
1501 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; | ||
1502 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1503 | ctpres = ar->power_2G_ht20; | ||
1504 | break; | ||
1505 | case 3: /* 2.4 GHz HT 40 */ | ||
1506 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; | ||
1507 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1508 | ctpres = ar->power_2G_ht40; | ||
1509 | break; | ||
1510 | default: | ||
1511 | BUG(); | ||
1512 | } | ||
1513 | |||
1514 | for (n = 0; n < ntargets; n++) { | ||
1515 | if (ctph[n].freq == 0xff) | ||
1516 | break; | ||
1517 | pwr_freqs[n] = ctph[n].freq; | ||
1518 | } | ||
1519 | ntargets = n; | ||
1520 | idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1521 | for (n = 0; n < 8; n++) | ||
1522 | ctpres[n] = carl9170_interpolate_u8(f, | ||
1523 | ctph[idx + 0].freq, ctph[idx + 0].power[n], | ||
1524 | ctph[idx + 1].freq, ctph[idx + 1].power[n]); | ||
1525 | } | ||
1526 | |||
1527 | /* calc. conformance test limits and apply to ar->power*[] */ | ||
1528 | carl9170_calc_ctl(ar, freq, bw); | ||
1529 | |||
1530 | /* set ACK/CTS TX power */ | ||
1531 | carl9170_regwrite_begin(ar); | ||
1532 | |||
1533 | if (ar->eeprom.tx_mask != 1) | ||
1534 | ackchains = AR9170_TX_PHY_TXCHAIN_2; | ||
1535 | else | ||
1536 | ackchains = AR9170_TX_PHY_TXCHAIN_1; | ||
1537 | |||
1538 | if (freq < 3000) | ||
1539 | ackpower = ar->power_2G_ofdm[0] & 0x3f; | ||
1540 | else | ||
1541 | ackpower = ar->power_5G_leg[0] & 0x3f; | ||
1542 | |||
1543 | carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, | ||
1544 | 0x3c1e | ackpower << 20 | ackchains << 26); | ||
1545 | carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC, | ||
1546 | ackpower << 5 | ackchains << 11 | | ||
1547 | ackpower << 21 | ackchains << 27); | ||
1548 | |||
1549 | carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC, | ||
1550 | ackpower << 5 | ackchains << 11 | | ||
1551 | ackpower << 21 | ackchains << 27); | ||
1552 | |||
1553 | carl9170_regwrite_finish(); | ||
1554 | return carl9170_regwrite_result(); | ||
1555 | } | ||
1556 | |||
1557 | /* TODO: replace this with sign_extend32(noise, 8) */ | ||
1558 | static int carl9170_calc_noise_dbm(u32 raw_noise) | ||
1559 | { | ||
1560 | if (raw_noise & 0x100) | ||
1561 | return ~0x1ff | raw_noise; | ||
1562 | else | ||
1563 | return raw_noise; | ||
1564 | } | ||
1565 | |||
1566 | int carl9170_get_noisefloor(struct ar9170 *ar) | ||
1567 | { | ||
1568 | static const u32 phy_regs[] = { | ||
1569 | AR9170_PHY_REG_CCA, AR9170_PHY_REG_CH2_CCA, | ||
1570 | AR9170_PHY_REG_EXT_CCA, AR9170_PHY_REG_CH2_EXT_CCA }; | ||
1571 | u32 phy_res[ARRAY_SIZE(phy_regs)]; | ||
1572 | int err, i; | ||
1573 | |||
1574 | BUILD_BUG_ON(ARRAY_SIZE(phy_regs) != ARRAY_SIZE(ar->noise)); | ||
1575 | |||
1576 | err = carl9170_read_mreg(ar, ARRAY_SIZE(phy_regs), phy_regs, phy_res); | ||
1577 | if (err) | ||
1578 | return err; | ||
1579 | |||
1580 | for (i = 0; i < 2; i++) { | ||
1581 | ar->noise[i] = carl9170_calc_noise_dbm( | ||
1582 | (phy_res[i] >> 19) & 0x1ff); | ||
1583 | |||
1584 | ar->noise[i + 2] = carl9170_calc_noise_dbm( | ||
1585 | (phy_res[i + 2] >> 23) & 0x1ff); | ||
1586 | } | ||
1587 | |||
1588 | return 0; | ||
1589 | } | ||
1590 | |||
1591 | static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type) | ||
1592 | { | ||
1593 | switch (type) { | ||
1594 | case NL80211_CHAN_NO_HT: | ||
1595 | case NL80211_CHAN_HT20: | ||
1596 | return CARL9170_BW_20; | ||
1597 | case NL80211_CHAN_HT40MINUS: | ||
1598 | return CARL9170_BW_40_BELOW; | ||
1599 | case NL80211_CHAN_HT40PLUS: | ||
1600 | return CARL9170_BW_40_ABOVE; | ||
1601 | default: | ||
1602 | BUG(); | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
1607 | enum nl80211_channel_type _bw, | ||
1608 | enum carl9170_rf_init_mode rfi) | ||
1609 | { | ||
1610 | const struct carl9170_phy_freq_params *freqpar; | ||
1611 | struct carl9170_rf_init_result rf_res; | ||
1612 | struct carl9170_rf_init rf; | ||
1613 | u32 cmd, tmp, offs = 0, new_ht = 0; | ||
1614 | int err; | ||
1615 | enum carl9170_bw bw; | ||
1616 | bool warm_reset; | ||
1617 | struct ieee80211_channel *old_channel = NULL; | ||
1618 | |||
1619 | bw = nl80211_to_carl(_bw); | ||
1620 | |||
1621 | if (conf_is_ht(&ar->hw->conf)) | ||
1622 | new_ht |= CARL9170FW_PHY_HT_ENABLE; | ||
1623 | |||
1624 | if (conf_is_ht40(&ar->hw->conf)) | ||
1625 | new_ht |= CARL9170FW_PHY_HT_DYN2040; | ||
1626 | |||
1627 | /* may be NULL at first setup */ | ||
1628 | if (ar->channel) { | ||
1629 | old_channel = ar->channel; | ||
1630 | warm_reset = (old_channel->band != channel->band) || | ||
1631 | (old_channel->center_freq == | ||
1632 | channel->center_freq) || | ||
1633 | (ar->ht_settings != new_ht); | ||
1634 | |||
1635 | ar->channel = NULL; | ||
1636 | } else { | ||
1637 | warm_reset = true; | ||
1638 | } | ||
1639 | |||
1640 | /* HW workaround */ | ||
1641 | if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && | ||
1642 | channel->center_freq <= 2417) | ||
1643 | warm_reset = true; | ||
1644 | |||
1645 | if (rfi != CARL9170_RFI_NONE || warm_reset) { | ||
1646 | u32 val; | ||
1647 | |||
1648 | if (rfi == CARL9170_RFI_COLD) | ||
1649 | val = AR9170_PWR_RESET_BB_COLD_RESET; | ||
1650 | else | ||
1651 | val = AR9170_PWR_RESET_BB_WARM_RESET; | ||
1652 | |||
1653 | /* warm/cold reset BB/ADDA */ | ||
1654 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val); | ||
1655 | if (err) | ||
1656 | return err; | ||
1657 | |||
1658 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); | ||
1659 | if (err) | ||
1660 | return err; | ||
1661 | |||
1662 | err = carl9170_init_phy(ar, channel->band); | ||
1663 | if (err) | ||
1664 | return err; | ||
1665 | |||
1666 | err = carl9170_init_rf_banks_0_7(ar, | ||
1667 | channel->band == IEEE80211_BAND_5GHZ); | ||
1668 | if (err) | ||
1669 | return err; | ||
1670 | |||
1671 | cmd = CARL9170_CMD_RF_INIT; | ||
1672 | |||
1673 | msleep(100); | ||
1674 | |||
1675 | err = carl9170_echo_test(ar, 0xaabbccdd); | ||
1676 | if (err) | ||
1677 | return err; | ||
1678 | } else { | ||
1679 | cmd = CARL9170_CMD_FREQUENCY; | ||
1680 | } | ||
1681 | |||
1682 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); | ||
1683 | if (err) | ||
1684 | return err; | ||
1685 | |||
1686 | err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, | ||
1687 | 0x200); | ||
1688 | |||
1689 | err = carl9170_init_rf_bank4_pwr(ar, | ||
1690 | channel->band == IEEE80211_BAND_5GHZ, | ||
1691 | channel->center_freq, bw); | ||
1692 | if (err) | ||
1693 | return err; | ||
1694 | |||
1695 | tmp = AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 | | ||
1696 | AR9170_PHY_TURBO_FC_HT_EN; | ||
1697 | |||
1698 | switch (bw) { | ||
1699 | case CARL9170_BW_20: | ||
1700 | break; | ||
1701 | case CARL9170_BW_40_BELOW: | ||
1702 | tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN | | ||
1703 | AR9170_PHY_TURBO_FC_SHORT_GI_40; | ||
1704 | offs = 3; | ||
1705 | break; | ||
1706 | case CARL9170_BW_40_ABOVE: | ||
1707 | tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN | | ||
1708 | AR9170_PHY_TURBO_FC_SHORT_GI_40 | | ||
1709 | AR9170_PHY_TURBO_FC_DYN2040_PRI_CH; | ||
1710 | offs = 1; | ||
1711 | break; | ||
1712 | default: | ||
1713 | BUG(); | ||
1714 | return -ENOSYS; | ||
1715 | } | ||
1716 | |||
1717 | if (ar->eeprom.tx_mask != 1) | ||
1718 | tmp |= AR9170_PHY_TURBO_FC_WALSH; | ||
1719 | |||
1720 | err = carl9170_write_reg(ar, AR9170_PHY_REG_TURBO, tmp); | ||
1721 | if (err) | ||
1722 | return err; | ||
1723 | |||
1724 | err = carl9170_set_freq_cal_data(ar, channel); | ||
1725 | if (err) | ||
1726 | return err; | ||
1727 | |||
1728 | err = carl9170_set_power_cal(ar, channel->center_freq, bw); | ||
1729 | if (err) | ||
1730 | return err; | ||
1731 | |||
1732 | freqpar = carl9170_get_hw_dyn_params(channel, bw); | ||
1733 | |||
1734 | rf.ht_settings = new_ht; | ||
1735 | if (conf_is_ht40(&ar->hw->conf)) | ||
1736 | SET_VAL(CARL9170FW_PHY_HT_EXT_CHAN_OFF, rf.ht_settings, offs); | ||
1737 | |||
1738 | rf.freq = cpu_to_le32(channel->center_freq * 1000); | ||
1739 | rf.delta_slope_coeff_exp = cpu_to_le32(freqpar->coeff_exp); | ||
1740 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); | ||
1741 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); | ||
1742 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); | ||
1743 | |||
1744 | if (rfi != CARL9170_RFI_NONE) | ||
1745 | rf.finiteLoopCount = cpu_to_le32(2000); | ||
1746 | else | ||
1747 | rf.finiteLoopCount = cpu_to_le32(1000); | ||
1748 | |||
1749 | err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf, | ||
1750 | sizeof(rf_res), &rf_res); | ||
1751 | if (err) | ||
1752 | return err; | ||
1753 | |||
1754 | err = le32_to_cpu(rf_res.ret); | ||
1755 | if (err != 0) { | ||
1756 | ar->chan_fail++; | ||
1757 | ar->total_chan_fail++; | ||
1758 | |||
1759 | wiphy_err(ar->hw->wiphy, "channel change: %d -> %d " | ||
1760 | "failed (%d).\n", old_channel ? | ||
1761 | old_channel->center_freq : -1, channel->center_freq, | ||
1762 | err); | ||
1763 | |||
1764 | if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) { | ||
1765 | /* | ||
1766 | * We have tried very hard to change to _another_ | ||
1767 | * channel and we've failed to do so! | ||
1768 | * Chances are that the PHY/RF is no longer | ||
1769 | * operable (due to corruptions/fatal events/bugs?) | ||
1770 | * and we need to reset at a higher level. | ||
1771 | */ | ||
1772 | carl9170_restart(ar, CARL9170_RR_TOO_MANY_PHY_ERRORS); | ||
1773 | return 0; | ||
1774 | } | ||
1775 | |||
1776 | err = carl9170_set_channel(ar, channel, _bw, | ||
1777 | CARL9170_RFI_COLD); | ||
1778 | if (err) | ||
1779 | return err; | ||
1780 | } else { | ||
1781 | ar->chan_fail = 0; | ||
1782 | } | ||
1783 | |||
1784 | err = carl9170_get_noisefloor(ar); | ||
1785 | if (err) | ||
1786 | return err; | ||
1787 | |||
1788 | if (ar->heavy_clip) { | ||
1789 | err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, | ||
1790 | 0x200 | ar->heavy_clip); | ||
1791 | if (err) { | ||
1792 | if (net_ratelimit()) { | ||
1793 | wiphy_err(ar->hw->wiphy, "failed to set " | ||
1794 | "heavy clip\n"); | ||
1795 | } | ||
1796 | |||
1797 | return err; | ||
1798 | } | ||
1799 | } | ||
1800 | |||
1801 | /* FIXME: PSM does not work in 5GHz Band */ | ||
1802 | if (channel->band == IEEE80211_BAND_5GHZ) | ||
1803 | ar->ps.off_override |= PS_OFF_5GHZ; | ||
1804 | else | ||
1805 | ar->ps.off_override &= ~PS_OFF_5GHZ; | ||
1806 | |||
1807 | ar->channel = channel; | ||
1808 | ar->ht_settings = new_ht; | ||
1809 | return 0; | ||
1810 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h new file mode 100644 index 000000000000..53c18d34ffcc --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/phy.h | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * PHY register map | ||
5 | * | ||
6 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
7 | * | ||
8 | * Permission to use, copy, modify, and/or distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | */ | ||
20 | |||
21 | #ifndef __CARL9170_SHARED_PHY_H | ||
22 | #define __CARL9170_SHARED_PHY_H | ||
23 | |||
24 | #define AR9170_PHY_REG_BASE (0x1bc000 + 0x9800) | ||
25 | #define AR9170_PHY_REG(_n) (AR9170_PHY_REG_BASE + \ | ||
26 | ((_n) << 2)) | ||
27 | |||
28 | #define AR9170_PHY_REG_TEST (AR9170_PHY_REG_BASE + 0x0000) | ||
29 | #define AR9170_PHY_TEST_AGC_CLR 0x10000000 | ||
30 | #define AR9170_PHY_TEST_RFSILENT_BB 0x00002000 | ||
31 | |||
32 | #define AR9170_PHY_REG_TURBO (AR9170_PHY_REG_BASE + 0x0004) | ||
33 | #define AR9170_PHY_TURBO_FC_TURBO_MODE 0x00000001 | ||
34 | #define AR9170_PHY_TURBO_FC_TURBO_SHORT 0x00000002 | ||
35 | #define AR9170_PHY_TURBO_FC_DYN2040_EN 0x00000004 | ||
36 | #define AR9170_PHY_TURBO_FC_DYN2040_PRI_ONLY 0x00000008 | ||
37 | #define AR9170_PHY_TURBO_FC_DYN2040_PRI_CH 0x00000010 | ||
38 | /* For 25 MHz channel spacing -- not used but supported by hw */ | ||
39 | #define AR9170_PHY_TURBO_FC_DYN2040_EXT_CH 0x00000020 | ||
40 | #define AR9170_PHY_TURBO_FC_HT_EN 0x00000040 | ||
41 | #define AR9170_PHY_TURBO_FC_SHORT_GI_40 0x00000080 | ||
42 | #define AR9170_PHY_TURBO_FC_WALSH 0x00000100 | ||
43 | #define AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 0x00000200 | ||
44 | #define AR9170_PHY_TURBO_FC_ENABLE_DAC_FIFO 0x00000800 | ||
45 | |||
46 | #define AR9170_PHY_REG_TEST2 (AR9170_PHY_REG_BASE + 0x0008) | ||
47 | |||
48 | #define AR9170_PHY_REG_TIMING2 (AR9170_PHY_REG_BASE + 0x0010) | ||
49 | #define AR9170_PHY_TIMING2_USE_FORCE 0x00001000 | ||
50 | #define AR9170_PHY_TIMING2_FORCE 0x00000fff | ||
51 | #define AR9170_PHY_TIMING2_FORCE_S 0 | ||
52 | |||
53 | #define AR9170_PHY_REG_TIMING3 (AR9170_PHY_REG_BASE + 0x0014) | ||
54 | #define AR9170_PHY_TIMING3_DSC_EXP 0x0001e000 | ||
55 | #define AR9170_PHY_TIMING3_DSC_EXP_S 13 | ||
56 | #define AR9170_PHY_TIMING3_DSC_MAN 0xfffe0000 | ||
57 | #define AR9170_PHY_TIMING3_DSC_MAN_S 17 | ||
58 | |||
59 | #define AR9170_PHY_REG_CHIP_ID (AR9170_PHY_REG_BASE + 0x0018) | ||
60 | #define AR9170_PHY_CHIP_ID_REV_0 0x80 | ||
61 | #define AR9170_PHY_CHIP_ID_REV_1 0x81 | ||
62 | #define AR9170_PHY_CHIP_ID_9160_REV_0 0xb0 | ||
63 | |||
64 | #define AR9170_PHY_REG_ACTIVE (AR9170_PHY_REG_BASE + 0x001c) | ||
65 | #define AR9170_PHY_ACTIVE_EN 0x00000001 | ||
66 | #define AR9170_PHY_ACTIVE_DIS 0x00000000 | ||
67 | |||
68 | #define AR9170_PHY_REG_RF_CTL2 (AR9170_PHY_REG_BASE + 0x0024) | ||
69 | #define AR9170_PHY_RF_CTL2_TX_END_DATA_START 0x000000ff | ||
70 | #define AR9170_PHY_RF_CTL2_TX_END_DATA_START_S 0 | ||
71 | #define AR9170_PHY_RF_CTL2_TX_END_PA_ON 0x0000ff00 | ||
72 | #define AR9170_PHY_RF_CTL2_TX_END_PA_ON_S 8 | ||
73 | |||
74 | #define AR9170_PHY_REG_RF_CTL3 (AR9170_PHY_REG_BASE + 0x0028) | ||
75 | #define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON 0x00ff0000 | ||
76 | #define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON_S 16 | ||
77 | |||
78 | #define AR9170_PHY_REG_ADC_CTL (AR9170_PHY_REG_BASE + 0x002c) | ||
79 | #define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 | ||
80 | #define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 | ||
81 | #define AR9170_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 | ||
82 | #define AR9170_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 | ||
83 | #define AR9170_PHY_ADC_CTL_OFF_PWDADC 0x00008000 | ||
84 | #define AR9170_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 | ||
85 | #define AR9170_PHY_ADC_CTL_ON_INBUFGAIN_S 16 | ||
86 | |||
87 | #define AR9170_PHY_REG_ADC_SERIAL_CTL (AR9170_PHY_REG_BASE + 0x0030) | ||
88 | #define AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC 0x00000000 | ||
89 | #define AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO 0x00000001 | ||
90 | |||
91 | #define AR9170_PHY_REG_RF_CTL4 (AR9170_PHY_REG_BASE + 0x0034) | ||
92 | #define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF 0xff000000 | ||
93 | #define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 | ||
94 | #define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00ff0000 | ||
95 | #define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 | ||
96 | #define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000ff00 | ||
97 | #define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 | ||
98 | #define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000ff | ||
99 | #define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 | ||
100 | |||
101 | #define AR9170_PHY_REG_TSTDAC_CONST (AR9170_PHY_REG_BASE + 0x003c) | ||
102 | |||
103 | #define AR9170_PHY_REG_SETTLING (AR9170_PHY_REG_BASE + 0x0044) | ||
104 | #define AR9170_PHY_SETTLING_SWITCH 0x00003f80 | ||
105 | #define AR9170_PHY_SETTLING_SWITCH_S 7 | ||
106 | |||
107 | #define AR9170_PHY_REG_RXGAIN (AR9170_PHY_REG_BASE + 0x0048) | ||
108 | #define AR9170_PHY_REG_RXGAIN_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2048) | ||
109 | #define AR9170_PHY_RXGAIN_TXRX_ATTEN 0x0003f000 | ||
110 | #define AR9170_PHY_RXGAIN_TXRX_ATTEN_S 12 | ||
111 | #define AR9170_PHY_RXGAIN_TXRX_RF_MAX 0x007c0000 | ||
112 | #define AR9170_PHY_RXGAIN_TXRX_RF_MAX_S 18 | ||
113 | |||
114 | #define AR9170_PHY_REG_DESIRED_SZ (AR9170_PHY_REG_BASE + 0x0050) | ||
115 | #define AR9170_PHY_DESIRED_SZ_ADC 0x000000ff | ||
116 | #define AR9170_PHY_DESIRED_SZ_ADC_S 0 | ||
117 | #define AR9170_PHY_DESIRED_SZ_PGA 0x0000ff00 | ||
118 | #define AR9170_PHY_DESIRED_SZ_PGA_S 8 | ||
119 | #define AR9170_PHY_DESIRED_SZ_TOT_DES 0x0ff00000 | ||
120 | #define AR9170_PHY_DESIRED_SZ_TOT_DES_S 20 | ||
121 | |||
122 | #define AR9170_PHY_REG_FIND_SIG (AR9170_PHY_REG_BASE + 0x0058) | ||
123 | #define AR9170_PHY_FIND_SIG_FIRSTEP 0x0003f000 | ||
124 | #define AR9170_PHY_FIND_SIG_FIRSTEP_S 12 | ||
125 | #define AR9170_PHY_FIND_SIG_FIRPWR 0x03fc0000 | ||
126 | #define AR9170_PHY_FIND_SIG_FIRPWR_S 18 | ||
127 | |||
128 | #define AR9170_PHY_REG_AGC_CTL1 (AR9170_PHY_REG_BASE + 0x005c) | ||
129 | #define AR9170_PHY_AGC_CTL1_COARSE_LOW 0x00007f80 | ||
130 | #define AR9170_PHY_AGC_CTL1_COARSE_LOW_S 7 | ||
131 | #define AR9170_PHY_AGC_CTL1_COARSE_HIGH 0x003f8000 | ||
132 | #define AR9170_PHY_AGC_CTL1_COARSE_HIGH_S 15 | ||
133 | |||
134 | #define AR9170_PHY_REG_AGC_CONTROL (AR9170_PHY_REG_BASE + 0x0060) | ||
135 | #define AR9170_PHY_AGC_CONTROL_CAL 0x00000001 | ||
136 | #define AR9170_PHY_AGC_CONTROL_NF 0x00000002 | ||
137 | #define AR9170_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 | ||
138 | #define AR9170_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 | ||
139 | #define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 | ||
140 | |||
141 | #define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064) | ||
142 | #define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000 | ||
143 | #define AR9170_PHY_CCA_MINCCA_PWR_S 19 | ||
144 | #define AR9170_PHY_CCA_THRESH62 0x0007f000 | ||
145 | #define AR9170_PHY_CCA_THRESH62_S 12 | ||
146 | |||
147 | #define AR9170_PHY_REG_SFCORR (AR9170_PHY_REG_BASE + 0x0068) | ||
148 | #define AR9170_PHY_SFCORR_M2COUNT_THR 0x0000001f | ||
149 | #define AR9170_PHY_SFCORR_M2COUNT_THR_S 0 | ||
150 | #define AR9170_PHY_SFCORR_M1_THRESH 0x00fe0000 | ||
151 | #define AR9170_PHY_SFCORR_M1_THRESH_S 17 | ||
152 | #define AR9170_PHY_SFCORR_M2_THRESH 0x7f000000 | ||
153 | #define AR9170_PHY_SFCORR_M2_THRESH_S 24 | ||
154 | |||
155 | #define AR9170_PHY_REG_SFCORR_LOW (AR9170_PHY_REG_BASE + 0x006c) | ||
156 | #define AR9170_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 | ||
157 | #define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003f00 | ||
158 | #define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 | ||
159 | #define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001fc000 | ||
160 | #define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 | ||
161 | #define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0fe00000 | ||
162 | #define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 | ||
163 | |||
164 | #define AR9170_PHY_REG_SLEEP_CTR_CONTROL (AR9170_PHY_REG_BASE + 0x0070) | ||
165 | #define AR9170_PHY_REG_SLEEP_CTR_LIMIT (AR9170_PHY_REG_BASE + 0x0074) | ||
166 | #define AR9170_PHY_REG_SLEEP_SCAL (AR9170_PHY_REG_BASE + 0x0078) | ||
167 | |||
168 | #define AR9170_PHY_REG_PLL_CTL (AR9170_PHY_REG_BASE + 0x007c) | ||
169 | #define AR9170_PHY_PLL_CTL_40 0xaa | ||
170 | #define AR9170_PHY_PLL_CTL_40_5413 0x04 | ||
171 | #define AR9170_PHY_PLL_CTL_44 0xab | ||
172 | #define AR9170_PHY_PLL_CTL_44_2133 0xeb | ||
173 | #define AR9170_PHY_PLL_CTL_40_2133 0xea | ||
174 | |||
175 | #define AR9170_PHY_REG_BIN_MASK_1 (AR9170_PHY_REG_BASE + 0x0100) | ||
176 | #define AR9170_PHY_REG_BIN_MASK_2 (AR9170_PHY_REG_BASE + 0x0104) | ||
177 | #define AR9170_PHY_REG_BIN_MASK_3 (AR9170_PHY_REG_BASE + 0x0108) | ||
178 | #define AR9170_PHY_REG_MASK_CTL (AR9170_PHY_REG_BASE + 0x010c) | ||
179 | |||
180 | /* analogue power on time (100ns) */ | ||
181 | #define AR9170_PHY_REG_RX_DELAY (AR9170_PHY_REG_BASE + 0x0114) | ||
182 | #define AR9170_PHY_REG_SEARCH_START_DELAY (AR9170_PHY_REG_BASE + 0x0118) | ||
183 | #define AR9170_PHY_RX_DELAY_DELAY 0x00003fff | ||
184 | |||
185 | #define AR9170_PHY_REG_TIMING_CTRL4(_i) (AR9170_PHY_REG_BASE + \ | ||
186 | (0x0120 + ((_i) << 12))) | ||
187 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01f | ||
188 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 | ||
189 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7e0 | ||
190 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 | ||
191 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 | ||
192 | #define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xf000 | ||
193 | #define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 | ||
194 | #define AR9170_PHY_TIMING_CTRL4_DO_IQCAL 0x10000 | ||
195 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 | ||
196 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 | ||
197 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 | ||
198 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 | ||
199 | |||
200 | #define AR9170_PHY_REG_TIMING5 (AR9170_PHY_REG_BASE + 0x0124) | ||
201 | #define AR9170_PHY_TIMING5_CYCPWR_THR1 0x000000fe | ||
202 | #define AR9170_PHY_TIMING5_CYCPWR_THR1_S 1 | ||
203 | |||
204 | #define AR9170_PHY_REG_POWER_TX_RATE1 (AR9170_PHY_REG_BASE + 0x0134) | ||
205 | #define AR9170_PHY_REG_POWER_TX_RATE2 (AR9170_PHY_REG_BASE + 0x0138) | ||
206 | #define AR9170_PHY_REG_POWER_TX_RATE_MAX (AR9170_PHY_REG_BASE + 0x013c) | ||
207 | #define AR9170_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 | ||
208 | |||
209 | #define AR9170_PHY_REG_FRAME_CTL (AR9170_PHY_REG_BASE + 0x0144) | ||
210 | #define AR9170_PHY_FRAME_CTL_TX_CLIP 0x00000038 | ||
211 | #define AR9170_PHY_FRAME_CTL_TX_CLIP_S 3 | ||
212 | |||
213 | #define AR9170_PHY_REG_SPUR_REG (AR9170_PHY_REG_BASE + 0x014c) | ||
214 | #define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL (0xff << 18) | ||
215 | #define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 | ||
216 | #define AR9170_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 | ||
217 | #define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT (0xff << 9) | ||
218 | #define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 | ||
219 | #define AR9170_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 | ||
220 | #define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7f | ||
221 | #define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 | ||
222 | |||
223 | #define AR9170_PHY_REG_RADAR_EXT (AR9170_PHY_REG_BASE + 0x0140) | ||
224 | #define AR9170_PHY_RADAR_EXT_ENA 0x00004000 | ||
225 | |||
226 | #define AR9170_PHY_REG_RADAR_0 (AR9170_PHY_REG_BASE + 0x0154) | ||
227 | #define AR9170_PHY_RADAR_0_ENA 0x00000001 | ||
228 | #define AR9170_PHY_RADAR_0_FFT_ENA 0x80000000 | ||
229 | /* inband pulse threshold */ | ||
230 | #define AR9170_PHY_RADAR_0_INBAND 0x0000003e | ||
231 | #define AR9170_PHY_RADAR_0_INBAND_S 1 | ||
232 | /* pulse RSSI threshold */ | ||
233 | #define AR9170_PHY_RADAR_0_PRSSI 0x00000fc0 | ||
234 | #define AR9170_PHY_RADAR_0_PRSSI_S 6 | ||
235 | /* pulse height threshold */ | ||
236 | #define AR9170_PHY_RADAR_0_HEIGHT 0x0003f000 | ||
237 | #define AR9170_PHY_RADAR_0_HEIGHT_S 12 | ||
238 | /* radar RSSI threshold */ | ||
239 | #define AR9170_PHY_RADAR_0_RRSSI 0x00fc0000 | ||
240 | #define AR9170_PHY_RADAR_0_RRSSI_S 18 | ||
241 | /* radar firepower threshold */ | ||
242 | #define AR9170_PHY_RADAR_0_FIRPWR 0x7f000000 | ||
243 | #define AR9170_PHY_RADAR_0_FIRPWR_S 24 | ||
244 | |||
245 | #define AR9170_PHY_REG_RADAR_1 (AR9170_PHY_REG_BASE + 0x0158) | ||
246 | #define AR9170_PHY_RADAR_1_RELPWR_ENA 0x00800000 | ||
247 | #define AR9170_PHY_RADAR_1_USE_FIR128 0x00400000 | ||
248 | #define AR9170_PHY_RADAR_1_RELPWR_THRESH 0x003f0000 | ||
249 | #define AR9170_PHY_RADAR_1_RELPWR_THRESH_S 16 | ||
250 | #define AR9170_PHY_RADAR_1_BLOCK_CHECK 0x00008000 | ||
251 | #define AR9170_PHY_RADAR_1_MAX_RRSSI 0x00004000 | ||
252 | #define AR9170_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 | ||
253 | #define AR9170_PHY_RADAR_1_RELSTEP_THRESH 0x00001f00 | ||
254 | #define AR9170_PHY_RADAR_1_RELSTEP_THRESH_S 8 | ||
255 | #define AR9170_PHY_RADAR_1_MAXLEN 0x000000ff | ||
256 | #define AR9170_PHY_RADAR_1_MAXLEN_S 0 | ||
257 | |||
258 | #define AR9170_PHY_REG_SWITCH_CHAIN_0 (AR9170_PHY_REG_BASE + 0x0160) | ||
259 | #define AR9170_PHY_REG_SWITCH_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2160) | ||
260 | |||
261 | #define AR9170_PHY_REG_SWITCH_COM (AR9170_PHY_REG_BASE + 0x0164) | ||
262 | |||
263 | #define AR9170_PHY_REG_CCA_THRESHOLD (AR9170_PHY_REG_BASE + 0x0168) | ||
264 | |||
265 | #define AR9170_PHY_REG_SIGMA_DELTA (AR9170_PHY_REG_BASE + 0x016c) | ||
266 | #define AR9170_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 | ||
267 | #define AR9170_PHY_SIGMA_DELTA_ADC_SEL_S 0 | ||
268 | #define AR9170_PHY_SIGMA_DELTA_FILT2 0x000000f8 | ||
269 | #define AR9170_PHY_SIGMA_DELTA_FILT2_S 3 | ||
270 | #define AR9170_PHY_SIGMA_DELTA_FILT1 0x00001f00 | ||
271 | #define AR9170_PHY_SIGMA_DELTA_FILT1_S 8 | ||
272 | #define AR9170_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000 | ||
273 | #define AR9170_PHY_SIGMA_DELTA_ADC_CLIP_S 13 | ||
274 | |||
275 | #define AR9170_PHY_REG_RESTART (AR9170_PHY_REG_BASE + 0x0170) | ||
276 | #define AR9170_PHY_RESTART_DIV_GC 0x001c0000 | ||
277 | #define AR9170_PHY_RESTART_DIV_GC_S 18 | ||
278 | |||
279 | #define AR9170_PHY_REG_RFBUS_REQ (AR9170_PHY_REG_BASE + 0x017c) | ||
280 | #define AR9170_PHY_RFBUS_REQ_EN 0x00000001 | ||
281 | |||
282 | #define AR9170_PHY_REG_TIMING7 (AR9170_PHY_REG_BASE + 0x0180) | ||
283 | #define AR9170_PHY_REG_TIMING8 (AR9170_PHY_REG_BASE + 0x0184) | ||
284 | #define AR9170_PHY_TIMING8_PILOT_MASK_2 0x000fffff | ||
285 | #define AR9170_PHY_TIMING8_PILOT_MASK_2_S 0 | ||
286 | |||
287 | #define AR9170_PHY_REG_BIN_MASK2_1 (AR9170_PHY_REG_BASE + 0x0188) | ||
288 | #define AR9170_PHY_REG_BIN_MASK2_2 (AR9170_PHY_REG_BASE + 0x018c) | ||
289 | #define AR9170_PHY_REG_BIN_MASK2_3 (AR9170_PHY_REG_BASE + 0x0190) | ||
290 | #define AR9170_PHY_REG_BIN_MASK2_4 (AR9170_PHY_REG_BASE + 0x0194) | ||
291 | #define AR9170_PHY_BIN_MASK2_4_MASK_4 0x00003fff | ||
292 | #define AR9170_PHY_BIN_MASK2_4_MASK_4_S 0 | ||
293 | |||
294 | #define AR9170_PHY_REG_TIMING9 (AR9170_PHY_REG_BASE + 0x0198) | ||
295 | #define AR9170_PHY_REG_TIMING10 (AR9170_PHY_REG_BASE + 0x019c) | ||
296 | #define AR9170_PHY_TIMING10_PILOT_MASK_2 0x000fffff | ||
297 | #define AR9170_PHY_TIMING10_PILOT_MASK_2_S 0 | ||
298 | |||
299 | #define AR9170_PHY_REG_TIMING11 (AR9170_PHY_REG_BASE + 0x01a0) | ||
300 | #define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE 0x000fffff | ||
301 | #define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 | ||
302 | #define AR9170_PHY_TIMING11_SPUR_FREQ_SD 0x3ff00000 | ||
303 | #define AR9170_PHY_TIMING11_SPUR_FREQ_SD_S 20 | ||
304 | #define AR9170_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 | ||
305 | #define AR9170_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 | ||
306 | |||
307 | #define AR9170_PHY_REG_RX_CHAINMASK (AR9170_PHY_REG_BASE + 0x01a4) | ||
308 | #define AR9170_PHY_REG_NEW_ADC_DC_GAIN_CORR(_i) (AR9170_PHY_REG_BASE + \ | ||
309 | 0x01b4 + ((_i) << 12)) | ||
310 | #define AR9170_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 | ||
311 | #define AR9170_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | ||
312 | |||
313 | #define AR9170_PHY_REG_MULTICHAIN_GAIN_CTL (AR9170_PHY_REG_BASE + 0x01ac) | ||
314 | #define AR9170_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | ||
315 | #define AR9170_PHY_9285_ANT_DIV_CTL 0x01000000 | ||
316 | #define AR9170_PHY_9285_ANT_DIV_CTL_S 24 | ||
317 | #define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 | ||
318 | #define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 | ||
319 | #define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 | ||
320 | #define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 | ||
321 | #define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 | ||
322 | #define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 | ||
323 | #define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 | ||
324 | #define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 | ||
325 | #define AR9170_PHY_9285_ANT_DIV_LNA1 2 | ||
326 | #define AR9170_PHY_9285_ANT_DIV_LNA2 1 | ||
327 | #define AR9170_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 | ||
328 | #define AR9170_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 | ||
329 | #define AR9170_PHY_9285_ANT_DIV_GAINTB_0 0 | ||
330 | #define AR9170_PHY_9285_ANT_DIV_GAINTB_1 1 | ||
331 | |||
332 | #define AR9170_PHY_REG_EXT_CCA0 (AR9170_PHY_REG_BASE + 0x01b8) | ||
333 | #define AR9170_PHY_REG_EXT_CCA0_THRESH62 0x000000ff | ||
334 | #define AR9170_PHY_REG_EXT_CCA0_THRESH62_S 0 | ||
335 | |||
336 | #define AR9170_PHY_REG_EXT_CCA (AR9170_PHY_REG_BASE + 0x01bc) | ||
337 | #define AR9170_PHY_EXT_CCA_CYCPWR_THR1 0x0000fe00 | ||
338 | #define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9 | ||
339 | #define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000 | ||
340 | #define AR9170_PHY_EXT_CCA_THRESH62_S 16 | ||
341 | #define AR9170_PHY_EXT_MINCCA_PWR 0xff800000 | ||
342 | #define AR9170_PHY_EXT_MINCCA_PWR_S 23 | ||
343 | |||
344 | #define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0) | ||
345 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f | ||
346 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_S 0 | ||
347 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH 0x00003f80 | ||
348 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_S 7 | ||
349 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001fc000 | ||
350 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 | ||
351 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0fe00000 | ||
352 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 | ||
353 | #define AR9170_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 | ||
354 | |||
355 | #define AR9170_PHY_REG_HALFGI (AR9170_PHY_REG_BASE + 0x01d0) | ||
356 | #define AR9170_PHY_HALFGI_DSC_MAN 0x0007fff0 | ||
357 | #define AR9170_PHY_HALFGI_DSC_MAN_S 4 | ||
358 | #define AR9170_PHY_HALFGI_DSC_EXP 0x0000000f | ||
359 | #define AR9170_PHY_HALFGI_DSC_EXP_S 0 | ||
360 | |||
361 | #define AR9170_PHY_REG_CHANNEL_MASK_01_30 (AR9170_PHY_REG_BASE + 0x01d4) | ||
362 | #define AR9170_PHY_REG_CHANNEL_MASK_31_60 (AR9170_PHY_REG_BASE + 0x01d8) | ||
363 | |||
364 | #define AR9170_PHY_REG_CHAN_INFO_MEMORY (AR9170_PHY_REG_BASE + 0x01dc) | ||
365 | #define AR9170_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 | ||
366 | |||
367 | #define AR9170_PHY_REG_HEAVY_CLIP_ENABLE (AR9170_PHY_REG_BASE + 0x01e0) | ||
368 | #define AR9170_PHY_REG_HEAVY_CLIP_FACTOR_RIFS (AR9170_PHY_REG_BASE + 0x01ec) | ||
369 | #define AR9170_PHY_RIFS_INIT_DELAY 0x03ff0000 | ||
370 | |||
371 | #define AR9170_PHY_REG_CALMODE (AR9170_PHY_REG_BASE + 0x01f0) | ||
372 | #define AR9170_PHY_CALMODE_IQ 0x00000000 | ||
373 | #define AR9170_PHY_CALMODE_ADC_GAIN 0x00000001 | ||
374 | #define AR9170_PHY_CALMODE_ADC_DC_PER 0x00000002 | ||
375 | #define AR9170_PHY_CALMODE_ADC_DC_INIT 0x00000003 | ||
376 | |||
377 | #define AR9170_PHY_REG_REFCLKDLY (AR9170_PHY_REG_BASE + 0x01f4) | ||
378 | #define AR9170_PHY_REG_REFCLKPD (AR9170_PHY_REG_BASE + 0x01f8) | ||
379 | |||
380 | |||
381 | #define AR9170_PHY_REG_CAL_MEAS_0(_i) (AR9170_PHY_REG_BASE + \ | ||
382 | 0x0410 + ((_i) << 12)) | ||
383 | #define AR9170_PHY_REG_CAL_MEAS_1(_i) (AR9170_PHY_REG_BASE + \ | ||
384 | 0x0414 \ + ((_i) << 12)) | ||
385 | #define AR9170_PHY_REG_CAL_MEAS_2(_i) (AR9170_PHY_REG_BASE + \ | ||
386 | 0x0418 + ((_i) << 12)) | ||
387 | #define AR9170_PHY_REG_CAL_MEAS_3(_i) (AR9170_PHY_REG_BASE + \ | ||
388 | 0x041c + ((_i) << 12)) | ||
389 | |||
390 | #define AR9170_PHY_REG_CURRENT_RSSI (AR9170_PHY_REG_BASE + 0x041c) | ||
391 | |||
392 | #define AR9170_PHY_REG_RFBUS_GRANT (AR9170_PHY_REG_BASE + 0x0420) | ||
393 | #define AR9170_PHY_RFBUS_GRANT_EN 0x00000001 | ||
394 | |||
395 | #define AR9170_PHY_REG_CHAN_INFO_GAIN_DIFF (AR9170_PHY_REG_BASE + 0x04f4) | ||
396 | #define AR9170_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 | ||
397 | |||
398 | #define AR9170_PHY_REG_CHAN_INFO_GAIN (AR9170_PHY_REG_BASE + 0x04fc) | ||
399 | |||
400 | #define AR9170_PHY_REG_MODE (AR9170_PHY_REG_BASE + 0x0a00) | ||
401 | #define AR9170_PHY_MODE_ASYNCFIFO 0x80 | ||
402 | #define AR9170_PHY_MODE_AR2133 0x08 | ||
403 | #define AR9170_PHY_MODE_AR5111 0x00 | ||
404 | #define AR9170_PHY_MODE_AR5112 0x08 | ||
405 | #define AR9170_PHY_MODE_DYNAMIC 0x04 | ||
406 | #define AR9170_PHY_MODE_RF2GHZ 0x02 | ||
407 | #define AR9170_PHY_MODE_RF5GHZ 0x00 | ||
408 | #define AR9170_PHY_MODE_CCK 0x01 | ||
409 | #define AR9170_PHY_MODE_OFDM 0x00 | ||
410 | #define AR9170_PHY_MODE_DYN_CCK_DISABLE 0x100 | ||
411 | |||
412 | #define AR9170_PHY_REG_CCK_TX_CTRL (AR9170_PHY_REG_BASE + 0x0a04) | ||
413 | #define AR9170_PHY_CCK_TX_CTRL_JAPAN 0x00000010 | ||
414 | #define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000c | ||
415 | #define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 | ||
416 | |||
417 | #define AR9170_PHY_REG_CCK_DETECT (AR9170_PHY_REG_BASE + 0x0a08) | ||
418 | #define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003f | ||
419 | #define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 | ||
420 | /* [12:6] settling time for antenna switch */ | ||
421 | #define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001fc0 | ||
422 | #define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 | ||
423 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 | ||
424 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 | ||
425 | |||
426 | #define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c) | ||
427 | #define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c) | ||
428 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000 | ||
429 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 | ||
430 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00 | ||
431 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 | ||
432 | #define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001f | ||
433 | #define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 | ||
434 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003e0000 | ||
435 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 | ||
436 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001f000 | ||
437 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 | ||
438 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000fc0 | ||
439 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 | ||
440 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003f | ||
441 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 | ||
442 | |||
443 | #define AR9170_PHY_REG_CCK_RXCTRL4 (AR9170_PHY_REG_BASE + 0x0a1c) | ||
444 | #define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01f80000 | ||
445 | #define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 | ||
446 | |||
447 | #define AR9170_PHY_REG_DAG_CTRLCCK (AR9170_PHY_REG_BASE + 0x0a28) | ||
448 | #define AR9170_REG_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 | ||
449 | #define AR9170_REG_DAG_CTRLCCK_RSSI_THR 0x0001fc00 | ||
450 | #define AR9170_REG_DAG_CTRLCCK_RSSI_THR_S 10 | ||
451 | |||
452 | #define AR9170_PHY_REG_FORCE_CLKEN_CCK (AR9170_PHY_REG_BASE + 0x0a2c) | ||
453 | #define AR9170_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 | ||
454 | |||
455 | #define AR9170_PHY_REG_POWER_TX_RATE3 (AR9170_PHY_REG_BASE + 0x0a34) | ||
456 | #define AR9170_PHY_REG_POWER_TX_RATE4 (AR9170_PHY_REG_BASE + 0x0a38) | ||
457 | |||
458 | #define AR9170_PHY_REG_SCRM_SEQ_XR (AR9170_PHY_REG_BASE + 0x0a3c) | ||
459 | #define AR9170_PHY_REG_HEADER_DETECT_XR (AR9170_PHY_REG_BASE + 0x0a40) | ||
460 | #define AR9170_PHY_REG_CHIRP_DETECTED_XR (AR9170_PHY_REG_BASE + 0x0a44) | ||
461 | #define AR9170_PHY_REG_BLUETOOTH (AR9170_PHY_REG_BASE + 0x0a54) | ||
462 | |||
463 | #define AR9170_PHY_REG_TPCRG1 (AR9170_PHY_REG_BASE + 0x0a58) | ||
464 | #define AR9170_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 | ||
465 | #define AR9170_PHY_TPCRG1_NUM_PD_GAIN_S 14 | ||
466 | #define AR9170_PHY_TPCRG1_PD_GAIN_1 0x00030000 | ||
467 | #define AR9170_PHY_TPCRG1_PD_GAIN_1_S 16 | ||
468 | #define AR9170_PHY_TPCRG1_PD_GAIN_2 0x000c0000 | ||
469 | #define AR9170_PHY_TPCRG1_PD_GAIN_2_S 18 | ||
470 | #define AR9170_PHY_TPCRG1_PD_GAIN_3 0x00300000 | ||
471 | #define AR9170_PHY_TPCRG1_PD_GAIN_3_S 20 | ||
472 | #define AR9170_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 | ||
473 | #define AR9170_PHY_TPCRG1_PD_CAL_ENABLE_S 22 | ||
474 | |||
475 | #define AR9170_PHY_REG_TX_PWRCTRL4 (AR9170_PHY_REG_BASE + 0x0a64) | ||
476 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 | ||
477 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 | ||
478 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001fe | ||
479 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 | ||
480 | |||
481 | #define AR9170_PHY_REG_ANALOG_SWAP (AR9170_PHY_REG_BASE + 0x0a68) | ||
482 | #define AR9170_PHY_ANALOG_SWAP_AB 0x0001 | ||
483 | #define AR9170_PHY_ANALOG_SWAP_ALT_CHAIN 0x00000040 | ||
484 | |||
485 | #define AR9170_PHY_REG_TPCRG5 (AR9170_PHY_REG_BASE + 0x0a6c) | ||
486 | #define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000f | ||
487 | #define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 | ||
488 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003f0 | ||
489 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 | ||
490 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000fc00 | ||
491 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 | ||
492 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003f0000 | ||
493 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 | ||
494 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0fc00000 | ||
495 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 | ||
496 | |||
497 | #define AR9170_PHY_REG_TX_PWRCTRL6_0 (AR9170_PHY_REG_BASE + 0x0a70) | ||
498 | #define AR9170_PHY_REG_TX_PWRCTRL6_1 (AR9170_PHY_REG_BASE + 0x1a70) | ||
499 | #define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 | ||
500 | #define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 | ||
501 | |||
502 | #define AR9170_PHY_REG_TX_PWRCTRL7 (AR9170_PHY_REG_BASE + 0x0a74) | ||
503 | #define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01f80000 | ||
504 | #define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | ||
505 | |||
506 | #define AR9170_PHY_REG_TX_PWRCTRL9 (AR9170_PHY_REG_BASE + 0x0a7c) | ||
507 | #define AR9170_PHY_TX_DESIRED_SCALE_CCK 0x00007c00 | ||
508 | #define AR9170_PHY_TX_DESIRED_SCALE_CCK_S 10 | ||
509 | #define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 | ||
510 | #define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 | ||
511 | |||
512 | #define AR9170_PHY_REG_TX_GAIN_TBL1 (AR9170_PHY_REG_BASE + 0x0b00) | ||
513 | #define AR9170_PHY_TX_GAIN 0x0007f000 | ||
514 | #define AR9170_PHY_TX_GAIN_S 12 | ||
515 | |||
516 | /* Carrier leak calibration control, do it after AGC calibration */ | ||
517 | #define AR9170_PHY_REG_CL_CAL_CTL (AR9170_PHY_REG_BASE + 0x0b58) | ||
518 | #define AR9170_PHY_CL_CAL_ENABLE 0x00000002 | ||
519 | #define AR9170_PHY_CL_CAL_PARALLEL_CAL_ENABLE 0x00000001 | ||
520 | |||
521 | #define AR9170_PHY_REG_POWER_TX_RATE5 (AR9170_PHY_REG_BASE + 0x0b8c) | ||
522 | #define AR9170_PHY_REG_POWER_TX_RATE6 (AR9170_PHY_REG_BASE + 0x0b90) | ||
523 | |||
524 | #define AR9170_PHY_REG_CH0_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x0b98) | ||
525 | #define AR9170_PHY_REG_CH1_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x1b98) | ||
526 | #define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP 0x0000fc00 | ||
527 | #define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP_S 10 | ||
528 | |||
529 | #define AR9170_PHY_REG_CAL_CHAINMASK (AR9170_PHY_REG_BASE + 0x0b9c) | ||
530 | #define AR9170_PHY_REG_VIT_MASK2_M_46_61 (AR9170_PHY_REG_BASE + 0x0ba0) | ||
531 | #define AR9170_PHY_REG_MASK2_M_31_45 (AR9170_PHY_REG_BASE + 0x0ba4) | ||
532 | #define AR9170_PHY_REG_MASK2_M_16_30 (AR9170_PHY_REG_BASE + 0x0ba8) | ||
533 | #define AR9170_PHY_REG_MASK2_M_00_15 (AR9170_PHY_REG_BASE + 0x0bac) | ||
534 | #define AR9170_PHY_REG_PILOT_MASK_01_30 (AR9170_PHY_REG_BASE + 0x0bb0) | ||
535 | #define AR9170_PHY_REG_PILOT_MASK_31_60 (AR9170_PHY_REG_BASE + 0x0bb4) | ||
536 | #define AR9170_PHY_REG_MASK2_P_15_01 (AR9170_PHY_REG_BASE + 0x0bb8) | ||
537 | #define AR9170_PHY_REG_MASK2_P_30_16 (AR9170_PHY_REG_BASE + 0x0bbc) | ||
538 | #define AR9170_PHY_REG_MASK2_P_45_31 (AR9170_PHY_REG_BASE + 0x0bc0) | ||
539 | #define AR9170_PHY_REG_MASK2_P_61_45 (AR9170_PHY_REG_BASE + 0x0bc4) | ||
540 | #define AR9170_PHY_REG_POWER_TX_SUB (AR9170_PHY_REG_BASE + 0x0bc8) | ||
541 | #define AR9170_PHY_REG_POWER_TX_RATE7 (AR9170_PHY_REG_BASE + 0x0bcc) | ||
542 | #define AR9170_PHY_REG_POWER_TX_RATE8 (AR9170_PHY_REG_BASE + 0x0bd0) | ||
543 | #define AR9170_PHY_REG_POWER_TX_RATE9 (AR9170_PHY_REG_BASE + 0x0bd4) | ||
544 | #define AR9170_PHY_REG_XPA_CFG (AR9170_PHY_REG_BASE + 0x0bd8) | ||
545 | #define AR9170_PHY_FORCE_XPA_CFG 0x000000001 | ||
546 | #define AR9170_PHY_FORCE_XPA_CFG_S 0 | ||
547 | |||
548 | #define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064) | ||
549 | #define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000 | ||
550 | #define AR9170_PHY_CH1_MINCCA_PWR_S 19 | ||
551 | |||
552 | #define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064) | ||
553 | #define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000 | ||
554 | #define AR9170_PHY_CH2_MINCCA_PWR_S 19 | ||
555 | |||
556 | #define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc) | ||
557 | #define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000 | ||
558 | #define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23 | ||
559 | |||
560 | #define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc) | ||
561 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 | ||
562 | #define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 | ||
563 | |||
564 | #define REDUCE_CHAIN_0 0x00000050 | ||
565 | #define REDUCE_CHAIN_1 0x00000051 | ||
566 | |||
567 | #endif /* __CARL9170_SHARED_PHY_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c new file mode 100644 index 000000000000..671dbc429547 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -0,0 +1,909 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * 802.11 & command trap routines | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <linux/crc32.h> | ||
45 | #include <net/mac80211.h> | ||
46 | #include "carl9170.h" | ||
47 | #include "hw.h" | ||
48 | #include "cmd.h" | ||
49 | |||
50 | static void carl9170_dbg_message(struct ar9170 *ar, const char *buf, u32 len) | ||
51 | { | ||
52 | bool restart = false; | ||
53 | enum carl9170_restart_reasons reason = CARL9170_RR_NO_REASON; | ||
54 | |||
55 | if (len > 3) { | ||
56 | if (memcmp(buf, CARL9170_ERR_MAGIC, 3) == 0) { | ||
57 | ar->fw.err_counter++; | ||
58 | if (ar->fw.err_counter > 3) { | ||
59 | restart = true; | ||
60 | reason = CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | if (memcmp(buf, CARL9170_BUG_MAGIC, 3) == 0) { | ||
65 | ar->fw.bug_counter++; | ||
66 | restart = true; | ||
67 | reason = CARL9170_RR_FATAL_FIRMWARE_ERROR; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | wiphy_info(ar->hw->wiphy, "FW: %.*s\n", len, buf); | ||
72 | |||
73 | if (restart) | ||
74 | carl9170_restart(ar, reason); | ||
75 | } | ||
76 | |||
77 | static void carl9170_handle_ps(struct ar9170 *ar, struct carl9170_rsp *rsp) | ||
78 | { | ||
79 | u32 ps; | ||
80 | bool new_ps; | ||
81 | |||
82 | ps = le32_to_cpu(rsp->psm.state); | ||
83 | |||
84 | new_ps = (ps & CARL9170_PSM_COUNTER) != CARL9170_PSM_WAKE; | ||
85 | if (ar->ps.state != new_ps) { | ||
86 | if (!new_ps) { | ||
87 | ar->ps.sleep_ms = jiffies_to_msecs(jiffies - | ||
88 | ar->ps.last_action); | ||
89 | } | ||
90 | |||
91 | ar->ps.last_action = jiffies; | ||
92 | |||
93 | ar->ps.state = new_ps; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq) | ||
98 | { | ||
99 | if (ar->cmd_seq < -1) | ||
100 | return 0; | ||
101 | |||
102 | /* | ||
103 | * Initialize Counter | ||
104 | */ | ||
105 | if (ar->cmd_seq < 0) | ||
106 | ar->cmd_seq = seq; | ||
107 | |||
108 | /* | ||
109 | * The sequence is strictly monotonic increasing and it never skips! | ||
110 | * | ||
111 | * Therefore we can safely assume that whenever we received an | ||
112 | * unexpected sequence we have lost some valuable data. | ||
113 | */ | ||
114 | if (seq != ar->cmd_seq) { | ||
115 | int count; | ||
116 | |||
117 | count = (seq - ar->cmd_seq) % ar->fw.cmd_bufs; | ||
118 | |||
119 | wiphy_err(ar->hw->wiphy, "lost %d command responses/traps! " | ||
120 | "w:%d g:%d\n", count, ar->cmd_seq, seq); | ||
121 | |||
122 | carl9170_restart(ar, CARL9170_RR_LOST_RSP); | ||
123 | return -EIO; | ||
124 | } | ||
125 | |||
126 | ar->cmd_seq = (ar->cmd_seq + 1) % ar->fw.cmd_bufs; | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) | ||
131 | { | ||
132 | /* | ||
133 | * Some commands may have a variable response length | ||
134 | * and we cannot predict the correct length in advance. | ||
135 | * So we only check if we provided enough space for the data. | ||
136 | */ | ||
137 | if (unlikely(ar->readlen != (len - 4))) { | ||
138 | dev_warn(&ar->udev->dev, "received invalid command response:" | ||
139 | "got %d, instead of %d\n", len - 4, ar->readlen); | ||
140 | print_hex_dump_bytes("carl9170 cmd:", DUMP_PREFIX_OFFSET, | ||
141 | ar->cmd_buf, (ar->cmd.hdr.len + 4) & 0x3f); | ||
142 | print_hex_dump_bytes("carl9170 rsp:", DUMP_PREFIX_OFFSET, | ||
143 | buffer, len); | ||
144 | /* | ||
145 | * Do not complete. The command times out, | ||
146 | * and we get a stack trace from there. | ||
147 | */ | ||
148 | carl9170_restart(ar, CARL9170_RR_INVALID_RSP); | ||
149 | } | ||
150 | |||
151 | spin_lock(&ar->cmd_lock); | ||
152 | if (ar->readbuf) { | ||
153 | if (len >= 4) | ||
154 | memcpy(ar->readbuf, buffer + 4, len - 4); | ||
155 | |||
156 | ar->readbuf = NULL; | ||
157 | } | ||
158 | complete(&ar->cmd_wait); | ||
159 | spin_unlock(&ar->cmd_lock); | ||
160 | } | ||
161 | |||
162 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | ||
163 | { | ||
164 | struct carl9170_rsp *cmd = (void *) buf; | ||
165 | struct ieee80211_vif *vif; | ||
166 | |||
167 | if (carl9170_check_sequence(ar, cmd->hdr.seq)) | ||
168 | return; | ||
169 | |||
170 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { | ||
171 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) | ||
172 | carl9170_cmd_callback(ar, len, buf); | ||
173 | |||
174 | return; | ||
175 | } | ||
176 | |||
177 | if (unlikely(cmd->hdr.len != (len - 4))) { | ||
178 | if (net_ratelimit()) { | ||
179 | wiphy_err(ar->hw->wiphy, "FW: received over-/under" | ||
180 | "sized event %x (%d, but should be %d).\n", | ||
181 | cmd->hdr.cmd, cmd->hdr.len, len - 4); | ||
182 | |||
183 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, | ||
184 | buf, len); | ||
185 | } | ||
186 | |||
187 | return; | ||
188 | } | ||
189 | |||
190 | /* hardware event handlers */ | ||
191 | switch (cmd->hdr.cmd) { | ||
192 | case CARL9170_RSP_PRETBTT: | ||
193 | /* pre-TBTT event */ | ||
194 | rcu_read_lock(); | ||
195 | vif = carl9170_get_main_vif(ar); | ||
196 | |||
197 | if (!vif) { | ||
198 | rcu_read_unlock(); | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | switch (vif->type) { | ||
203 | case NL80211_IFTYPE_STATION: | ||
204 | carl9170_handle_ps(ar, cmd); | ||
205 | break; | ||
206 | |||
207 | case NL80211_IFTYPE_AP: | ||
208 | case NL80211_IFTYPE_ADHOC: | ||
209 | carl9170_update_beacon(ar, true); | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | break; | ||
214 | } | ||
215 | rcu_read_unlock(); | ||
216 | |||
217 | break; | ||
218 | |||
219 | |||
220 | case CARL9170_RSP_TXCOMP: | ||
221 | /* TX status notification */ | ||
222 | carl9170_tx_process_status(ar, cmd); | ||
223 | break; | ||
224 | |||
225 | case CARL9170_RSP_BEACON_CONFIG: | ||
226 | /* | ||
227 | * (IBSS) beacon send notification | ||
228 | * bytes: 04 c2 XX YY B4 B3 B2 B1 | ||
229 | * | ||
230 | * XX always 80 | ||
231 | * YY always 00 | ||
232 | * B1-B4 "should" be the number of send out beacons. | ||
233 | */ | ||
234 | break; | ||
235 | |||
236 | case CARL9170_RSP_ATIM: | ||
237 | /* End of Atim Window */ | ||
238 | break; | ||
239 | |||
240 | case CARL9170_RSP_WATCHDOG: | ||
241 | /* Watchdog Interrupt */ | ||
242 | carl9170_restart(ar, CARL9170_RR_WATCHDOG); | ||
243 | break; | ||
244 | |||
245 | case CARL9170_RSP_TEXT: | ||
246 | /* firmware debug */ | ||
247 | carl9170_dbg_message(ar, (char *)buf + 4, len - 4); | ||
248 | break; | ||
249 | |||
250 | case CARL9170_RSP_HEXDUMP: | ||
251 | wiphy_dbg(ar->hw->wiphy, "FW: HD %d\n", len - 4); | ||
252 | print_hex_dump_bytes("FW:", DUMP_PREFIX_NONE, | ||
253 | (char *)buf + 4, len - 4); | ||
254 | break; | ||
255 | |||
256 | case CARL9170_RSP_RADAR: | ||
257 | if (!net_ratelimit()) | ||
258 | break; | ||
259 | |||
260 | wiphy_info(ar->hw->wiphy, "FW: RADAR! Please report this " | ||
261 | "incident to linux-wireless@vger.kernel.org !\n"); | ||
262 | break; | ||
263 | |||
264 | case CARL9170_RSP_GPIO: | ||
265 | #ifdef CONFIG_CARL9170_WPC | ||
266 | if (ar->wps.pbc) { | ||
267 | bool state = !!(cmd->gpio.gpio & cpu_to_le32( | ||
268 | AR9170_GPIO_PORT_WPS_BUTTON_PRESSED)); | ||
269 | |||
270 | if (state != ar->wps.pbc_state) { | ||
271 | ar->wps.pbc_state = state; | ||
272 | input_report_key(ar->wps.pbc, KEY_WPS_BUTTON, | ||
273 | state); | ||
274 | input_sync(ar->wps.pbc); | ||
275 | } | ||
276 | } | ||
277 | #endif /* CONFIG_CARL9170_WPC */ | ||
278 | break; | ||
279 | |||
280 | case CARL9170_RSP_BOOT: | ||
281 | complete(&ar->fw_boot_wait); | ||
282 | break; | ||
283 | |||
284 | default: | ||
285 | wiphy_err(ar->hw->wiphy, "FW: received unhandled event %x\n", | ||
286 | cmd->hdr.cmd); | ||
287 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); | ||
288 | break; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | static int carl9170_rx_mac_status(struct ar9170 *ar, | ||
293 | struct ar9170_rx_head *head, struct ar9170_rx_macstatus *mac, | ||
294 | struct ieee80211_rx_status *status) | ||
295 | { | ||
296 | struct ieee80211_channel *chan; | ||
297 | u8 error, decrypt; | ||
298 | |||
299 | BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); | ||
300 | BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); | ||
301 | |||
302 | error = mac->error; | ||
303 | |||
304 | if (error & AR9170_RX_ERROR_WRONG_RA) { | ||
305 | if (!ar->sniffer_enabled) | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | if (error & AR9170_RX_ERROR_PLCP) { | ||
310 | if (!(ar->filter_state & FIF_PLCPFAIL)) | ||
311 | return -EINVAL; | ||
312 | |||
313 | status->flag |= RX_FLAG_FAILED_PLCP_CRC; | ||
314 | } | ||
315 | |||
316 | if (error & AR9170_RX_ERROR_FCS) { | ||
317 | ar->tx_fcs_errors++; | ||
318 | |||
319 | if (!(ar->filter_state & FIF_FCSFAIL)) | ||
320 | return -EINVAL; | ||
321 | |||
322 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
323 | } | ||
324 | |||
325 | decrypt = ar9170_get_decrypt_type(mac); | ||
326 | if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && | ||
327 | decrypt != AR9170_ENC_ALG_NONE) { | ||
328 | if ((decrypt == AR9170_ENC_ALG_TKIP) && | ||
329 | (error & AR9170_RX_ERROR_MMIC)) | ||
330 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
331 | |||
332 | status->flag |= RX_FLAG_DECRYPTED; | ||
333 | } | ||
334 | |||
335 | if (error & AR9170_RX_ERROR_DECRYPT && !ar->sniffer_enabled) | ||
336 | return -ENODATA; | ||
337 | |||
338 | error &= ~(AR9170_RX_ERROR_MMIC | | ||
339 | AR9170_RX_ERROR_FCS | | ||
340 | AR9170_RX_ERROR_WRONG_RA | | ||
341 | AR9170_RX_ERROR_DECRYPT | | ||
342 | AR9170_RX_ERROR_PLCP); | ||
343 | |||
344 | /* drop any other error frames */ | ||
345 | if (unlikely(error)) { | ||
346 | /* TODO: update netdevice's RX dropped/errors statistics */ | ||
347 | |||
348 | if (net_ratelimit()) | ||
349 | wiphy_dbg(ar->hw->wiphy, "received frame with " | ||
350 | "suspicious error code (%#x).\n", error); | ||
351 | |||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | chan = ar->channel; | ||
356 | if (chan) { | ||
357 | status->band = chan->band; | ||
358 | status->freq = chan->center_freq; | ||
359 | } | ||
360 | |||
361 | switch (mac->status & AR9170_RX_STATUS_MODULATION) { | ||
362 | case AR9170_RX_STATUS_MODULATION_CCK: | ||
363 | if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) | ||
364 | status->flag |= RX_FLAG_SHORTPRE; | ||
365 | switch (head->plcp[0]) { | ||
366 | case AR9170_RX_PHY_RATE_CCK_1M: | ||
367 | status->rate_idx = 0; | ||
368 | break; | ||
369 | case AR9170_RX_PHY_RATE_CCK_2M: | ||
370 | status->rate_idx = 1; | ||
371 | break; | ||
372 | case AR9170_RX_PHY_RATE_CCK_5M: | ||
373 | status->rate_idx = 2; | ||
374 | break; | ||
375 | case AR9170_RX_PHY_RATE_CCK_11M: | ||
376 | status->rate_idx = 3; | ||
377 | break; | ||
378 | default: | ||
379 | if (net_ratelimit()) { | ||
380 | wiphy_err(ar->hw->wiphy, "invalid plcp cck " | ||
381 | "rate (%x).\n", head->plcp[0]); | ||
382 | } | ||
383 | |||
384 | return -EINVAL; | ||
385 | } | ||
386 | break; | ||
387 | |||
388 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
389 | case AR9170_RX_STATUS_MODULATION_OFDM: | ||
390 | switch (head->plcp[0] & 0xf) { | ||
391 | case AR9170_TXRX_PHY_RATE_OFDM_6M: | ||
392 | status->rate_idx = 0; | ||
393 | break; | ||
394 | case AR9170_TXRX_PHY_RATE_OFDM_9M: | ||
395 | status->rate_idx = 1; | ||
396 | break; | ||
397 | case AR9170_TXRX_PHY_RATE_OFDM_12M: | ||
398 | status->rate_idx = 2; | ||
399 | break; | ||
400 | case AR9170_TXRX_PHY_RATE_OFDM_18M: | ||
401 | status->rate_idx = 3; | ||
402 | break; | ||
403 | case AR9170_TXRX_PHY_RATE_OFDM_24M: | ||
404 | status->rate_idx = 4; | ||
405 | break; | ||
406 | case AR9170_TXRX_PHY_RATE_OFDM_36M: | ||
407 | status->rate_idx = 5; | ||
408 | break; | ||
409 | case AR9170_TXRX_PHY_RATE_OFDM_48M: | ||
410 | status->rate_idx = 6; | ||
411 | break; | ||
412 | case AR9170_TXRX_PHY_RATE_OFDM_54M: | ||
413 | status->rate_idx = 7; | ||
414 | break; | ||
415 | default: | ||
416 | if (net_ratelimit()) { | ||
417 | wiphy_err(ar->hw->wiphy, "invalid plcp ofdm " | ||
418 | "rate (%x).\n", head->plcp[0]); | ||
419 | } | ||
420 | |||
421 | return -EINVAL; | ||
422 | } | ||
423 | if (status->band == IEEE80211_BAND_2GHZ) | ||
424 | status->rate_idx += 4; | ||
425 | break; | ||
426 | |||
427 | case AR9170_RX_STATUS_MODULATION_HT: | ||
428 | if (head->plcp[3] & 0x80) | ||
429 | status->flag |= RX_FLAG_40MHZ; | ||
430 | if (head->plcp[6] & 0x80) | ||
431 | status->flag |= RX_FLAG_SHORT_GI; | ||
432 | |||
433 | status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f); | ||
434 | status->flag |= RX_FLAG_HT; | ||
435 | break; | ||
436 | |||
437 | default: | ||
438 | BUG(); | ||
439 | return -ENOSYS; | ||
440 | } | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static void carl9170_rx_phy_status(struct ar9170 *ar, | ||
446 | struct ar9170_rx_phystatus *phy, struct ieee80211_rx_status *status) | ||
447 | { | ||
448 | int i; | ||
449 | |||
450 | BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); | ||
451 | |||
452 | for (i = 0; i < 3; i++) | ||
453 | if (phy->rssi[i] != 0x80) | ||
454 | status->antenna |= BIT(i); | ||
455 | |||
456 | /* post-process RSSI */ | ||
457 | for (i = 0; i < 7; i++) | ||
458 | if (phy->rssi[i] & 0x80) | ||
459 | phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; | ||
460 | |||
461 | /* TODO: we could do something with phy_errors */ | ||
462 | status->signal = ar->noise[0] + phy->rssi_combined; | ||
463 | } | ||
464 | |||
465 | static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len) | ||
466 | { | ||
467 | struct sk_buff *skb; | ||
468 | int reserved = 0; | ||
469 | struct ieee80211_hdr *hdr = (void *) buf; | ||
470 | |||
471 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
472 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
473 | reserved += NET_IP_ALIGN; | ||
474 | |||
475 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
476 | reserved += NET_IP_ALIGN; | ||
477 | } | ||
478 | |||
479 | if (ieee80211_has_a4(hdr->frame_control)) | ||
480 | reserved += NET_IP_ALIGN; | ||
481 | |||
482 | reserved = 32 + (reserved & NET_IP_ALIGN); | ||
483 | |||
484 | skb = dev_alloc_skb(len + reserved); | ||
485 | if (likely(skb)) { | ||
486 | skb_reserve(skb, reserved); | ||
487 | memcpy(skb_put(skb, len), buf, len); | ||
488 | } | ||
489 | |||
490 | return skb; | ||
491 | } | ||
492 | |||
493 | static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie) | ||
494 | { | ||
495 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
496 | u8 *pos, *end; | ||
497 | |||
498 | pos = (u8 *)mgmt->u.beacon.variable; | ||
499 | end = data + len; | ||
500 | while (pos < end) { | ||
501 | if (pos + 2 + pos[1] > end) | ||
502 | return NULL; | ||
503 | |||
504 | if (pos[0] == ie) | ||
505 | return pos; | ||
506 | |||
507 | pos += 2 + pos[1]; | ||
508 | } | ||
509 | return NULL; | ||
510 | } | ||
511 | |||
512 | /* | ||
513 | * NOTE: | ||
514 | * | ||
515 | * The firmware is in charge of waking up the device just before | ||
516 | * the AP is expected to transmit the next beacon. | ||
517 | * | ||
518 | * This leaves the driver with the important task of deciding when | ||
519 | * to set the PHY back to bed again. | ||
520 | */ | ||
521 | static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | ||
522 | { | ||
523 | struct ieee80211_hdr *hdr = (void *) data; | ||
524 | struct ieee80211_tim_ie *tim_ie; | ||
525 | u8 *tim; | ||
526 | u8 tim_len; | ||
527 | bool cam; | ||
528 | |||
529 | if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) | ||
530 | return; | ||
531 | |||
532 | /* check if this really is a beacon */ | ||
533 | if (!ieee80211_is_beacon(hdr->frame_control)) | ||
534 | return; | ||
535 | |||
536 | /* min. beacon length + FCS_LEN */ | ||
537 | if (len <= 40 + FCS_LEN) | ||
538 | return; | ||
539 | |||
540 | /* and only beacons from the associated BSSID, please */ | ||
541 | if (compare_ether_addr(hdr->addr3, ar->common.curbssid) || | ||
542 | !ar->common.curaid) | ||
543 | return; | ||
544 | |||
545 | ar->ps.last_beacon = jiffies; | ||
546 | |||
547 | tim = carl9170_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); | ||
548 | if (!tim) | ||
549 | return; | ||
550 | |||
551 | if (tim[1] < sizeof(*tim_ie)) | ||
552 | return; | ||
553 | |||
554 | tim_len = tim[1]; | ||
555 | tim_ie = (struct ieee80211_tim_ie *) &tim[2]; | ||
556 | |||
557 | if (!WARN_ON_ONCE(!ar->hw->conf.ps_dtim_period)) | ||
558 | ar->ps.dtim_counter = (tim_ie->dtim_count - 1) % | ||
559 | ar->hw->conf.ps_dtim_period; | ||
560 | |||
561 | /* Check whenever the PHY can be turned off again. */ | ||
562 | |||
563 | /* 1. What about buffered unicast traffic for our AID? */ | ||
564 | cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid); | ||
565 | |||
566 | /* 2. Maybe the AP wants to send multicast/broadcast data? */ | ||
567 | cam = !!(tim_ie->bitmap_ctrl & 0x01); | ||
568 | |||
569 | if (!cam) { | ||
570 | /* back to low-power land. */ | ||
571 | ar->ps.off_override &= ~PS_OFF_BCN; | ||
572 | carl9170_ps_check(ar); | ||
573 | } else { | ||
574 | /* force CAM */ | ||
575 | ar->ps.off_override |= PS_OFF_BCN; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | /* | ||
580 | * If the frame alignment is right (or the kernel has | ||
581 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there | ||
582 | * is only a single MPDU in the USB frame, then we could | ||
583 | * submit to mac80211 the SKB directly. However, since | ||
584 | * there may be multiple packets in one SKB in stream | ||
585 | * mode, and we need to observe the proper ordering, | ||
586 | * this is non-trivial. | ||
587 | */ | ||
588 | |||
589 | static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | ||
590 | { | ||
591 | struct ar9170_rx_head *head; | ||
592 | struct ar9170_rx_macstatus *mac; | ||
593 | struct ar9170_rx_phystatus *phy = NULL; | ||
594 | struct ieee80211_rx_status status; | ||
595 | struct sk_buff *skb; | ||
596 | int mpdu_len; | ||
597 | |||
598 | if (!IS_STARTED(ar)) | ||
599 | return; | ||
600 | |||
601 | if (unlikely(len < sizeof(*mac))) { | ||
602 | ar->rx_dropped++; | ||
603 | return; | ||
604 | } | ||
605 | |||
606 | mpdu_len = len - sizeof(*mac); | ||
607 | |||
608 | mac = (void *)(buf + mpdu_len); | ||
609 | if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { | ||
610 | ar->rx_dropped++; | ||
611 | return; | ||
612 | } | ||
613 | |||
614 | switch (mac->status & AR9170_RX_STATUS_MPDU) { | ||
615 | case AR9170_RX_STATUS_MPDU_FIRST: | ||
616 | /* Aggregated MPDUs start with an PLCP header */ | ||
617 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { | ||
618 | head = (void *) buf; | ||
619 | |||
620 | /* | ||
621 | * The PLCP header needs to be cached for the | ||
622 | * following MIDDLE + LAST A-MPDU packets. | ||
623 | * | ||
624 | * So, if you are wondering why all frames seem | ||
625 | * to share a common RX status information, | ||
626 | * then you have the answer right here... | ||
627 | */ | ||
628 | memcpy(&ar->rx_plcp, (void *) buf, | ||
629 | sizeof(struct ar9170_rx_head)); | ||
630 | |||
631 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
632 | buf += sizeof(struct ar9170_rx_head); | ||
633 | |||
634 | ar->rx_has_plcp = true; | ||
635 | } else { | ||
636 | if (net_ratelimit()) { | ||
637 | wiphy_err(ar->hw->wiphy, "plcp info " | ||
638 | "is clipped.\n"); | ||
639 | } | ||
640 | |||
641 | ar->rx_dropped++; | ||
642 | return; | ||
643 | } | ||
644 | break; | ||
645 | |||
646 | case AR9170_RX_STATUS_MPDU_LAST: | ||
647 | /* | ||
648 | * The last frame of an A-MPDU has an extra tail | ||
649 | * which does contain the phy status of the whole | ||
650 | * aggregate. | ||
651 | */ | ||
652 | |||
653 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { | ||
654 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
655 | phy = (void *)(buf + mpdu_len); | ||
656 | } else { | ||
657 | if (net_ratelimit()) { | ||
658 | wiphy_err(ar->hw->wiphy, "frame tail " | ||
659 | "is clipped.\n"); | ||
660 | } | ||
661 | |||
662 | ar->rx_dropped++; | ||
663 | return; | ||
664 | } | ||
665 | |||
666 | case AR9170_RX_STATUS_MPDU_MIDDLE: | ||
667 | /* These are just data + mac status */ | ||
668 | if (unlikely(!ar->rx_has_plcp)) { | ||
669 | if (!net_ratelimit()) | ||
670 | return; | ||
671 | |||
672 | wiphy_err(ar->hw->wiphy, "rx stream does not start " | ||
673 | "with a first_mpdu frame tag.\n"); | ||
674 | |||
675 | ar->rx_dropped++; | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | head = &ar->rx_plcp; | ||
680 | break; | ||
681 | |||
682 | case AR9170_RX_STATUS_MPDU_SINGLE: | ||
683 | /* single mpdu has both: plcp (head) and phy status (tail) */ | ||
684 | head = (void *) buf; | ||
685 | |||
686 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
687 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
688 | |||
689 | buf += sizeof(struct ar9170_rx_head); | ||
690 | phy = (void *)(buf + mpdu_len); | ||
691 | break; | ||
692 | |||
693 | default: | ||
694 | BUG_ON(1); | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | /* FC + DU + RA + FCS */ | ||
699 | if (unlikely(mpdu_len < (2 + 2 + 6 + FCS_LEN))) { | ||
700 | ar->rx_dropped++; | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | memset(&status, 0, sizeof(status)); | ||
705 | if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) { | ||
706 | ar->rx_dropped++; | ||
707 | return; | ||
708 | } | ||
709 | |||
710 | if (phy) | ||
711 | carl9170_rx_phy_status(ar, phy, &status); | ||
712 | |||
713 | carl9170_ps_beacon(ar, buf, mpdu_len); | ||
714 | |||
715 | skb = carl9170_rx_copy_data(buf, mpdu_len); | ||
716 | if (likely(skb)) { | ||
717 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
718 | ieee80211_rx(ar->hw, skb); | ||
719 | } else { | ||
720 | ar->rx_dropped++; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, | ||
725 | const unsigned int resplen) | ||
726 | { | ||
727 | struct carl9170_rsp *cmd; | ||
728 | int i = 0; | ||
729 | |||
730 | while (i < resplen) { | ||
731 | cmd = (void *) &respbuf[i]; | ||
732 | |||
733 | i += cmd->hdr.len + 4; | ||
734 | if (unlikely(i > resplen)) | ||
735 | break; | ||
736 | |||
737 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); | ||
738 | } | ||
739 | |||
740 | if (unlikely(i != resplen)) { | ||
741 | if (!net_ratelimit()) | ||
742 | return; | ||
743 | |||
744 | wiphy_err(ar->hw->wiphy, "malformed firmware trap:\n"); | ||
745 | print_hex_dump_bytes("rxcmd:", DUMP_PREFIX_OFFSET, | ||
746 | respbuf, resplen); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) | ||
751 | { | ||
752 | unsigned int i = 0; | ||
753 | |||
754 | /* weird thing, but this is the same in the original driver */ | ||
755 | while (len > 2 && i < 12 && buf[0] == 0xff && buf[1] == 0xff) { | ||
756 | i += 2; | ||
757 | len -= 2; | ||
758 | buf += 2; | ||
759 | } | ||
760 | |||
761 | if (unlikely(len < 4)) | ||
762 | return; | ||
763 | |||
764 | /* found the 6 * 0xffff marker? */ | ||
765 | if (i == 12) | ||
766 | carl9170_rx_untie_cmds(ar, buf, len); | ||
767 | else | ||
768 | carl9170_handle_mpdu(ar, buf, len); | ||
769 | } | ||
770 | |||
771 | static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) | ||
772 | { | ||
773 | unsigned int tlen, wlen = 0, clen = 0; | ||
774 | struct ar9170_stream *rx_stream; | ||
775 | u8 *tbuf; | ||
776 | |||
777 | tbuf = buf; | ||
778 | tlen = len; | ||
779 | |||
780 | while (tlen >= 4) { | ||
781 | rx_stream = (void *) tbuf; | ||
782 | clen = le16_to_cpu(rx_stream->length); | ||
783 | wlen = ALIGN(clen, 4); | ||
784 | |||
785 | /* check if this is stream has a valid tag.*/ | ||
786 | if (rx_stream->tag != cpu_to_le16(AR9170_RX_STREAM_TAG)) { | ||
787 | /* | ||
788 | * TODO: handle the highly unlikely event that the | ||
789 | * corrupted stream has the TAG at the right position. | ||
790 | */ | ||
791 | |||
792 | /* check if the frame can be repaired. */ | ||
793 | if (!ar->rx_failover_missing) { | ||
794 | |||
795 | /* this is not "short read". */ | ||
796 | if (net_ratelimit()) { | ||
797 | wiphy_err(ar->hw->wiphy, | ||
798 | "missing tag!\n"); | ||
799 | } | ||
800 | |||
801 | __carl9170_rx(ar, tbuf, tlen); | ||
802 | return; | ||
803 | } | ||
804 | |||
805 | if (ar->rx_failover_missing > tlen) { | ||
806 | if (net_ratelimit()) { | ||
807 | wiphy_err(ar->hw->wiphy, | ||
808 | "possible multi " | ||
809 | "stream corruption!\n"); | ||
810 | goto err_telluser; | ||
811 | } else { | ||
812 | goto err_silent; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
817 | ar->rx_failover_missing -= tlen; | ||
818 | |||
819 | if (ar->rx_failover_missing <= 0) { | ||
820 | /* | ||
821 | * nested carl9170_rx_stream call! | ||
822 | * | ||
823 | * termination is guranteed, even when the | ||
824 | * combined frame also have an element with | ||
825 | * a bad tag. | ||
826 | */ | ||
827 | |||
828 | ar->rx_failover_missing = 0; | ||
829 | carl9170_rx_stream(ar, ar->rx_failover->data, | ||
830 | ar->rx_failover->len); | ||
831 | |||
832 | skb_reset_tail_pointer(ar->rx_failover); | ||
833 | skb_trim(ar->rx_failover, 0); | ||
834 | } | ||
835 | |||
836 | return; | ||
837 | } | ||
838 | |||
839 | /* check if stream is clipped */ | ||
840 | if (wlen > tlen - 4) { | ||
841 | if (ar->rx_failover_missing) { | ||
842 | /* TODO: handle double stream corruption. */ | ||
843 | if (net_ratelimit()) { | ||
844 | wiphy_err(ar->hw->wiphy, "double rx " | ||
845 | "stream corruption!\n"); | ||
846 | goto err_telluser; | ||
847 | } else { | ||
848 | goto err_silent; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | /* | ||
853 | * save incomplete data set. | ||
854 | * the firmware will resend the missing bits when | ||
855 | * the rx - descriptor comes round again. | ||
856 | */ | ||
857 | |||
858 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
859 | ar->rx_failover_missing = clen - tlen; | ||
860 | return; | ||
861 | } | ||
862 | __carl9170_rx(ar, rx_stream->payload, clen); | ||
863 | |||
864 | tbuf += wlen + 4; | ||
865 | tlen -= wlen + 4; | ||
866 | } | ||
867 | |||
868 | if (tlen) { | ||
869 | if (net_ratelimit()) { | ||
870 | wiphy_err(ar->hw->wiphy, "%d bytes of unprocessed " | ||
871 | "data left in rx stream!\n", tlen); | ||
872 | } | ||
873 | |||
874 | goto err_telluser; | ||
875 | } | ||
876 | |||
877 | return; | ||
878 | |||
879 | err_telluser: | ||
880 | wiphy_err(ar->hw->wiphy, "damaged RX stream data [want:%d, " | ||
881 | "data:%d, rx:%d, pending:%d ]\n", clen, wlen, tlen, | ||
882 | ar->rx_failover_missing); | ||
883 | |||
884 | if (ar->rx_failover_missing) | ||
885 | print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, | ||
886 | ar->rx_failover->data, | ||
887 | ar->rx_failover->len); | ||
888 | |||
889 | print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, | ||
890 | buf, len); | ||
891 | |||
892 | wiphy_err(ar->hw->wiphy, "please check your hardware and cables, if " | ||
893 | "you see this message frequently.\n"); | ||
894 | |||
895 | err_silent: | ||
896 | if (ar->rx_failover_missing) { | ||
897 | skb_reset_tail_pointer(ar->rx_failover); | ||
898 | skb_trim(ar->rx_failover, 0); | ||
899 | ar->rx_failover_missing = 0; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len) | ||
904 | { | ||
905 | if (ar->fw.rx_stream) | ||
906 | carl9170_rx_stream(ar, buf, len); | ||
907 | else | ||
908 | __carl9170_rx(ar, buf, len); | ||
909 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c new file mode 100644 index 000000000000..e0d2374e0c77 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -0,0 +1,1373 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * 802.11 xmit & status routines | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <net/mac80211.h> | ||
45 | #include "carl9170.h" | ||
46 | #include "hw.h" | ||
47 | #include "cmd.h" | ||
48 | |||
49 | static inline unsigned int __carl9170_get_queue(struct ar9170 *ar, | ||
50 | unsigned int queue) | ||
51 | { | ||
52 | if (unlikely(modparam_noht)) { | ||
53 | return queue; | ||
54 | } else { | ||
55 | /* | ||
56 | * This is just another workaround, until | ||
57 | * someone figures out how to get QoS and | ||
58 | * AMPDU to play nicely together. | ||
59 | */ | ||
60 | |||
61 | return 2; /* AC_BE */ | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static inline unsigned int carl9170_get_queue(struct ar9170 *ar, | ||
66 | struct sk_buff *skb) | ||
67 | { | ||
68 | return __carl9170_get_queue(ar, skb_get_queue_mapping(skb)); | ||
69 | } | ||
70 | |||
71 | static bool is_mem_full(struct ar9170 *ar) | ||
72 | { | ||
73 | return (DIV_ROUND_UP(IEEE80211_MAX_FRAME_LEN, ar->fw.mem_block_size) > | ||
74 | atomic_read(&ar->mem_free_blocks)); | ||
75 | } | ||
76 | |||
77 | static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb) | ||
78 | { | ||
79 | int queue, i; | ||
80 | bool mem_full; | ||
81 | |||
82 | atomic_inc(&ar->tx_total_queued); | ||
83 | |||
84 | queue = skb_get_queue_mapping(skb); | ||
85 | spin_lock_bh(&ar->tx_stats_lock); | ||
86 | |||
87 | /* | ||
88 | * The driver has to accept the frame, regardless if the queue is | ||
89 | * full to the brim, or not. We have to do the queuing internally, | ||
90 | * since mac80211 assumes that a driver which can operate with | ||
91 | * aggregated frames does not reject frames for this reason. | ||
92 | */ | ||
93 | ar->tx_stats[queue].len++; | ||
94 | ar->tx_stats[queue].count++; | ||
95 | |||
96 | mem_full = is_mem_full(ar); | ||
97 | for (i = 0; i < ar->hw->queues; i++) { | ||
98 | if (mem_full || ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | ||
99 | ieee80211_stop_queue(ar->hw, i); | ||
100 | ar->queue_stop_timeout[i] = jiffies; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | spin_unlock_bh(&ar->tx_stats_lock); | ||
105 | } | ||
106 | |||
107 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) | ||
108 | { | ||
109 | struct ieee80211_tx_info *txinfo; | ||
110 | int queue; | ||
111 | |||
112 | txinfo = IEEE80211_SKB_CB(skb); | ||
113 | queue = skb_get_queue_mapping(skb); | ||
114 | |||
115 | spin_lock_bh(&ar->tx_stats_lock); | ||
116 | |||
117 | ar->tx_stats[queue].len--; | ||
118 | |||
119 | if (!is_mem_full(ar)) { | ||
120 | unsigned int i; | ||
121 | for (i = 0; i < ar->hw->queues; i++) { | ||
122 | if (ar->tx_stats[i].len >= CARL9170_NUM_TX_LIMIT_SOFT) | ||
123 | continue; | ||
124 | |||
125 | if (ieee80211_queue_stopped(ar->hw, i)) { | ||
126 | unsigned long tmp; | ||
127 | |||
128 | tmp = jiffies - ar->queue_stop_timeout[i]; | ||
129 | if (tmp > ar->max_queue_stop_timeout[i]) | ||
130 | ar->max_queue_stop_timeout[i] = tmp; | ||
131 | } | ||
132 | |||
133 | ieee80211_wake_queue(ar->hw, i); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | spin_unlock_bh(&ar->tx_stats_lock); | ||
138 | if (atomic_dec_and_test(&ar->tx_total_queued)) | ||
139 | complete(&ar->tx_flush); | ||
140 | } | ||
141 | |||
142 | static int carl9170_alloc_dev_space(struct ar9170 *ar, struct sk_buff *skb) | ||
143 | { | ||
144 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
145 | unsigned int chunks; | ||
146 | int cookie = -1; | ||
147 | |||
148 | atomic_inc(&ar->mem_allocs); | ||
149 | |||
150 | chunks = DIV_ROUND_UP(skb->len, ar->fw.mem_block_size); | ||
151 | if (unlikely(atomic_sub_return(chunks, &ar->mem_free_blocks) < 0)) { | ||
152 | atomic_add(chunks, &ar->mem_free_blocks); | ||
153 | return -ENOSPC; | ||
154 | } | ||
155 | |||
156 | spin_lock_bh(&ar->mem_lock); | ||
157 | cookie = bitmap_find_free_region(ar->mem_bitmap, ar->fw.mem_blocks, 0); | ||
158 | spin_unlock_bh(&ar->mem_lock); | ||
159 | |||
160 | if (unlikely(cookie < 0)) { | ||
161 | atomic_add(chunks, &ar->mem_free_blocks); | ||
162 | return -ENOSPC; | ||
163 | } | ||
164 | |||
165 | super = (void *) skb->data; | ||
166 | |||
167 | /* | ||
168 | * Cookie #0 serves two special purposes: | ||
169 | * 1. The firmware might use it generate BlockACK frames | ||
170 | * in responds of an incoming BlockAckReqs. | ||
171 | * | ||
172 | * 2. Prevent double-free bugs. | ||
173 | */ | ||
174 | super->s.cookie = (u8) cookie + 1; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void carl9170_release_dev_space(struct ar9170 *ar, struct sk_buff *skb) | ||
179 | { | ||
180 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
181 | int cookie; | ||
182 | |||
183 | /* make a local copy of the cookie */ | ||
184 | cookie = super->s.cookie; | ||
185 | /* invalidate cookie */ | ||
186 | super->s.cookie = 0; | ||
187 | |||
188 | /* | ||
189 | * Do a out-of-bounds check on the cookie: | ||
190 | * | ||
191 | * * cookie "0" is reserved and won't be assigned to any | ||
192 | * out-going frame. Internally however, it is used to | ||
193 | * mark no longer/un-accounted frames and serves as a | ||
194 | * cheap way of preventing frames from being freed | ||
195 | * twice by _accident_. NB: There is a tiny race... | ||
196 | * | ||
197 | * * obviously, cookie number is limited by the amount | ||
198 | * of available memory blocks, so the number can | ||
199 | * never execeed the mem_blocks count. | ||
200 | */ | ||
201 | if (unlikely(WARN_ON_ONCE(cookie == 0) || | ||
202 | WARN_ON_ONCE(cookie > ar->fw.mem_blocks))) | ||
203 | return; | ||
204 | |||
205 | atomic_add(DIV_ROUND_UP(skb->len, ar->fw.mem_block_size), | ||
206 | &ar->mem_free_blocks); | ||
207 | |||
208 | spin_lock_bh(&ar->mem_lock); | ||
209 | bitmap_release_region(ar->mem_bitmap, cookie - 1, 0); | ||
210 | spin_unlock_bh(&ar->mem_lock); | ||
211 | } | ||
212 | |||
213 | /* Called from any context */ | ||
214 | static void carl9170_tx_release(struct kref *ref) | ||
215 | { | ||
216 | struct ar9170 *ar; | ||
217 | struct carl9170_tx_info *arinfo; | ||
218 | struct ieee80211_tx_info *txinfo; | ||
219 | struct sk_buff *skb; | ||
220 | |||
221 | arinfo = container_of(ref, struct carl9170_tx_info, ref); | ||
222 | txinfo = container_of((void *) arinfo, struct ieee80211_tx_info, | ||
223 | rate_driver_data); | ||
224 | skb = container_of((void *) txinfo, struct sk_buff, cb); | ||
225 | |||
226 | ar = arinfo->ar; | ||
227 | if (WARN_ON_ONCE(!ar)) | ||
228 | return; | ||
229 | |||
230 | BUILD_BUG_ON( | ||
231 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); | ||
232 | |||
233 | memset(&txinfo->status.ampdu_ack_len, 0, | ||
234 | sizeof(struct ieee80211_tx_info) - | ||
235 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); | ||
236 | |||
237 | if (atomic_read(&ar->tx_total_queued)) | ||
238 | ar->tx_schedule = true; | ||
239 | |||
240 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) { | ||
241 | if (!atomic_read(&ar->tx_ampdu_upload)) | ||
242 | ar->tx_ampdu_schedule = true; | ||
243 | |||
244 | if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) { | ||
245 | txinfo->status.ampdu_len = txinfo->pad[0]; | ||
246 | txinfo->status.ampdu_ack_len = txinfo->pad[1]; | ||
247 | txinfo->pad[0] = txinfo->pad[1] = 0; | ||
248 | } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) { | ||
249 | /* | ||
250 | * drop redundant tx_status reports: | ||
251 | * | ||
252 | * 1. ampdu_ack_len of the final tx_status does | ||
253 | * include the feedback of this particular frame. | ||
254 | * | ||
255 | * 2. tx_status_irqsafe only queues up to 128 | ||
256 | * tx feedback reports and discards the rest. | ||
257 | * | ||
258 | * 3. minstrel_ht is picky, it only accepts | ||
259 | * reports of frames with the TX_STATUS_AMPDU flag. | ||
260 | */ | ||
261 | |||
262 | dev_kfree_skb_any(skb); | ||
263 | return; | ||
264 | } else { | ||
265 | /* | ||
266 | * Frame has failed, but we want to keep it in | ||
267 | * case it was lost due to a power-state | ||
268 | * transition. | ||
269 | */ | ||
270 | } | ||
271 | } | ||
272 | |||
273 | skb_pull(skb, sizeof(struct _carl9170_tx_superframe)); | ||
274 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
275 | } | ||
276 | |||
277 | void carl9170_tx_get_skb(struct sk_buff *skb) | ||
278 | { | ||
279 | struct carl9170_tx_info *arinfo = (void *) | ||
280 | (IEEE80211_SKB_CB(skb))->rate_driver_data; | ||
281 | kref_get(&arinfo->ref); | ||
282 | } | ||
283 | |||
284 | int carl9170_tx_put_skb(struct sk_buff *skb) | ||
285 | { | ||
286 | struct carl9170_tx_info *arinfo = (void *) | ||
287 | (IEEE80211_SKB_CB(skb))->rate_driver_data; | ||
288 | |||
289 | return kref_put(&arinfo->ref, carl9170_tx_release); | ||
290 | } | ||
291 | |||
292 | /* Caller must hold the tid_info->lock & rcu_read_lock */ | ||
293 | static void carl9170_tx_shift_bm(struct ar9170 *ar, | ||
294 | struct carl9170_sta_tid *tid_info, u16 seq) | ||
295 | { | ||
296 | u16 off; | ||
297 | |||
298 | off = SEQ_DIFF(seq, tid_info->bsn); | ||
299 | |||
300 | if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS)) | ||
301 | return; | ||
302 | |||
303 | /* | ||
304 | * Sanity check. For each MPDU we set the bit in bitmap and | ||
305 | * clear it once we received the tx_status. | ||
306 | * But if the bit is already cleared then we've been bitten | ||
307 | * by a bug. | ||
308 | */ | ||
309 | WARN_ON_ONCE(!test_and_clear_bit(off, tid_info->bitmap)); | ||
310 | |||
311 | off = SEQ_DIFF(tid_info->snx, tid_info->bsn); | ||
312 | if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS)) | ||
313 | return; | ||
314 | |||
315 | if (!bitmap_empty(tid_info->bitmap, off)) | ||
316 | off = find_first_bit(tid_info->bitmap, off); | ||
317 | |||
318 | tid_info->bsn += off; | ||
319 | tid_info->bsn &= 0x0fff; | ||
320 | |||
321 | bitmap_shift_right(tid_info->bitmap, tid_info->bitmap, | ||
322 | off, CARL9170_BAW_BITS); | ||
323 | } | ||
324 | |||
325 | static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | ||
326 | struct sk_buff *skb, struct ieee80211_tx_info *txinfo) | ||
327 | { | ||
328 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
329 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | ||
330 | struct ieee80211_tx_info *tx_info; | ||
331 | struct carl9170_tx_info *ar_info; | ||
332 | struct carl9170_sta_info *sta_info; | ||
333 | struct ieee80211_sta *sta; | ||
334 | struct carl9170_sta_tid *tid_info; | ||
335 | struct ieee80211_vif *vif; | ||
336 | unsigned int vif_id; | ||
337 | u8 tid; | ||
338 | |||
339 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || | ||
340 | txinfo->flags & IEEE80211_TX_CTL_INJECTED) | ||
341 | return; | ||
342 | |||
343 | tx_info = IEEE80211_SKB_CB(skb); | ||
344 | ar_info = (void *) tx_info->rate_driver_data; | ||
345 | |||
346 | vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> | ||
347 | CARL9170_TX_SUPER_MISC_VIF_ID_S; | ||
348 | |||
349 | if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) | ||
350 | return; | ||
351 | |||
352 | rcu_read_lock(); | ||
353 | vif = rcu_dereference(ar->vif_priv[vif_id].vif); | ||
354 | if (unlikely(!vif)) | ||
355 | goto out_rcu; | ||
356 | |||
357 | /* | ||
358 | * Normally we should use wrappers like ieee80211_get_DA to get | ||
359 | * the correct peer ieee80211_sta. | ||
360 | * | ||
361 | * But there is a problem with indirect traffic (broadcasts, or | ||
362 | * data which is designated for other stations) in station mode. | ||
363 | * The frame will be directed to the AP for distribution and not | ||
364 | * to the actual destination. | ||
365 | */ | ||
366 | sta = ieee80211_find_sta(vif, hdr->addr1); | ||
367 | if (unlikely(!sta)) | ||
368 | goto out_rcu; | ||
369 | |||
370 | tid = get_tid_h(hdr); | ||
371 | |||
372 | sta_info = (void *) sta->drv_priv; | ||
373 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
374 | if (!tid_info) | ||
375 | goto out_rcu; | ||
376 | |||
377 | spin_lock_bh(&tid_info->lock); | ||
378 | if (likely(tid_info->state >= CARL9170_TID_STATE_IDLE)) | ||
379 | carl9170_tx_shift_bm(ar, tid_info, get_seq_h(hdr)); | ||
380 | |||
381 | if (sta_info->stats[tid].clear) { | ||
382 | sta_info->stats[tid].clear = false; | ||
383 | sta_info->stats[tid].ampdu_len = 0; | ||
384 | sta_info->stats[tid].ampdu_ack_len = 0; | ||
385 | } | ||
386 | |||
387 | sta_info->stats[tid].ampdu_len++; | ||
388 | if (txinfo->status.rates[0].count == 1) | ||
389 | sta_info->stats[tid].ampdu_ack_len++; | ||
390 | |||
391 | if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) { | ||
392 | txinfo->pad[0] = sta_info->stats[tid].ampdu_len; | ||
393 | txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len; | ||
394 | txinfo->flags |= IEEE80211_TX_STAT_AMPDU; | ||
395 | sta_info->stats[tid].clear = true; | ||
396 | } | ||
397 | spin_unlock_bh(&tid_info->lock); | ||
398 | |||
399 | out_rcu: | ||
400 | rcu_read_unlock(); | ||
401 | } | ||
402 | |||
403 | void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | ||
404 | const bool success) | ||
405 | { | ||
406 | struct ieee80211_tx_info *txinfo; | ||
407 | |||
408 | carl9170_tx_accounting_free(ar, skb); | ||
409 | |||
410 | txinfo = IEEE80211_SKB_CB(skb); | ||
411 | |||
412 | if (success) | ||
413 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
414 | else | ||
415 | ar->tx_ack_failures++; | ||
416 | |||
417 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) | ||
418 | carl9170_tx_status_process_ampdu(ar, skb, txinfo); | ||
419 | |||
420 | carl9170_tx_put_skb(skb); | ||
421 | } | ||
422 | |||
423 | /* This function may be called form any context */ | ||
424 | void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
425 | { | ||
426 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
427 | |||
428 | atomic_dec(&ar->tx_total_pending); | ||
429 | |||
430 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) | ||
431 | atomic_dec(&ar->tx_ampdu_upload); | ||
432 | |||
433 | if (carl9170_tx_put_skb(skb)) | ||
434 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
435 | } | ||
436 | |||
437 | static struct sk_buff *carl9170_get_queued_skb(struct ar9170 *ar, u8 cookie, | ||
438 | struct sk_buff_head *queue) | ||
439 | { | ||
440 | struct sk_buff *skb; | ||
441 | |||
442 | spin_lock_bh(&queue->lock); | ||
443 | skb_queue_walk(queue, skb) { | ||
444 | struct _carl9170_tx_superframe *txc = (void *) skb->data; | ||
445 | |||
446 | if (txc->s.cookie != cookie) | ||
447 | continue; | ||
448 | |||
449 | __skb_unlink(skb, queue); | ||
450 | spin_unlock_bh(&queue->lock); | ||
451 | |||
452 | carl9170_release_dev_space(ar, skb); | ||
453 | return skb; | ||
454 | } | ||
455 | spin_unlock_bh(&queue->lock); | ||
456 | |||
457 | return NULL; | ||
458 | } | ||
459 | |||
460 | static void carl9170_tx_fill_rateinfo(struct ar9170 *ar, unsigned int rix, | ||
461 | unsigned int tries, struct ieee80211_tx_info *txinfo) | ||
462 | { | ||
463 | unsigned int i; | ||
464 | |||
465 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | ||
466 | if (txinfo->status.rates[i].idx < 0) | ||
467 | break; | ||
468 | |||
469 | if (i == rix) { | ||
470 | txinfo->status.rates[i].count = tries; | ||
471 | i++; | ||
472 | break; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | for (; i < IEEE80211_TX_MAX_RATES; i++) { | ||
477 | txinfo->status.rates[i].idx = -1; | ||
478 | txinfo->status.rates[i].count = 0; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | static void carl9170_check_queue_stop_timeout(struct ar9170 *ar) | ||
483 | { | ||
484 | int i; | ||
485 | struct sk_buff *skb; | ||
486 | struct ieee80211_tx_info *txinfo; | ||
487 | struct carl9170_tx_info *arinfo; | ||
488 | bool restart = false; | ||
489 | |||
490 | for (i = 0; i < ar->hw->queues; i++) { | ||
491 | spin_lock_bh(&ar->tx_status[i].lock); | ||
492 | |||
493 | skb = skb_peek(&ar->tx_status[i]); | ||
494 | |||
495 | if (!skb) | ||
496 | goto next; | ||
497 | |||
498 | txinfo = IEEE80211_SKB_CB(skb); | ||
499 | arinfo = (void *) txinfo->rate_driver_data; | ||
500 | |||
501 | if (time_is_before_jiffies(arinfo->timeout + | ||
502 | msecs_to_jiffies(CARL9170_QUEUE_STUCK_TIMEOUT)) == true) | ||
503 | restart = true; | ||
504 | |||
505 | next: | ||
506 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
507 | } | ||
508 | |||
509 | if (restart) { | ||
510 | /* | ||
511 | * At least one queue has been stuck for long enough. | ||
512 | * Give the device a kick and hope it gets back to | ||
513 | * work. | ||
514 | * | ||
515 | * possible reasons may include: | ||
516 | * - frames got lost/corrupted (bad connection to the device) | ||
517 | * - stalled rx processing/usb controller hiccups | ||
518 | * - firmware errors/bugs | ||
519 | * - every bug you can think of. | ||
520 | * - all bugs you can't... | ||
521 | * - ... | ||
522 | */ | ||
523 | carl9170_restart(ar, CARL9170_RR_STUCK_TX); | ||
524 | } | ||
525 | } | ||
526 | |||
527 | void carl9170_tx_janitor(struct work_struct *work) | ||
528 | { | ||
529 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
530 | tx_janitor.work); | ||
531 | if (!IS_STARTED(ar)) | ||
532 | return; | ||
533 | |||
534 | ar->tx_janitor_last_run = jiffies; | ||
535 | |||
536 | carl9170_check_queue_stop_timeout(ar); | ||
537 | |||
538 | if (!atomic_read(&ar->tx_total_queued)) | ||
539 | return; | ||
540 | |||
541 | ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor, | ||
542 | msecs_to_jiffies(CARL9170_TX_TIMEOUT)); | ||
543 | } | ||
544 | |||
545 | static void __carl9170_tx_process_status(struct ar9170 *ar, | ||
546 | const uint8_t cookie, const uint8_t info) | ||
547 | { | ||
548 | struct sk_buff *skb; | ||
549 | struct ieee80211_tx_info *txinfo; | ||
550 | struct carl9170_tx_info *arinfo; | ||
551 | unsigned int r, t, q; | ||
552 | bool success = true; | ||
553 | |||
554 | q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE]; | ||
555 | |||
556 | skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]); | ||
557 | if (!skb) { | ||
558 | /* | ||
559 | * We have lost the race to another thread. | ||
560 | */ | ||
561 | |||
562 | return ; | ||
563 | } | ||
564 | |||
565 | txinfo = IEEE80211_SKB_CB(skb); | ||
566 | arinfo = (void *) txinfo->rate_driver_data; | ||
567 | |||
568 | if (!(info & CARL9170_TX_STATUS_SUCCESS)) | ||
569 | success = false; | ||
570 | |||
571 | r = (info & CARL9170_TX_STATUS_RIX) >> CARL9170_TX_STATUS_RIX_S; | ||
572 | t = (info & CARL9170_TX_STATUS_TRIES) >> CARL9170_TX_STATUS_TRIES_S; | ||
573 | |||
574 | carl9170_tx_fill_rateinfo(ar, r, t, txinfo); | ||
575 | carl9170_tx_status(ar, skb, success); | ||
576 | } | ||
577 | |||
578 | void carl9170_tx_process_status(struct ar9170 *ar, | ||
579 | const struct carl9170_rsp *cmd) | ||
580 | { | ||
581 | unsigned int i; | ||
582 | |||
583 | for (i = 0; i < cmd->hdr.ext; i++) { | ||
584 | if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { | ||
585 | print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, | ||
586 | (void *) cmd, cmd->hdr.len + 4); | ||
587 | break; | ||
588 | } | ||
589 | |||
590 | __carl9170_tx_process_status(ar, cmd->_tx_status[i].cookie, | ||
591 | cmd->_tx_status[i].info); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | static __le32 carl9170_tx_physet(struct ar9170 *ar, | ||
596 | struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate) | ||
597 | { | ||
598 | struct ieee80211_rate *rate = NULL; | ||
599 | u32 power, chains; | ||
600 | __le32 tmp; | ||
601 | |||
602 | tmp = cpu_to_le32(0); | ||
603 | |||
604 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
605 | tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ << | ||
606 | AR9170_TX_PHY_BW_S); | ||
607 | /* this works because 40 MHz is 2 and dup is 3 */ | ||
608 | if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) | ||
609 | tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP << | ||
610 | AR9170_TX_PHY_BW_S); | ||
611 | |||
612 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
613 | tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); | ||
614 | |||
615 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | ||
616 | u32 r = txrate->idx; | ||
617 | u8 *txpower; | ||
618 | |||
619 | /* heavy clip control */ | ||
620 | tmp |= cpu_to_le32((r & 0x7) << | ||
621 | AR9170_TX_PHY_TX_HEAVY_CLIP_S); | ||
622 | |||
623 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { | ||
624 | if (info->band == IEEE80211_BAND_5GHZ) | ||
625 | txpower = ar->power_5G_ht40; | ||
626 | else | ||
627 | txpower = ar->power_2G_ht40; | ||
628 | } else { | ||
629 | if (info->band == IEEE80211_BAND_5GHZ) | ||
630 | txpower = ar->power_5G_ht20; | ||
631 | else | ||
632 | txpower = ar->power_2G_ht20; | ||
633 | } | ||
634 | |||
635 | power = txpower[r & 7]; | ||
636 | |||
637 | /* +1 dBm for HT40 */ | ||
638 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
639 | power += 2; | ||
640 | |||
641 | r <<= AR9170_TX_PHY_MCS_S; | ||
642 | BUG_ON(r & ~AR9170_TX_PHY_MCS); | ||
643 | |||
644 | tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS); | ||
645 | tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); | ||
646 | |||
647 | /* | ||
648 | * green field preamble does not work. | ||
649 | * | ||
650 | * if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
651 | * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); | ||
652 | */ | ||
653 | } else { | ||
654 | u8 *txpower; | ||
655 | u32 mod; | ||
656 | u32 phyrate; | ||
657 | u8 idx = txrate->idx; | ||
658 | |||
659 | if (info->band != IEEE80211_BAND_2GHZ) { | ||
660 | idx += 4; | ||
661 | txpower = ar->power_5G_leg; | ||
662 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
663 | } else { | ||
664 | if (idx < 4) { | ||
665 | txpower = ar->power_2G_cck; | ||
666 | mod = AR9170_TX_PHY_MOD_CCK; | ||
667 | } else { | ||
668 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
669 | txpower = ar->power_2G_ofdm; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | rate = &__carl9170_ratetable[idx]; | ||
674 | |||
675 | phyrate = rate->hw_value & 0xF; | ||
676 | power = txpower[(rate->hw_value & 0x30) >> 4]; | ||
677 | phyrate <<= AR9170_TX_PHY_MCS_S; | ||
678 | |||
679 | tmp |= cpu_to_le32(mod); | ||
680 | tmp |= cpu_to_le32(phyrate); | ||
681 | |||
682 | /* | ||
683 | * short preamble seems to be broken too. | ||
684 | * | ||
685 | * if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
686 | * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); | ||
687 | */ | ||
688 | } | ||
689 | power <<= AR9170_TX_PHY_TX_PWR_S; | ||
690 | power &= AR9170_TX_PHY_TX_PWR; | ||
691 | tmp |= cpu_to_le32(power); | ||
692 | |||
693 | /* set TX chains */ | ||
694 | if (ar->eeprom.tx_mask == 1) { | ||
695 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
696 | } else { | ||
697 | chains = AR9170_TX_PHY_TXCHAIN_2; | ||
698 | |||
699 | /* >= 36M legacy OFDM - use only one chain */ | ||
700 | if (rate && rate->bitrate >= 360 && | ||
701 | !(txrate->flags & IEEE80211_TX_RC_MCS)) | ||
702 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
703 | } | ||
704 | tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S); | ||
705 | |||
706 | return tmp; | ||
707 | } | ||
708 | |||
709 | static bool carl9170_tx_rts_check(struct ar9170 *ar, | ||
710 | struct ieee80211_tx_rate *rate, | ||
711 | bool ampdu, bool multi) | ||
712 | { | ||
713 | switch (ar->erp_mode) { | ||
714 | case CARL9170_ERP_AUTO: | ||
715 | if (ampdu) | ||
716 | break; | ||
717 | |||
718 | case CARL9170_ERP_MAC80211: | ||
719 | if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)) | ||
720 | break; | ||
721 | |||
722 | case CARL9170_ERP_RTS: | ||
723 | if (likely(!multi)) | ||
724 | return true; | ||
725 | |||
726 | default: | ||
727 | break; | ||
728 | } | ||
729 | |||
730 | return false; | ||
731 | } | ||
732 | |||
733 | static bool carl9170_tx_cts_check(struct ar9170 *ar, | ||
734 | struct ieee80211_tx_rate *rate) | ||
735 | { | ||
736 | switch (ar->erp_mode) { | ||
737 | case CARL9170_ERP_AUTO: | ||
738 | case CARL9170_ERP_MAC80211: | ||
739 | if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
740 | break; | ||
741 | |||
742 | case CARL9170_ERP_CTS: | ||
743 | return true; | ||
744 | |||
745 | default: | ||
746 | break; | ||
747 | } | ||
748 | |||
749 | return false; | ||
750 | } | ||
751 | |||
752 | static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | ||
753 | { | ||
754 | struct ieee80211_hdr *hdr; | ||
755 | struct _carl9170_tx_superframe *txc; | ||
756 | struct carl9170_vif_info *cvif; | ||
757 | struct ieee80211_tx_info *info; | ||
758 | struct ieee80211_tx_rate *txrate; | ||
759 | struct ieee80211_sta *sta; | ||
760 | struct carl9170_tx_info *arinfo; | ||
761 | unsigned int hw_queue; | ||
762 | int i; | ||
763 | u16 keytype = 0; | ||
764 | u16 len, icv = 0; | ||
765 | bool ampdu, no_ack; | ||
766 | |||
767 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
768 | BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) != | ||
769 | CARL9170_TX_SUPERDESC_LEN); | ||
770 | |||
771 | BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) != | ||
772 | AR9170_TX_HWDESC_LEN); | ||
773 | |||
774 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); | ||
775 | |||
776 | hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; | ||
777 | |||
778 | hdr = (void *)skb->data; | ||
779 | info = IEEE80211_SKB_CB(skb); | ||
780 | len = skb->len; | ||
781 | |||
782 | /* | ||
783 | * Note: If the frame was sent through a monitor interface, | ||
784 | * the ieee80211_vif pointer can be NULL. | ||
785 | */ | ||
786 | if (likely(info->control.vif)) | ||
787 | cvif = (void *) info->control.vif->drv_priv; | ||
788 | else | ||
789 | cvif = NULL; | ||
790 | |||
791 | sta = info->control.sta; | ||
792 | |||
793 | txc = (void *)skb_push(skb, sizeof(*txc)); | ||
794 | memset(txc, 0, sizeof(*txc)); | ||
795 | |||
796 | ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); | ||
797 | no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); | ||
798 | |||
799 | if (info->control.hw_key) { | ||
800 | icv = info->control.hw_key->icv_len; | ||
801 | |||
802 | switch (info->control.hw_key->cipher) { | ||
803 | case WLAN_CIPHER_SUITE_WEP40: | ||
804 | case WLAN_CIPHER_SUITE_WEP104: | ||
805 | case WLAN_CIPHER_SUITE_TKIP: | ||
806 | keytype = AR9170_TX_MAC_ENCR_RC4; | ||
807 | break; | ||
808 | case WLAN_CIPHER_SUITE_CCMP: | ||
809 | keytype = AR9170_TX_MAC_ENCR_AES; | ||
810 | break; | ||
811 | default: | ||
812 | WARN_ON(1); | ||
813 | goto err_out; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > | ||
818 | ((CARL9170_TX_SUPER_MISC_VIF_ID >> | ||
819 | CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); | ||
820 | |||
821 | txc->s.len = cpu_to_le16(len + sizeof(*txc)); | ||
822 | txc->f.length = cpu_to_le16(len + icv + 4); | ||
823 | SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, | ||
824 | cvif ? cvif->id : 0); | ||
825 | |||
826 | txc->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | | ||
827 | AR9170_TX_MAC_BACKOFF); | ||
828 | |||
829 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); | ||
830 | |||
831 | txc->f.mac_control |= cpu_to_le16(hw_queue << AR9170_TX_MAC_QOS_S); | ||
832 | txc->f.mac_control |= cpu_to_le16(keytype); | ||
833 | txc->f.phy_control = cpu_to_le32(0); | ||
834 | |||
835 | if (no_ack) | ||
836 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); | ||
837 | |||
838 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) | ||
839 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; | ||
840 | |||
841 | txrate = &info->control.rates[0]; | ||
842 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
843 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
844 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
845 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
846 | |||
847 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); | ||
848 | txc->f.phy_control |= carl9170_tx_physet(ar, info, txrate); | ||
849 | |||
850 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
851 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | ||
852 | txrate = &info->control.rates[i]; | ||
853 | if (txrate->idx >= 0) | ||
854 | continue; | ||
855 | |||
856 | txrate->idx = 0; | ||
857 | txrate->count = ar->hw->max_rate_tries; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * NOTE: For the first rate, the ERP & AMPDU flags are directly | ||
863 | * taken from mac_control. For all fallback rate, the firmware | ||
864 | * updates the mac_control flags from the rate info field. | ||
865 | */ | ||
866 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | ||
867 | txrate = &info->control.rates[i]; | ||
868 | if (txrate->idx < 0) | ||
869 | break; | ||
870 | |||
871 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], | ||
872 | txrate->count); | ||
873 | |||
874 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
875 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << | ||
876 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | ||
877 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
878 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << | ||
879 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | ||
880 | |||
881 | /* | ||
882 | * unaggregated fallback, in case aggregation | ||
883 | * proves to be unsuccessful and unreliable. | ||
884 | */ | ||
885 | if (ampdu && i < 3) | ||
886 | txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; | ||
887 | |||
888 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); | ||
889 | } | ||
890 | |||
891 | if (ieee80211_is_probe_resp(hdr->frame_control)) | ||
892 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; | ||
893 | |||
894 | if (ampdu) { | ||
895 | unsigned int density, factor; | ||
896 | |||
897 | if (unlikely(!sta || !cvif)) | ||
898 | goto err_out; | ||
899 | |||
900 | density = info->control.sta->ht_cap.ampdu_density; | ||
901 | factor = info->control.sta->ht_cap.ampdu_factor; | ||
902 | |||
903 | if (density) { | ||
904 | /* | ||
905 | * Watch out! | ||
906 | * | ||
907 | * Otus uses slightly different density values than | ||
908 | * those from the 802.11n spec. | ||
909 | */ | ||
910 | |||
911 | density = max_t(unsigned int, density + 1, 7u); | ||
912 | } | ||
913 | |||
914 | factor = min_t(unsigned int, 1u, factor); | ||
915 | |||
916 | SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, | ||
917 | txc->s.ampdu_settings, density); | ||
918 | |||
919 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, | ||
920 | txc->s.ampdu_settings, factor); | ||
921 | |||
922 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
923 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
924 | } else { | ||
925 | /* | ||
926 | * Not sure if it's even possible to aggregate | ||
927 | * non-ht rates with this HW. | ||
928 | */ | ||
929 | WARN_ON_ONCE(1); | ||
930 | } | ||
931 | } | ||
932 | |||
933 | arinfo = (void *)info->rate_driver_data; | ||
934 | arinfo->timeout = jiffies; | ||
935 | arinfo->ar = ar; | ||
936 | kref_init(&arinfo->ref); | ||
937 | return 0; | ||
938 | |||
939 | err_out: | ||
940 | skb_pull(skb, sizeof(*txc)); | ||
941 | return -EINVAL; | ||
942 | } | ||
943 | |||
944 | static void carl9170_set_immba(struct ar9170 *ar, struct sk_buff *skb) | ||
945 | { | ||
946 | struct _carl9170_tx_superframe *super; | ||
947 | |||
948 | super = (void *) skb->data; | ||
949 | super->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_BA); | ||
950 | } | ||
951 | |||
952 | static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb) | ||
953 | { | ||
954 | struct _carl9170_tx_superframe *super; | ||
955 | int tmp; | ||
956 | |||
957 | super = (void *) skb->data; | ||
958 | |||
959 | tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_DENSITY) << | ||
960 | CARL9170_TX_SUPER_AMPDU_DENSITY_S; | ||
961 | |||
962 | /* | ||
963 | * If you haven't noticed carl9170_tx_prepare has already filled | ||
964 | * in all ampdu spacing & factor parameters. | ||
965 | * Now it's the time to check whenever the settings have to be | ||
966 | * updated by the firmware, or if everything is still the same. | ||
967 | * | ||
968 | * There's no sane way to handle different density values with | ||
969 | * this hardware, so we may as well just do the compare in the | ||
970 | * driver. | ||
971 | */ | ||
972 | |||
973 | if (tmp != ar->current_density) { | ||
974 | ar->current_density = tmp; | ||
975 | super->s.ampdu_settings |= | ||
976 | CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY; | ||
977 | } | ||
978 | |||
979 | tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_FACTOR) << | ||
980 | CARL9170_TX_SUPER_AMPDU_FACTOR_S; | ||
981 | |||
982 | if (tmp != ar->current_factor) { | ||
983 | ar->current_factor = tmp; | ||
984 | super->s.ampdu_settings |= | ||
985 | CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest, | ||
990 | struct sk_buff *_src) | ||
991 | { | ||
992 | struct _carl9170_tx_superframe *dest, *src; | ||
993 | |||
994 | dest = (void *) _dest->data; | ||
995 | src = (void *) _src->data; | ||
996 | |||
997 | /* | ||
998 | * The mac80211 rate control algorithm expects that all MPDUs in | ||
999 | * an AMPDU share the same tx vectors. | ||
1000 | * This is not really obvious right now, because the hardware | ||
1001 | * does the AMPDU setup according to its own rulebook. | ||
1002 | * Our nicely assembled, strictly monotonic increasing mpdu | ||
1003 | * chains will be broken up, mashed back together... | ||
1004 | */ | ||
1005 | |||
1006 | return (dest->f.phy_control == src->f.phy_control); | ||
1007 | } | ||
1008 | |||
1009 | static void carl9170_tx_ampdu(struct ar9170 *ar) | ||
1010 | { | ||
1011 | struct sk_buff_head agg; | ||
1012 | struct carl9170_sta_tid *tid_info; | ||
1013 | struct sk_buff *skb, *first; | ||
1014 | unsigned int i = 0, done_ampdus = 0; | ||
1015 | u16 seq, queue, tmpssn; | ||
1016 | |||
1017 | atomic_inc(&ar->tx_ampdu_scheduler); | ||
1018 | ar->tx_ampdu_schedule = false; | ||
1019 | |||
1020 | if (atomic_read(&ar->tx_ampdu_upload)) | ||
1021 | return; | ||
1022 | |||
1023 | if (!ar->tx_ampdu_list_len) | ||
1024 | return; | ||
1025 | |||
1026 | __skb_queue_head_init(&agg); | ||
1027 | |||
1028 | rcu_read_lock(); | ||
1029 | tid_info = rcu_dereference(ar->tx_ampdu_iter); | ||
1030 | if (WARN_ON_ONCE(!tid_info)) { | ||
1031 | rcu_read_unlock(); | ||
1032 | return; | ||
1033 | } | ||
1034 | |||
1035 | retry: | ||
1036 | list_for_each_entry_continue_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
1037 | i++; | ||
1038 | |||
1039 | if (tid_info->state < CARL9170_TID_STATE_PROGRESS) | ||
1040 | continue; | ||
1041 | |||
1042 | queue = TID_TO_WME_AC(tid_info->tid); | ||
1043 | |||
1044 | spin_lock_bh(&tid_info->lock); | ||
1045 | if (tid_info->state != CARL9170_TID_STATE_XMIT) { | ||
1046 | first = skb_peek(&tid_info->queue); | ||
1047 | if (first) { | ||
1048 | struct ieee80211_tx_info *txinfo; | ||
1049 | struct carl9170_tx_info *arinfo; | ||
1050 | |||
1051 | txinfo = IEEE80211_SKB_CB(first); | ||
1052 | arinfo = (void *) txinfo->rate_driver_data; | ||
1053 | |||
1054 | if (time_is_after_jiffies(arinfo->timeout + | ||
1055 | msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)) | ||
1056 | == true) | ||
1057 | goto processed; | ||
1058 | |||
1059 | /* | ||
1060 | * We've been waiting for the frame which | ||
1061 | * matches "snx" (start sequence of the | ||
1062 | * next aggregate) for some time now. | ||
1063 | * | ||
1064 | * But it never arrived. Therefore | ||
1065 | * jump to the next available frame | ||
1066 | * and kick-start the transmission. | ||
1067 | * | ||
1068 | * Note: This might induce odd latency | ||
1069 | * spikes because the receiver will be | ||
1070 | * waiting for the lost frame too. | ||
1071 | */ | ||
1072 | ar->tx_ampdu_timeout++; | ||
1073 | |||
1074 | tid_info->snx = carl9170_get_seq(first); | ||
1075 | tid_info->state = CARL9170_TID_STATE_XMIT; | ||
1076 | } else { | ||
1077 | goto processed; | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | tid_info->counter++; | ||
1082 | first = skb_peek(&tid_info->queue); | ||
1083 | tmpssn = carl9170_get_seq(first); | ||
1084 | seq = tid_info->snx; | ||
1085 | |||
1086 | if (unlikely(tmpssn != seq)) { | ||
1087 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1088 | |||
1089 | goto processed; | ||
1090 | } | ||
1091 | |||
1092 | while ((skb = skb_peek(&tid_info->queue))) { | ||
1093 | /* strict 0, 1, ..., n - 1, n frame sequence order */ | ||
1094 | if (unlikely(carl9170_get_seq(skb) != seq)) | ||
1095 | break; | ||
1096 | |||
1097 | /* don't upload more than AMPDU FACTOR allows. */ | ||
1098 | if (unlikely(SEQ_DIFF(tid_info->snx, tid_info->bsn) >= | ||
1099 | (tid_info->max - 1))) | ||
1100 | break; | ||
1101 | |||
1102 | if (!carl9170_tx_rate_check(ar, skb, first)) | ||
1103 | break; | ||
1104 | |||
1105 | atomic_inc(&ar->tx_ampdu_upload); | ||
1106 | tid_info->snx = seq = SEQ_NEXT(seq); | ||
1107 | __skb_unlink(skb, &tid_info->queue); | ||
1108 | |||
1109 | __skb_queue_tail(&agg, skb); | ||
1110 | |||
1111 | if (skb_queue_len(&agg) >= CARL9170_NUM_TX_AGG_MAX) | ||
1112 | break; | ||
1113 | } | ||
1114 | |||
1115 | if (skb_queue_empty(&tid_info->queue) || | ||
1116 | carl9170_get_seq(skb_peek(&tid_info->queue)) != | ||
1117 | tid_info->snx) { | ||
1118 | /* | ||
1119 | * stop TID, if A-MPDU frames are still missing, | ||
1120 | * or whenever the queue is empty. | ||
1121 | */ | ||
1122 | |||
1123 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1124 | } | ||
1125 | done_ampdus++; | ||
1126 | |||
1127 | processed: | ||
1128 | spin_unlock_bh(&tid_info->lock); | ||
1129 | |||
1130 | if (skb_queue_empty(&agg)) | ||
1131 | continue; | ||
1132 | |||
1133 | /* apply ampdu spacing & factor settings */ | ||
1134 | carl9170_set_ampdu_params(ar, skb_peek(&agg)); | ||
1135 | |||
1136 | /* set aggregation push bit */ | ||
1137 | carl9170_set_immba(ar, skb_peek_tail(&agg)); | ||
1138 | |||
1139 | spin_lock_bh(&ar->tx_pending[queue].lock); | ||
1140 | skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); | ||
1141 | spin_unlock_bh(&ar->tx_pending[queue].lock); | ||
1142 | ar->tx_schedule = true; | ||
1143 | } | ||
1144 | if ((done_ampdus++ == 0) && (i++ == 0)) | ||
1145 | goto retry; | ||
1146 | |||
1147 | rcu_assign_pointer(ar->tx_ampdu_iter, tid_info); | ||
1148 | rcu_read_unlock(); | ||
1149 | } | ||
1150 | |||
1151 | static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar, | ||
1152 | struct sk_buff_head *queue) | ||
1153 | { | ||
1154 | struct sk_buff *skb; | ||
1155 | struct ieee80211_tx_info *info; | ||
1156 | struct carl9170_tx_info *arinfo; | ||
1157 | |||
1158 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
1159 | |||
1160 | spin_lock_bh(&queue->lock); | ||
1161 | skb = skb_peek(queue); | ||
1162 | if (unlikely(!skb)) | ||
1163 | goto err_unlock; | ||
1164 | |||
1165 | if (carl9170_alloc_dev_space(ar, skb)) | ||
1166 | goto err_unlock; | ||
1167 | |||
1168 | __skb_unlink(skb, queue); | ||
1169 | spin_unlock_bh(&queue->lock); | ||
1170 | |||
1171 | info = IEEE80211_SKB_CB(skb); | ||
1172 | arinfo = (void *) info->rate_driver_data; | ||
1173 | |||
1174 | arinfo->timeout = jiffies; | ||
1175 | |||
1176 | /* | ||
1177 | * increase ref count to "2". | ||
1178 | * Ref counting is the easiest way to solve the race between | ||
1179 | * the the urb's completion routine: carl9170_tx_callback and | ||
1180 | * wlan tx status functions: carl9170_tx_status/janitor. | ||
1181 | */ | ||
1182 | carl9170_tx_get_skb(skb); | ||
1183 | |||
1184 | return skb; | ||
1185 | |||
1186 | err_unlock: | ||
1187 | spin_unlock_bh(&queue->lock); | ||
1188 | return NULL; | ||
1189 | } | ||
1190 | |||
1191 | void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb) | ||
1192 | { | ||
1193 | struct _carl9170_tx_superframe *super; | ||
1194 | uint8_t q = 0; | ||
1195 | |||
1196 | ar->tx_dropped++; | ||
1197 | |||
1198 | super = (void *)skb->data; | ||
1199 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q, | ||
1200 | ar9170_qmap[carl9170_get_queue(ar, skb)]); | ||
1201 | __carl9170_tx_process_status(ar, super->s.cookie, q); | ||
1202 | } | ||
1203 | |||
1204 | static void carl9170_tx(struct ar9170 *ar) | ||
1205 | { | ||
1206 | struct sk_buff *skb; | ||
1207 | unsigned int i, q; | ||
1208 | bool schedule_garbagecollector = false; | ||
1209 | |||
1210 | ar->tx_schedule = false; | ||
1211 | |||
1212 | if (unlikely(!IS_STARTED(ar))) | ||
1213 | return; | ||
1214 | |||
1215 | carl9170_usb_handle_tx_err(ar); | ||
1216 | |||
1217 | for (i = 0; i < ar->hw->queues; i++) { | ||
1218 | while (!skb_queue_empty(&ar->tx_pending[i])) { | ||
1219 | skb = carl9170_tx_pick_skb(ar, &ar->tx_pending[i]); | ||
1220 | if (unlikely(!skb)) | ||
1221 | break; | ||
1222 | |||
1223 | atomic_inc(&ar->tx_total_pending); | ||
1224 | |||
1225 | q = __carl9170_get_queue(ar, i); | ||
1226 | /* | ||
1227 | * NB: tx_status[i] vs. tx_status[q], | ||
1228 | * TODO: Move into pick_skb or alloc_dev_space. | ||
1229 | */ | ||
1230 | skb_queue_tail(&ar->tx_status[q], skb); | ||
1231 | |||
1232 | carl9170_usb_tx(ar, skb); | ||
1233 | schedule_garbagecollector = true; | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | if (!schedule_garbagecollector) | ||
1238 | return; | ||
1239 | |||
1240 | ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor, | ||
1241 | msecs_to_jiffies(CARL9170_TX_TIMEOUT)); | ||
1242 | } | ||
1243 | |||
1244 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | ||
1245 | struct ieee80211_sta *sta, struct sk_buff *skb) | ||
1246 | { | ||
1247 | struct carl9170_sta_info *sta_info; | ||
1248 | struct carl9170_sta_tid *agg; | ||
1249 | struct sk_buff *iter; | ||
1250 | unsigned int max; | ||
1251 | u16 tid, seq, qseq, off; | ||
1252 | bool run = false; | ||
1253 | |||
1254 | tid = carl9170_get_tid(skb); | ||
1255 | seq = carl9170_get_seq(skb); | ||
1256 | sta_info = (void *) sta->drv_priv; | ||
1257 | |||
1258 | rcu_read_lock(); | ||
1259 | agg = rcu_dereference(sta_info->agg[tid]); | ||
1260 | max = sta_info->ampdu_max_len; | ||
1261 | |||
1262 | if (!agg) | ||
1263 | goto err_unlock_rcu; | ||
1264 | |||
1265 | spin_lock_bh(&agg->lock); | ||
1266 | if (unlikely(agg->state < CARL9170_TID_STATE_IDLE)) | ||
1267 | goto err_unlock; | ||
1268 | |||
1269 | /* check if sequence is within the BA window */ | ||
1270 | if (unlikely(!BAW_WITHIN(agg->bsn, CARL9170_BAW_BITS, seq))) | ||
1271 | goto err_unlock; | ||
1272 | |||
1273 | if (WARN_ON_ONCE(!BAW_WITHIN(agg->snx, CARL9170_BAW_BITS, seq))) | ||
1274 | goto err_unlock; | ||
1275 | |||
1276 | off = SEQ_DIFF(seq, agg->bsn); | ||
1277 | if (WARN_ON_ONCE(test_and_set_bit(off, agg->bitmap))) | ||
1278 | goto err_unlock; | ||
1279 | |||
1280 | if (likely(BAW_WITHIN(agg->hsn, CARL9170_BAW_BITS, seq))) { | ||
1281 | __skb_queue_tail(&agg->queue, skb); | ||
1282 | agg->hsn = seq; | ||
1283 | goto queued; | ||
1284 | } | ||
1285 | |||
1286 | skb_queue_reverse_walk(&agg->queue, iter) { | ||
1287 | qseq = carl9170_get_seq(iter); | ||
1288 | |||
1289 | if (BAW_WITHIN(qseq, CARL9170_BAW_BITS, seq)) { | ||
1290 | __skb_queue_after(&agg->queue, iter, skb); | ||
1291 | goto queued; | ||
1292 | } | ||
1293 | } | ||
1294 | |||
1295 | __skb_queue_head(&agg->queue, skb); | ||
1296 | queued: | ||
1297 | |||
1298 | if (unlikely(agg->state != CARL9170_TID_STATE_XMIT)) { | ||
1299 | if (agg->snx == carl9170_get_seq(skb_peek(&agg->queue))) { | ||
1300 | agg->state = CARL9170_TID_STATE_XMIT; | ||
1301 | run = true; | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | spin_unlock_bh(&agg->lock); | ||
1306 | rcu_read_unlock(); | ||
1307 | |||
1308 | return run; | ||
1309 | |||
1310 | err_unlock: | ||
1311 | spin_unlock_bh(&agg->lock); | ||
1312 | |||
1313 | err_unlock_rcu: | ||
1314 | rcu_read_unlock(); | ||
1315 | carl9170_tx_status(ar, skb, false); | ||
1316 | ar->tx_dropped++; | ||
1317 | return false; | ||
1318 | } | ||
1319 | |||
1320 | int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1321 | { | ||
1322 | struct ar9170 *ar = hw->priv; | ||
1323 | struct ieee80211_tx_info *info; | ||
1324 | struct ieee80211_sta *sta; | ||
1325 | bool run; | ||
1326 | |||
1327 | if (unlikely(!IS_STARTED(ar))) | ||
1328 | goto err_free; | ||
1329 | |||
1330 | info = IEEE80211_SKB_CB(skb); | ||
1331 | sta = info->control.sta; | ||
1332 | |||
1333 | if (unlikely(carl9170_tx_prepare(ar, skb))) | ||
1334 | goto err_free; | ||
1335 | |||
1336 | carl9170_tx_accounting(ar, skb); | ||
1337 | /* | ||
1338 | * from now on, one has to use carl9170_tx_status to free | ||
1339 | * all ressouces which are associated with the frame. | ||
1340 | */ | ||
1341 | |||
1342 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1343 | if (WARN_ON_ONCE(!sta)) | ||
1344 | goto err_free; | ||
1345 | |||
1346 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | ||
1347 | if (run) | ||
1348 | carl9170_tx_ampdu(ar); | ||
1349 | |||
1350 | } else { | ||
1351 | unsigned int queue = skb_get_queue_mapping(skb); | ||
1352 | |||
1353 | skb_queue_tail(&ar->tx_pending[queue], skb); | ||
1354 | } | ||
1355 | |||
1356 | carl9170_tx(ar); | ||
1357 | return NETDEV_TX_OK; | ||
1358 | |||
1359 | err_free: | ||
1360 | ar->tx_dropped++; | ||
1361 | dev_kfree_skb_any(skb); | ||
1362 | return NETDEV_TX_OK; | ||
1363 | } | ||
1364 | |||
1365 | void carl9170_tx_scheduler(struct ar9170 *ar) | ||
1366 | { | ||
1367 | |||
1368 | if (ar->tx_ampdu_schedule) | ||
1369 | carl9170_tx_ampdu(ar); | ||
1370 | |||
1371 | if (ar->tx_schedule) | ||
1372 | carl9170_tx(ar); | ||
1373 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c new file mode 100644 index 000000000000..eb789a9e4f15 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/usb.c | |||
@@ -0,0 +1,1138 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * USB - frontend | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU 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; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/module.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/usb.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/etherdevice.h> | ||
45 | #include <linux/device.h> | ||
46 | #include <net/mac80211.h> | ||
47 | #include "carl9170.h" | ||
48 | #include "cmd.h" | ||
49 | #include "hw.h" | ||
50 | #include "fwcmd.h" | ||
51 | |||
52 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
53 | MODULE_AUTHOR("Christian Lamparter <chunkeey@googlemail.com>"); | ||
54 | MODULE_LICENSE("GPL"); | ||
55 | MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); | ||
56 | MODULE_FIRMWARE(CARL9170FW_NAME); | ||
57 | MODULE_ALIAS("ar9170usb"); | ||
58 | MODULE_ALIAS("arusb_lnx"); | ||
59 | |||
60 | /* | ||
61 | * Note: | ||
62 | * | ||
63 | * Always update our wiki's device list (located at: | ||
64 | * http://wireless.kernel.org/en/users/Drivers/ar9170/devices ), | ||
65 | * whenever you add a new device. | ||
66 | */ | ||
67 | static struct usb_device_id carl9170_usb_ids[] = { | ||
68 | /* Atheros 9170 */ | ||
69 | { USB_DEVICE(0x0cf3, 0x9170) }, | ||
70 | /* Atheros TG121N */ | ||
71 | { USB_DEVICE(0x0cf3, 0x1001) }, | ||
72 | /* TP-Link TL-WN821N v2 */ | ||
73 | { USB_DEVICE(0x0cf3, 0x1002), .driver_info = CARL9170_WPS_BUTTON | | ||
74 | CARL9170_ONE_LED }, | ||
75 | /* 3Com Dual Band 802.11n USB Adapter */ | ||
76 | { USB_DEVICE(0x0cf3, 0x1010) }, | ||
77 | /* H3C Dual Band 802.11n USB Adapter */ | ||
78 | { USB_DEVICE(0x0cf3, 0x1011) }, | ||
79 | /* Cace Airpcap NX */ | ||
80 | { USB_DEVICE(0xcace, 0x0300) }, | ||
81 | /* D-Link DWA 160 A1 */ | ||
82 | { USB_DEVICE(0x07d1, 0x3c10) }, | ||
83 | /* D-Link DWA 160 A2 */ | ||
84 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
85 | /* Netgear WNA1000 */ | ||
86 | { USB_DEVICE(0x0846, 0x9040) }, | ||
87 | /* Netgear WNDA3100 */ | ||
88 | { USB_DEVICE(0x0846, 0x9010) }, | ||
89 | /* Netgear WN111 v2 */ | ||
90 | { USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED }, | ||
91 | /* Zydas ZD1221 */ | ||
92 | { USB_DEVICE(0x0ace, 0x1221) }, | ||
93 | /* Proxim ORiNOCO 802.11n USB */ | ||
94 | { USB_DEVICE(0x1435, 0x0804) }, | ||
95 | /* WNC Generic 11n USB Dongle */ | ||
96 | { USB_DEVICE(0x1435, 0x0326) }, | ||
97 | /* ZyXEL NWD271N */ | ||
98 | { USB_DEVICE(0x0586, 0x3417) }, | ||
99 | /* Z-Com UB81 BG */ | ||
100 | { USB_DEVICE(0x0cde, 0x0023) }, | ||
101 | /* Z-Com UB82 ABG */ | ||
102 | { USB_DEVICE(0x0cde, 0x0026) }, | ||
103 | /* Sphairon Homelink 1202 */ | ||
104 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
105 | /* Arcadyan WN7512 */ | ||
106 | { USB_DEVICE(0x083a, 0xf522) }, | ||
107 | /* Planex GWUS300 */ | ||
108 | { USB_DEVICE(0x2019, 0x5304) }, | ||
109 | /* IO-Data WNGDNUS2 */ | ||
110 | { USB_DEVICE(0x04bb, 0x093f) }, | ||
111 | /* NEC WL300NU-G */ | ||
112 | { USB_DEVICE(0x0409, 0x0249) }, | ||
113 | /* AVM FRITZ!WLAN USB Stick N */ | ||
114 | { USB_DEVICE(0x057c, 0x8401) }, | ||
115 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ | ||
116 | { USB_DEVICE(0x057c, 0x8402) }, | ||
117 | /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ | ||
118 | { USB_DEVICE(0x1668, 0x1200) }, | ||
119 | |||
120 | /* terminate */ | ||
121 | {} | ||
122 | }; | ||
123 | MODULE_DEVICE_TABLE(usb, carl9170_usb_ids); | ||
124 | |||
125 | static void carl9170_usb_submit_data_urb(struct ar9170 *ar) | ||
126 | { | ||
127 | struct urb *urb; | ||
128 | int err; | ||
129 | |||
130 | if (atomic_inc_return(&ar->tx_anch_urbs) > AR9170_NUM_TX_URBS) | ||
131 | goto err_acc; | ||
132 | |||
133 | urb = usb_get_from_anchor(&ar->tx_wait); | ||
134 | if (!urb) | ||
135 | goto err_acc; | ||
136 | |||
137 | usb_anchor_urb(urb, &ar->tx_anch); | ||
138 | |||
139 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
140 | if (unlikely(err)) { | ||
141 | if (net_ratelimit()) { | ||
142 | dev_err(&ar->udev->dev, "tx submit failed (%d)\n", | ||
143 | urb->status); | ||
144 | } | ||
145 | |||
146 | usb_unanchor_urb(urb); | ||
147 | usb_anchor_urb(urb, &ar->tx_err); | ||
148 | } | ||
149 | |||
150 | usb_free_urb(urb); | ||
151 | |||
152 | if (likely(err == 0)) | ||
153 | return; | ||
154 | |||
155 | err_acc: | ||
156 | atomic_dec(&ar->tx_anch_urbs); | ||
157 | } | ||
158 | |||
159 | static void carl9170_usb_tx_data_complete(struct urb *urb) | ||
160 | { | ||
161 | struct ar9170 *ar = (struct ar9170 *) | ||
162 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
163 | |||
164 | if (WARN_ON_ONCE(!ar)) { | ||
165 | dev_kfree_skb_irq(urb->context); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | atomic_dec(&ar->tx_anch_urbs); | ||
170 | |||
171 | switch (urb->status) { | ||
172 | /* everything is fine */ | ||
173 | case 0: | ||
174 | carl9170_tx_callback(ar, (void *)urb->context); | ||
175 | break; | ||
176 | |||
177 | /* disconnect */ | ||
178 | case -ENOENT: | ||
179 | case -ECONNRESET: | ||
180 | case -ENODEV: | ||
181 | case -ESHUTDOWN: | ||
182 | /* | ||
183 | * Defer the frame clean-up to the tasklet worker. | ||
184 | * This is necessary, because carl9170_tx_drop | ||
185 | * does not work in an irqsave context. | ||
186 | */ | ||
187 | usb_anchor_urb(urb, &ar->tx_err); | ||
188 | return; | ||
189 | |||
190 | /* a random transmission error has occurred? */ | ||
191 | default: | ||
192 | if (net_ratelimit()) { | ||
193 | dev_err(&ar->udev->dev, "tx failed (%d)\n", | ||
194 | urb->status); | ||
195 | } | ||
196 | |||
197 | usb_anchor_urb(urb, &ar->tx_err); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | if (likely(IS_STARTED(ar))) | ||
202 | carl9170_usb_submit_data_urb(ar); | ||
203 | } | ||
204 | |||
205 | static int carl9170_usb_submit_cmd_urb(struct ar9170 *ar) | ||
206 | { | ||
207 | struct urb *urb; | ||
208 | int err; | ||
209 | |||
210 | if (atomic_inc_return(&ar->tx_cmd_urbs) != 1) { | ||
211 | atomic_dec(&ar->tx_cmd_urbs); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | urb = usb_get_from_anchor(&ar->tx_cmd); | ||
216 | if (!urb) { | ||
217 | atomic_dec(&ar->tx_cmd_urbs); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | usb_anchor_urb(urb, &ar->tx_anch); | ||
222 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
223 | if (unlikely(err)) { | ||
224 | usb_unanchor_urb(urb); | ||
225 | atomic_dec(&ar->tx_cmd_urbs); | ||
226 | } | ||
227 | usb_free_urb(urb); | ||
228 | |||
229 | return err; | ||
230 | } | ||
231 | |||
232 | static void carl9170_usb_cmd_complete(struct urb *urb) | ||
233 | { | ||
234 | struct ar9170 *ar = urb->context; | ||
235 | int err = 0; | ||
236 | |||
237 | if (WARN_ON_ONCE(!ar)) | ||
238 | return; | ||
239 | |||
240 | atomic_dec(&ar->tx_cmd_urbs); | ||
241 | |||
242 | switch (urb->status) { | ||
243 | /* everything is fine */ | ||
244 | case 0: | ||
245 | break; | ||
246 | |||
247 | /* disconnect */ | ||
248 | case -ENOENT: | ||
249 | case -ECONNRESET: | ||
250 | case -ENODEV: | ||
251 | case -ESHUTDOWN: | ||
252 | return; | ||
253 | |||
254 | default: | ||
255 | err = urb->status; | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | if (!IS_INITIALIZED(ar)) | ||
260 | return; | ||
261 | |||
262 | if (err) | ||
263 | dev_err(&ar->udev->dev, "submit cmd cb failed (%d).\n", err); | ||
264 | |||
265 | err = carl9170_usb_submit_cmd_urb(ar); | ||
266 | if (err) | ||
267 | dev_err(&ar->udev->dev, "submit cmd failed (%d).\n", err); | ||
268 | } | ||
269 | |||
270 | static void carl9170_usb_rx_irq_complete(struct urb *urb) | ||
271 | { | ||
272 | struct ar9170 *ar = urb->context; | ||
273 | |||
274 | if (WARN_ON_ONCE(!ar)) | ||
275 | return; | ||
276 | |||
277 | switch (urb->status) { | ||
278 | /* everything is fine */ | ||
279 | case 0: | ||
280 | break; | ||
281 | |||
282 | /* disconnect */ | ||
283 | case -ENOENT: | ||
284 | case -ECONNRESET: | ||
285 | case -ENODEV: | ||
286 | case -ESHUTDOWN: | ||
287 | return; | ||
288 | |||
289 | default: | ||
290 | goto resubmit; | ||
291 | } | ||
292 | |||
293 | carl9170_handle_command_response(ar, urb->transfer_buffer, | ||
294 | urb->actual_length); | ||
295 | |||
296 | resubmit: | ||
297 | usb_anchor_urb(urb, &ar->rx_anch); | ||
298 | if (unlikely(usb_submit_urb(urb, GFP_ATOMIC))) | ||
299 | usb_unanchor_urb(urb); | ||
300 | } | ||
301 | |||
302 | static int carl9170_usb_submit_rx_urb(struct ar9170 *ar, gfp_t gfp) | ||
303 | { | ||
304 | struct urb *urb; | ||
305 | int err = 0, runs = 0; | ||
306 | |||
307 | while ((atomic_read(&ar->rx_anch_urbs) < AR9170_NUM_RX_URBS) && | ||
308 | (runs++ < AR9170_NUM_RX_URBS)) { | ||
309 | err = -ENOSPC; | ||
310 | urb = usb_get_from_anchor(&ar->rx_pool); | ||
311 | if (urb) { | ||
312 | usb_anchor_urb(urb, &ar->rx_anch); | ||
313 | err = usb_submit_urb(urb, gfp); | ||
314 | if (unlikely(err)) { | ||
315 | usb_unanchor_urb(urb); | ||
316 | usb_anchor_urb(urb, &ar->rx_pool); | ||
317 | } else { | ||
318 | atomic_dec(&ar->rx_pool_urbs); | ||
319 | atomic_inc(&ar->rx_anch_urbs); | ||
320 | } | ||
321 | usb_free_urb(urb); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | return err; | ||
326 | } | ||
327 | |||
328 | static void carl9170_usb_rx_work(struct ar9170 *ar) | ||
329 | { | ||
330 | struct urb *urb; | ||
331 | int i; | ||
332 | |||
333 | for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { | ||
334 | urb = usb_get_from_anchor(&ar->rx_work); | ||
335 | if (!urb) | ||
336 | break; | ||
337 | |||
338 | atomic_dec(&ar->rx_work_urbs); | ||
339 | if (IS_INITIALIZED(ar)) { | ||
340 | carl9170_rx(ar, urb->transfer_buffer, | ||
341 | urb->actual_length); | ||
342 | } | ||
343 | |||
344 | usb_anchor_urb(urb, &ar->rx_pool); | ||
345 | atomic_inc(&ar->rx_pool_urbs); | ||
346 | |||
347 | usb_free_urb(urb); | ||
348 | |||
349 | carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | void carl9170_usb_handle_tx_err(struct ar9170 *ar) | ||
354 | { | ||
355 | struct urb *urb; | ||
356 | |||
357 | while ((urb = usb_get_from_anchor(&ar->tx_err))) { | ||
358 | struct sk_buff *skb = (void *)urb->context; | ||
359 | |||
360 | carl9170_tx_drop(ar, skb); | ||
361 | carl9170_tx_callback(ar, skb); | ||
362 | usb_free_urb(urb); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | static void carl9170_usb_tasklet(unsigned long data) | ||
367 | { | ||
368 | struct ar9170 *ar = (struct ar9170 *) data; | ||
369 | |||
370 | if (!IS_INITIALIZED(ar)) | ||
371 | return; | ||
372 | |||
373 | carl9170_usb_rx_work(ar); | ||
374 | |||
375 | /* | ||
376 | * Strictly speaking: The tx scheduler is not part of the USB system. | ||
377 | * But the rx worker returns frames back to the mac80211-stack and | ||
378 | * this is the _perfect_ place to generate the next transmissions. | ||
379 | */ | ||
380 | if (IS_STARTED(ar)) | ||
381 | carl9170_tx_scheduler(ar); | ||
382 | } | ||
383 | |||
384 | static void carl9170_usb_rx_complete(struct urb *urb) | ||
385 | { | ||
386 | struct ar9170 *ar = (struct ar9170 *)urb->context; | ||
387 | int err; | ||
388 | |||
389 | if (WARN_ON_ONCE(!ar)) | ||
390 | return; | ||
391 | |||
392 | atomic_dec(&ar->rx_anch_urbs); | ||
393 | |||
394 | switch (urb->status) { | ||
395 | case 0: | ||
396 | /* rx path */ | ||
397 | usb_anchor_urb(urb, &ar->rx_work); | ||
398 | atomic_inc(&ar->rx_work_urbs); | ||
399 | break; | ||
400 | |||
401 | case -ENOENT: | ||
402 | case -ECONNRESET: | ||
403 | case -ENODEV: | ||
404 | case -ESHUTDOWN: | ||
405 | /* handle disconnect events*/ | ||
406 | return; | ||
407 | |||
408 | default: | ||
409 | /* handle all other errors */ | ||
410 | usb_anchor_urb(urb, &ar->rx_pool); | ||
411 | atomic_inc(&ar->rx_pool_urbs); | ||
412 | break; | ||
413 | } | ||
414 | |||
415 | err = carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); | ||
416 | if (unlikely(err)) { | ||
417 | /* | ||
418 | * usb_submit_rx_urb reported a problem. | ||
419 | * In case this is due to a rx buffer shortage, | ||
420 | * elevate the tasklet worker priority to | ||
421 | * the highest available level. | ||
422 | */ | ||
423 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
424 | |||
425 | if (atomic_read(&ar->rx_anch_urbs) == 0) { | ||
426 | /* | ||
427 | * The system is too slow to cope with | ||
428 | * the enormous workload. We have simply | ||
429 | * run out of active rx urbs and this | ||
430 | * unfortunatly leads to an unpredictable | ||
431 | * device. | ||
432 | */ | ||
433 | |||
434 | carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM); | ||
435 | } | ||
436 | } else { | ||
437 | /* | ||
438 | * Using anything less than _high_ priority absolutely | ||
439 | * kills the rx performance my UP-System... | ||
440 | */ | ||
441 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | static struct urb *carl9170_usb_alloc_rx_urb(struct ar9170 *ar, gfp_t gfp) | ||
446 | { | ||
447 | struct urb *urb; | ||
448 | void *buf; | ||
449 | |||
450 | buf = kmalloc(ar->fw.rx_size, gfp); | ||
451 | if (!buf) | ||
452 | return NULL; | ||
453 | |||
454 | urb = usb_alloc_urb(0, gfp); | ||
455 | if (!urb) { | ||
456 | kfree(buf); | ||
457 | return NULL; | ||
458 | } | ||
459 | |||
460 | usb_fill_bulk_urb(urb, ar->udev, usb_rcvbulkpipe(ar->udev, | ||
461 | AR9170_USB_EP_RX), buf, ar->fw.rx_size, | ||
462 | carl9170_usb_rx_complete, ar); | ||
463 | |||
464 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
465 | |||
466 | return urb; | ||
467 | } | ||
468 | |||
469 | static int carl9170_usb_send_rx_irq_urb(struct ar9170 *ar) | ||
470 | { | ||
471 | struct urb *urb = NULL; | ||
472 | void *ibuf; | ||
473 | int err = -ENOMEM; | ||
474 | |||
475 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
476 | if (!urb) | ||
477 | goto out; | ||
478 | |||
479 | ibuf = kmalloc(AR9170_USB_EP_CTRL_MAX, GFP_KERNEL); | ||
480 | if (!ibuf) | ||
481 | goto out; | ||
482 | |||
483 | usb_fill_int_urb(urb, ar->udev, usb_rcvintpipe(ar->udev, | ||
484 | AR9170_USB_EP_IRQ), ibuf, AR9170_USB_EP_CTRL_MAX, | ||
485 | carl9170_usb_rx_irq_complete, ar, 1); | ||
486 | |||
487 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
488 | |||
489 | usb_anchor_urb(urb, &ar->rx_anch); | ||
490 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
491 | if (err) | ||
492 | usb_unanchor_urb(urb); | ||
493 | |||
494 | out: | ||
495 | usb_free_urb(urb); | ||
496 | return err; | ||
497 | } | ||
498 | |||
499 | static int carl9170_usb_init_rx_bulk_urbs(struct ar9170 *ar) | ||
500 | { | ||
501 | struct urb *urb; | ||
502 | int i, err = -EINVAL; | ||
503 | |||
504 | /* | ||
505 | * The driver actively maintains a second shadow | ||
506 | * pool for inactive, but fully-prepared rx urbs. | ||
507 | * | ||
508 | * The pool should help the driver to master huge | ||
509 | * workload spikes without running the risk of | ||
510 | * undersupplying the hardware or wasting time by | ||
511 | * processing rx data (streams) inside the urb | ||
512 | * completion (hardirq context). | ||
513 | */ | ||
514 | for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { | ||
515 | urb = carl9170_usb_alloc_rx_urb(ar, GFP_KERNEL); | ||
516 | if (!urb) { | ||
517 | err = -ENOMEM; | ||
518 | goto err_out; | ||
519 | } | ||
520 | |||
521 | usb_anchor_urb(urb, &ar->rx_pool); | ||
522 | atomic_inc(&ar->rx_pool_urbs); | ||
523 | usb_free_urb(urb); | ||
524 | } | ||
525 | |||
526 | err = carl9170_usb_submit_rx_urb(ar, GFP_KERNEL); | ||
527 | if (err) | ||
528 | goto err_out; | ||
529 | |||
530 | /* the device now waiting for the firmware. */ | ||
531 | carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); | ||
532 | return 0; | ||
533 | |||
534 | err_out: | ||
535 | |||
536 | usb_scuttle_anchored_urbs(&ar->rx_pool); | ||
537 | usb_scuttle_anchored_urbs(&ar->rx_work); | ||
538 | usb_kill_anchored_urbs(&ar->rx_anch); | ||
539 | return err; | ||
540 | } | ||
541 | |||
542 | static int carl9170_usb_flush(struct ar9170 *ar) | ||
543 | { | ||
544 | struct urb *urb; | ||
545 | int ret, err = 0; | ||
546 | |||
547 | while ((urb = usb_get_from_anchor(&ar->tx_wait))) { | ||
548 | struct sk_buff *skb = (void *)urb->context; | ||
549 | carl9170_tx_drop(ar, skb); | ||
550 | carl9170_tx_callback(ar, skb); | ||
551 | usb_free_urb(urb); | ||
552 | } | ||
553 | |||
554 | ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ); | ||
555 | if (ret == 0) | ||
556 | err = -ETIMEDOUT; | ||
557 | |||
558 | /* lets wait a while until the tx - queues are dried out */ | ||
559 | ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ); | ||
560 | if (ret == 0) | ||
561 | err = -ETIMEDOUT; | ||
562 | |||
563 | usb_kill_anchored_urbs(&ar->tx_anch); | ||
564 | carl9170_usb_handle_tx_err(ar); | ||
565 | |||
566 | return err; | ||
567 | } | ||
568 | |||
569 | static void carl9170_usb_cancel_urbs(struct ar9170 *ar) | ||
570 | { | ||
571 | int err; | ||
572 | |||
573 | carl9170_set_state(ar, CARL9170_UNKNOWN_STATE); | ||
574 | |||
575 | err = carl9170_usb_flush(ar); | ||
576 | if (err) | ||
577 | dev_err(&ar->udev->dev, "stuck tx urbs!\n"); | ||
578 | |||
579 | usb_poison_anchored_urbs(&ar->tx_anch); | ||
580 | carl9170_usb_handle_tx_err(ar); | ||
581 | usb_poison_anchored_urbs(&ar->rx_anch); | ||
582 | |||
583 | tasklet_kill(&ar->usb_tasklet); | ||
584 | |||
585 | usb_scuttle_anchored_urbs(&ar->rx_work); | ||
586 | usb_scuttle_anchored_urbs(&ar->rx_pool); | ||
587 | usb_scuttle_anchored_urbs(&ar->tx_cmd); | ||
588 | } | ||
589 | |||
590 | int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, | ||
591 | const bool free_buf) | ||
592 | { | ||
593 | struct urb *urb; | ||
594 | |||
595 | if (!IS_INITIALIZED(ar)) | ||
596 | return -EPERM; | ||
597 | |||
598 | if (WARN_ON(cmd->hdr.len > CARL9170_MAX_CMD_LEN - 4)) | ||
599 | return -EINVAL; | ||
600 | |||
601 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
602 | if (!urb) | ||
603 | return -ENOMEM; | ||
604 | |||
605 | usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev, | ||
606 | AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, | ||
607 | carl9170_usb_cmd_complete, ar, 1); | ||
608 | |||
609 | urb->transfer_flags |= URB_ZERO_PACKET; | ||
610 | |||
611 | if (free_buf) | ||
612 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
613 | |||
614 | usb_anchor_urb(urb, &ar->tx_cmd); | ||
615 | usb_free_urb(urb); | ||
616 | |||
617 | return carl9170_usb_submit_cmd_urb(ar); | ||
618 | } | ||
619 | |||
620 | int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd, | ||
621 | unsigned int plen, void *payload, unsigned int outlen, void *out) | ||
622 | { | ||
623 | int err = -ENOMEM; | ||
624 | |||
625 | if (!IS_ACCEPTING_CMD(ar)) | ||
626 | return -EIO; | ||
627 | |||
628 | if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) | ||
629 | might_sleep(); | ||
630 | |||
631 | ar->cmd.hdr.len = plen; | ||
632 | ar->cmd.hdr.cmd = cmd; | ||
633 | /* writing multiple regs fills this buffer already */ | ||
634 | if (plen && payload != (u8 *)(ar->cmd.data)) | ||
635 | memcpy(ar->cmd.data, payload, plen); | ||
636 | |||
637 | spin_lock_bh(&ar->cmd_lock); | ||
638 | ar->readbuf = (u8 *)out; | ||
639 | ar->readlen = outlen; | ||
640 | spin_unlock_bh(&ar->cmd_lock); | ||
641 | |||
642 | err = __carl9170_exec_cmd(ar, &ar->cmd, false); | ||
643 | |||
644 | if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) { | ||
645 | err = wait_for_completion_timeout(&ar->cmd_wait, HZ); | ||
646 | if (err == 0) { | ||
647 | err = -ETIMEDOUT; | ||
648 | goto err_unbuf; | ||
649 | } | ||
650 | |||
651 | if (ar->readlen != outlen) { | ||
652 | err = -EMSGSIZE; | ||
653 | goto err_unbuf; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | return 0; | ||
658 | |||
659 | err_unbuf: | ||
660 | /* Maybe the device was removed in the moment we were waiting? */ | ||
661 | if (IS_STARTED(ar)) { | ||
662 | dev_err(&ar->udev->dev, "no command feedback " | ||
663 | "received (%d).\n", err); | ||
664 | |||
665 | /* provide some maybe useful debug information */ | ||
666 | print_hex_dump_bytes("carl9170 cmd: ", DUMP_PREFIX_NONE, | ||
667 | &ar->cmd, plen + 4); | ||
668 | |||
669 | carl9170_restart(ar, CARL9170_RR_COMMAND_TIMEOUT); | ||
670 | } | ||
671 | |||
672 | /* invalidate to avoid completing the next command prematurely */ | ||
673 | spin_lock_bh(&ar->cmd_lock); | ||
674 | ar->readbuf = NULL; | ||
675 | ar->readlen = 0; | ||
676 | spin_unlock_bh(&ar->cmd_lock); | ||
677 | |||
678 | return err; | ||
679 | } | ||
680 | |||
681 | void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) | ||
682 | { | ||
683 | struct urb *urb; | ||
684 | struct ar9170_stream *tx_stream; | ||
685 | void *data; | ||
686 | unsigned int len; | ||
687 | |||
688 | if (!IS_STARTED(ar)) | ||
689 | goto err_drop; | ||
690 | |||
691 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
692 | if (!urb) | ||
693 | goto err_drop; | ||
694 | |||
695 | if (ar->fw.tx_stream) { | ||
696 | tx_stream = (void *) (skb->data - sizeof(*tx_stream)); | ||
697 | |||
698 | len = skb->len + sizeof(*tx_stream); | ||
699 | tx_stream->length = cpu_to_le16(len); | ||
700 | tx_stream->tag = cpu_to_le16(AR9170_TX_STREAM_TAG); | ||
701 | data = tx_stream; | ||
702 | } else { | ||
703 | data = skb->data; | ||
704 | len = skb->len; | ||
705 | } | ||
706 | |||
707 | usb_fill_bulk_urb(urb, ar->udev, usb_sndbulkpipe(ar->udev, | ||
708 | AR9170_USB_EP_TX), data, len, | ||
709 | carl9170_usb_tx_data_complete, skb); | ||
710 | |||
711 | urb->transfer_flags |= URB_ZERO_PACKET; | ||
712 | |||
713 | usb_anchor_urb(urb, &ar->tx_wait); | ||
714 | |||
715 | usb_free_urb(urb); | ||
716 | |||
717 | carl9170_usb_submit_data_urb(ar); | ||
718 | return; | ||
719 | |||
720 | err_drop: | ||
721 | carl9170_tx_drop(ar, skb); | ||
722 | carl9170_tx_callback(ar, skb); | ||
723 | } | ||
724 | |||
725 | static void carl9170_release_firmware(struct ar9170 *ar) | ||
726 | { | ||
727 | if (ar->fw.fw) { | ||
728 | release_firmware(ar->fw.fw); | ||
729 | memset(&ar->fw, 0, sizeof(ar->fw)); | ||
730 | } | ||
731 | } | ||
732 | |||
733 | void carl9170_usb_stop(struct ar9170 *ar) | ||
734 | { | ||
735 | int ret; | ||
736 | |||
737 | carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STOPPED); | ||
738 | |||
739 | ret = carl9170_usb_flush(ar); | ||
740 | if (ret) | ||
741 | dev_err(&ar->udev->dev, "kill pending tx urbs.\n"); | ||
742 | |||
743 | usb_poison_anchored_urbs(&ar->tx_anch); | ||
744 | carl9170_usb_handle_tx_err(ar); | ||
745 | |||
746 | /* kill any pending command */ | ||
747 | spin_lock_bh(&ar->cmd_lock); | ||
748 | ar->readlen = 0; | ||
749 | spin_unlock_bh(&ar->cmd_lock); | ||
750 | complete_all(&ar->cmd_wait); | ||
751 | |||
752 | /* This is required to prevent an early completion on _start */ | ||
753 | INIT_COMPLETION(ar->cmd_wait); | ||
754 | |||
755 | /* | ||
756 | * Note: | ||
757 | * So far we freed all tx urbs, but we won't dare to touch any rx urbs. | ||
758 | * Else we would end up with a unresponsive device... | ||
759 | */ | ||
760 | } | ||
761 | |||
762 | int carl9170_usb_open(struct ar9170 *ar) | ||
763 | { | ||
764 | usb_unpoison_anchored_urbs(&ar->tx_anch); | ||
765 | |||
766 | carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); | ||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static int carl9170_usb_load_firmware(struct ar9170 *ar) | ||
771 | { | ||
772 | const u8 *data; | ||
773 | u8 *buf; | ||
774 | unsigned int transfer; | ||
775 | size_t len; | ||
776 | u32 addr; | ||
777 | int err = 0; | ||
778 | |||
779 | buf = kmalloc(4096, GFP_KERNEL); | ||
780 | if (!buf) { | ||
781 | err = -ENOMEM; | ||
782 | goto err_out; | ||
783 | } | ||
784 | |||
785 | data = ar->fw.fw->data; | ||
786 | len = ar->fw.fw->size; | ||
787 | addr = ar->fw.address; | ||
788 | |||
789 | /* this removes the miniboot image */ | ||
790 | data += ar->fw.offset; | ||
791 | len -= ar->fw.offset; | ||
792 | |||
793 | while (len) { | ||
794 | transfer = min_t(unsigned int, len, 4096u); | ||
795 | memcpy(buf, data, transfer); | ||
796 | |||
797 | err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), | ||
798 | 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, | ||
799 | addr >> 8, 0, buf, transfer, 100); | ||
800 | |||
801 | if (err < 0) { | ||
802 | kfree(buf); | ||
803 | goto err_out; | ||
804 | } | ||
805 | |||
806 | len -= transfer; | ||
807 | data += transfer; | ||
808 | addr += transfer; | ||
809 | } | ||
810 | kfree(buf); | ||
811 | |||
812 | err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), | ||
813 | 0x31 /* FW DL COMPLETE */, | ||
814 | 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 200); | ||
815 | |||
816 | if (wait_for_completion_timeout(&ar->fw_boot_wait, HZ) == 0) { | ||
817 | err = -ETIMEDOUT; | ||
818 | goto err_out; | ||
819 | } | ||
820 | |||
821 | err = carl9170_echo_test(ar, 0x4a110123); | ||
822 | if (err) | ||
823 | goto err_out; | ||
824 | |||
825 | /* firmware restarts cmd counter */ | ||
826 | ar->cmd_seq = -1; | ||
827 | |||
828 | return 0; | ||
829 | |||
830 | err_out: | ||
831 | dev_err(&ar->udev->dev, "firmware upload failed (%d).\n", err); | ||
832 | return err; | ||
833 | } | ||
834 | |||
835 | int carl9170_usb_restart(struct ar9170 *ar) | ||
836 | { | ||
837 | int err = 0; | ||
838 | |||
839 | if (ar->intf->condition != USB_INTERFACE_BOUND) | ||
840 | return 0; | ||
841 | |||
842 | /* Disable command response sequence counter. */ | ||
843 | ar->cmd_seq = -2; | ||
844 | |||
845 | err = carl9170_reboot(ar); | ||
846 | |||
847 | carl9170_usb_stop(ar); | ||
848 | |||
849 | if (err) | ||
850 | goto err_out; | ||
851 | |||
852 | tasklet_schedule(&ar->usb_tasklet); | ||
853 | |||
854 | /* The reboot procedure can take quite a while to complete. */ | ||
855 | msleep(1100); | ||
856 | |||
857 | err = carl9170_usb_open(ar); | ||
858 | if (err) | ||
859 | goto err_out; | ||
860 | |||
861 | err = carl9170_usb_load_firmware(ar); | ||
862 | if (err) | ||
863 | goto err_out; | ||
864 | |||
865 | return 0; | ||
866 | |||
867 | err_out: | ||
868 | carl9170_usb_cancel_urbs(ar); | ||
869 | return err; | ||
870 | } | ||
871 | |||
872 | void carl9170_usb_reset(struct ar9170 *ar) | ||
873 | { | ||
874 | /* | ||
875 | * This is the last resort to get the device going again | ||
876 | * without any *user replugging action*. | ||
877 | * | ||
878 | * But there is a catch: usb_reset really is like a physical | ||
879 | * *reconnect*. The mac80211 state will be lost in the process. | ||
880 | * Therefore a userspace application, which is monitoring | ||
881 | * the link must step in. | ||
882 | */ | ||
883 | carl9170_usb_cancel_urbs(ar); | ||
884 | |||
885 | carl9170_usb_stop(ar); | ||
886 | |||
887 | usb_queue_reset_device(ar->intf); | ||
888 | } | ||
889 | |||
890 | static int carl9170_usb_init_device(struct ar9170 *ar) | ||
891 | { | ||
892 | int err; | ||
893 | |||
894 | err = carl9170_usb_send_rx_irq_urb(ar); | ||
895 | if (err) | ||
896 | goto err_out; | ||
897 | |||
898 | err = carl9170_usb_init_rx_bulk_urbs(ar); | ||
899 | if (err) | ||
900 | goto err_unrx; | ||
901 | |||
902 | mutex_lock(&ar->mutex); | ||
903 | err = carl9170_usb_load_firmware(ar); | ||
904 | mutex_unlock(&ar->mutex); | ||
905 | if (err) | ||
906 | goto err_unrx; | ||
907 | |||
908 | return 0; | ||
909 | |||
910 | err_unrx: | ||
911 | carl9170_usb_cancel_urbs(ar); | ||
912 | |||
913 | err_out: | ||
914 | return err; | ||
915 | } | ||
916 | |||
917 | static void carl9170_usb_firmware_failed(struct ar9170 *ar) | ||
918 | { | ||
919 | struct device *parent = ar->udev->dev.parent; | ||
920 | struct usb_device *udev; | ||
921 | |||
922 | /* | ||
923 | * Store a copy of the usb_device pointer locally. | ||
924 | * This is because device_release_driver initiates | ||
925 | * carl9170_usb_disconnect, which in turn frees our | ||
926 | * driver context (ar). | ||
927 | */ | ||
928 | udev = ar->udev; | ||
929 | |||
930 | complete(&ar->fw_load_wait); | ||
931 | |||
932 | /* unbind anything failed */ | ||
933 | if (parent) | ||
934 | device_lock(parent); | ||
935 | |||
936 | device_release_driver(&udev->dev); | ||
937 | if (parent) | ||
938 | device_unlock(parent); | ||
939 | |||
940 | usb_put_dev(udev); | ||
941 | } | ||
942 | |||
943 | static void carl9170_usb_firmware_finish(struct ar9170 *ar) | ||
944 | { | ||
945 | int err; | ||
946 | |||
947 | err = carl9170_parse_firmware(ar); | ||
948 | if (err) | ||
949 | goto err_freefw; | ||
950 | |||
951 | err = carl9170_usb_init_device(ar); | ||
952 | if (err) | ||
953 | goto err_freefw; | ||
954 | |||
955 | err = carl9170_usb_open(ar); | ||
956 | if (err) | ||
957 | goto err_unrx; | ||
958 | |||
959 | err = carl9170_register(ar); | ||
960 | |||
961 | carl9170_usb_stop(ar); | ||
962 | if (err) | ||
963 | goto err_unrx; | ||
964 | |||
965 | complete(&ar->fw_load_wait); | ||
966 | usb_put_dev(ar->udev); | ||
967 | return; | ||
968 | |||
969 | err_unrx: | ||
970 | carl9170_usb_cancel_urbs(ar); | ||
971 | |||
972 | err_freefw: | ||
973 | carl9170_release_firmware(ar); | ||
974 | carl9170_usb_firmware_failed(ar); | ||
975 | } | ||
976 | |||
977 | static void carl9170_usb_firmware_step2(const struct firmware *fw, | ||
978 | void *context) | ||
979 | { | ||
980 | struct ar9170 *ar = context; | ||
981 | |||
982 | if (fw) { | ||
983 | ar->fw.fw = fw; | ||
984 | carl9170_usb_firmware_finish(ar); | ||
985 | return; | ||
986 | } | ||
987 | |||
988 | dev_err(&ar->udev->dev, "firmware not found.\n"); | ||
989 | carl9170_usb_firmware_failed(ar); | ||
990 | } | ||
991 | |||
992 | static int carl9170_usb_probe(struct usb_interface *intf, | ||
993 | const struct usb_device_id *id) | ||
994 | { | ||
995 | struct ar9170 *ar; | ||
996 | struct usb_device *udev; | ||
997 | int err; | ||
998 | |||
999 | err = usb_reset_device(interface_to_usbdev(intf)); | ||
1000 | if (err) | ||
1001 | return err; | ||
1002 | |||
1003 | ar = carl9170_alloc(sizeof(*ar)); | ||
1004 | if (IS_ERR(ar)) | ||
1005 | return PTR_ERR(ar); | ||
1006 | |||
1007 | udev = interface_to_usbdev(intf); | ||
1008 | usb_get_dev(udev); | ||
1009 | ar->udev = udev; | ||
1010 | ar->intf = intf; | ||
1011 | ar->features = id->driver_info; | ||
1012 | |||
1013 | usb_set_intfdata(intf, ar); | ||
1014 | SET_IEEE80211_DEV(ar->hw, &intf->dev); | ||
1015 | |||
1016 | init_usb_anchor(&ar->rx_anch); | ||
1017 | init_usb_anchor(&ar->rx_pool); | ||
1018 | init_usb_anchor(&ar->rx_work); | ||
1019 | init_usb_anchor(&ar->tx_wait); | ||
1020 | init_usb_anchor(&ar->tx_anch); | ||
1021 | init_usb_anchor(&ar->tx_cmd); | ||
1022 | init_usb_anchor(&ar->tx_err); | ||
1023 | init_completion(&ar->cmd_wait); | ||
1024 | init_completion(&ar->fw_boot_wait); | ||
1025 | init_completion(&ar->fw_load_wait); | ||
1026 | tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet, | ||
1027 | (unsigned long)ar); | ||
1028 | |||
1029 | atomic_set(&ar->tx_cmd_urbs, 0); | ||
1030 | atomic_set(&ar->tx_anch_urbs, 0); | ||
1031 | atomic_set(&ar->rx_work_urbs, 0); | ||
1032 | atomic_set(&ar->rx_anch_urbs, 0); | ||
1033 | atomic_set(&ar->rx_pool_urbs, 0); | ||
1034 | ar->cmd_seq = -2; | ||
1035 | |||
1036 | usb_get_dev(ar->udev); | ||
1037 | |||
1038 | carl9170_set_state(ar, CARL9170_STOPPED); | ||
1039 | |||
1040 | return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, | ||
1041 | &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); | ||
1042 | } | ||
1043 | |||
1044 | static void carl9170_usb_disconnect(struct usb_interface *intf) | ||
1045 | { | ||
1046 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1047 | struct usb_device *udev; | ||
1048 | |||
1049 | if (WARN_ON(!ar)) | ||
1050 | return; | ||
1051 | |||
1052 | udev = ar->udev; | ||
1053 | wait_for_completion(&ar->fw_load_wait); | ||
1054 | |||
1055 | if (IS_INITIALIZED(ar)) { | ||
1056 | carl9170_reboot(ar); | ||
1057 | carl9170_usb_stop(ar); | ||
1058 | } | ||
1059 | |||
1060 | carl9170_usb_cancel_urbs(ar); | ||
1061 | carl9170_unregister(ar); | ||
1062 | |||
1063 | usb_set_intfdata(intf, NULL); | ||
1064 | |||
1065 | carl9170_release_firmware(ar); | ||
1066 | carl9170_free(ar); | ||
1067 | usb_put_dev(udev); | ||
1068 | } | ||
1069 | |||
1070 | #ifdef CONFIG_PM | ||
1071 | static int carl9170_usb_suspend(struct usb_interface *intf, | ||
1072 | pm_message_t message) | ||
1073 | { | ||
1074 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1075 | |||
1076 | if (!ar) | ||
1077 | return -ENODEV; | ||
1078 | |||
1079 | carl9170_usb_cancel_urbs(ar); | ||
1080 | |||
1081 | /* | ||
1082 | * firmware automatically reboots for usb suspend. | ||
1083 | */ | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static int carl9170_usb_resume(struct usb_interface *intf) | ||
1089 | { | ||
1090 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1091 | int err; | ||
1092 | |||
1093 | if (!ar) | ||
1094 | return -ENODEV; | ||
1095 | |||
1096 | usb_unpoison_anchored_urbs(&ar->rx_anch); | ||
1097 | |||
1098 | err = carl9170_usb_init_device(ar); | ||
1099 | if (err) | ||
1100 | goto err_unrx; | ||
1101 | |||
1102 | err = carl9170_usb_open(ar); | ||
1103 | if (err) | ||
1104 | goto err_unrx; | ||
1105 | |||
1106 | return 0; | ||
1107 | |||
1108 | err_unrx: | ||
1109 | carl9170_usb_cancel_urbs(ar); | ||
1110 | |||
1111 | return err; | ||
1112 | } | ||
1113 | #endif /* CONFIG_PM */ | ||
1114 | |||
1115 | static struct usb_driver carl9170_driver = { | ||
1116 | .name = KBUILD_MODNAME, | ||
1117 | .probe = carl9170_usb_probe, | ||
1118 | .disconnect = carl9170_usb_disconnect, | ||
1119 | .id_table = carl9170_usb_ids, | ||
1120 | .soft_unbind = 1, | ||
1121 | #ifdef CONFIG_PM | ||
1122 | .suspend = carl9170_usb_suspend, | ||
1123 | .resume = carl9170_usb_resume, | ||
1124 | #endif /* CONFIG_PM */ | ||
1125 | }; | ||
1126 | |||
1127 | static int __init carl9170_usb_init(void) | ||
1128 | { | ||
1129 | return usb_register(&carl9170_driver); | ||
1130 | } | ||
1131 | |||
1132 | static void __exit carl9170_usb_exit(void) | ||
1133 | { | ||
1134 | usb_deregister(&carl9170_driver); | ||
1135 | } | ||
1136 | |||
1137 | module_init(carl9170_usb_init); | ||
1138 | module_exit(carl9170_usb_exit); | ||
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h new file mode 100644 index 000000000000..0e917f80eab4 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | ||
2 | #define __CARL9170_SHARED_VERSION_H | ||
3 | #define CARL9170FW_VERSION_YEAR 10 | ||
4 | #define CARL9170FW_VERSION_MONTH 8 | ||
5 | #define CARL9170FW_VERSION_DAY 30 | ||
6 | #define CARL9170FW_VERSION_GIT "1.8.8.1" | ||
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h new file mode 100644 index 000000000000..48ead2268f50 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/wlan.h | |||
@@ -0,0 +1,412 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * RX/TX meta descriptor format | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_WLAN_H | ||
40 | #define __CARL9170_SHARED_WLAN_H | ||
41 | |||
42 | #include "fwcmd.h" | ||
43 | |||
44 | #define AR9170_RX_PHY_RATE_CCK_1M 0x0a | ||
45 | #define AR9170_RX_PHY_RATE_CCK_2M 0x14 | ||
46 | #define AR9170_RX_PHY_RATE_CCK_5M 0x37 | ||
47 | #define AR9170_RX_PHY_RATE_CCK_11M 0x6e | ||
48 | |||
49 | #define AR9170_ENC_ALG_NONE 0x0 | ||
50 | #define AR9170_ENC_ALG_WEP64 0x1 | ||
51 | #define AR9170_ENC_ALG_TKIP 0x2 | ||
52 | #define AR9170_ENC_ALG_AESCCMP 0x4 | ||
53 | #define AR9170_ENC_ALG_WEP128 0x5 | ||
54 | #define AR9170_ENC_ALG_WEP256 0x6 | ||
55 | #define AR9170_ENC_ALG_CENC 0x7 | ||
56 | |||
57 | #define AR9170_RX_ENC_SOFTWARE 0x8 | ||
58 | |||
59 | #define AR9170_RX_STATUS_MODULATION 0x03 | ||
60 | #define AR9170_RX_STATUS_MODULATION_S 0 | ||
61 | #define AR9170_RX_STATUS_MODULATION_CCK 0x00 | ||
62 | #define AR9170_RX_STATUS_MODULATION_OFDM 0x01 | ||
63 | #define AR9170_RX_STATUS_MODULATION_HT 0x02 | ||
64 | #define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 | ||
65 | |||
66 | /* depends on modulation */ | ||
67 | #define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 | ||
68 | #define AR9170_RX_STATUS_GREENFIELD 0x08 | ||
69 | |||
70 | #define AR9170_RX_STATUS_MPDU 0x30 | ||
71 | #define AR9170_RX_STATUS_MPDU_S 4 | ||
72 | #define AR9170_RX_STATUS_MPDU_SINGLE 0x00 | ||
73 | #define AR9170_RX_STATUS_MPDU_FIRST 0x20 | ||
74 | #define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 | ||
75 | #define AR9170_RX_STATUS_MPDU_LAST 0x10 | ||
76 | |||
77 | #define AR9170_RX_ERROR_RXTO 0x01 | ||
78 | #define AR9170_RX_ERROR_OVERRUN 0x02 | ||
79 | #define AR9170_RX_ERROR_DECRYPT 0x04 | ||
80 | #define AR9170_RX_ERROR_FCS 0x08 | ||
81 | #define AR9170_RX_ERROR_WRONG_RA 0x10 | ||
82 | #define AR9170_RX_ERROR_PLCP 0x20 | ||
83 | #define AR9170_RX_ERROR_MMIC 0x40 | ||
84 | #define AR9170_RX_ERROR_FATAL 0x80 | ||
85 | |||
86 | /* these are either-or */ | ||
87 | #define AR9170_TX_MAC_PROT_RTS 0x0001 | ||
88 | #define AR9170_TX_MAC_PROT_CTS 0x0002 | ||
89 | #define AR9170_TX_MAC_PROT 0x0003 | ||
90 | |||
91 | #define AR9170_TX_MAC_NO_ACK 0x0004 | ||
92 | /* if unset, MAC will only do SIFS space before frame */ | ||
93 | #define AR9170_TX_MAC_BACKOFF 0x0008 | ||
94 | #define AR9170_TX_MAC_BURST 0x0010 | ||
95 | #define AR9170_TX_MAC_AGGR 0x0020 | ||
96 | |||
97 | /* encryption is a two-bit field */ | ||
98 | #define AR9170_TX_MAC_ENCR_NONE 0x0000 | ||
99 | #define AR9170_TX_MAC_ENCR_RC4 0x0040 | ||
100 | #define AR9170_TX_MAC_ENCR_CENC 0x0080 | ||
101 | #define AR9170_TX_MAC_ENCR_AES 0x00c0 | ||
102 | |||
103 | #define AR9170_TX_MAC_MMIC 0x0100 | ||
104 | #define AR9170_TX_MAC_HW_DURATION 0x0200 | ||
105 | #define AR9170_TX_MAC_QOS_S 10 | ||
106 | #define AR9170_TX_MAC_QOS 0x0c00 | ||
107 | #define AR9170_TX_MAC_DISABLE_TXOP 0x1000 | ||
108 | #define AR9170_TX_MAC_TXOP_RIFS 0x2000 | ||
109 | #define AR9170_TX_MAC_IMM_BA 0x4000 | ||
110 | |||
111 | /* either-or */ | ||
112 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 | ||
113 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 | ||
114 | #define AR9170_TX_PHY_MOD_HT 0x00000002 | ||
115 | |||
116 | /* depends on modulation */ | ||
117 | #define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 | ||
118 | #define AR9170_TX_PHY_GREENFIELD 0x00000004 | ||
119 | |||
120 | #define AR9170_TX_PHY_BW_S 3 | ||
121 | #define AR9170_TX_PHY_BW (3 << AR9170_TX_PHY_BW_SHIFT) | ||
122 | #define AR9170_TX_PHY_BW_20MHZ 0 | ||
123 | #define AR9170_TX_PHY_BW_40MHZ 2 | ||
124 | #define AR9170_TX_PHY_BW_40MHZ_DUP 3 | ||
125 | |||
126 | #define AR9170_TX_PHY_TX_HEAVY_CLIP_S 6 | ||
127 | #define AR9170_TX_PHY_TX_HEAVY_CLIP (7 << \ | ||
128 | AR9170_TX_PHY_TX_HEAVY_CLIP_S) | ||
129 | |||
130 | #define AR9170_TX_PHY_TX_PWR_S 9 | ||
131 | #define AR9170_TX_PHY_TX_PWR (0x3f << \ | ||
132 | AR9170_TX_PHY_TX_PWR_S) | ||
133 | |||
134 | #define AR9170_TX_PHY_TXCHAIN_S 15 | ||
135 | #define AR9170_TX_PHY_TXCHAIN (7 << \ | ||
136 | AR9170_TX_PHY_TXCHAIN_S) | ||
137 | #define AR9170_TX_PHY_TXCHAIN_1 1 | ||
138 | /* use for cck, ofdm 6/9/12/18/24 and HT if capable */ | ||
139 | #define AR9170_TX_PHY_TXCHAIN_2 5 | ||
140 | |||
141 | #define AR9170_TX_PHY_MCS_S 18 | ||
142 | #define AR9170_TX_PHY_MCS (0x7f << \ | ||
143 | AR9170_TX_PHY_MCS_S) | ||
144 | |||
145 | #define AR9170_TX_PHY_RATE_CCK_1M 0x0 | ||
146 | #define AR9170_TX_PHY_RATE_CCK_2M 0x1 | ||
147 | #define AR9170_TX_PHY_RATE_CCK_5M 0x2 | ||
148 | #define AR9170_TX_PHY_RATE_CCK_11M 0x3 | ||
149 | |||
150 | /* same as AR9170_RX_PHY_RATE */ | ||
151 | #define AR9170_TXRX_PHY_RATE_OFDM_6M 0xb | ||
152 | #define AR9170_TXRX_PHY_RATE_OFDM_9M 0xf | ||
153 | #define AR9170_TXRX_PHY_RATE_OFDM_12M 0xa | ||
154 | #define AR9170_TXRX_PHY_RATE_OFDM_18M 0xe | ||
155 | #define AR9170_TXRX_PHY_RATE_OFDM_24M 0x9 | ||
156 | #define AR9170_TXRX_PHY_RATE_OFDM_36M 0xd | ||
157 | #define AR9170_TXRX_PHY_RATE_OFDM_48M 0x8 | ||
158 | #define AR9170_TXRX_PHY_RATE_OFDM_54M 0xc | ||
159 | |||
160 | #define AR9170_TXRX_PHY_RATE_HT_MCS0 0x0 | ||
161 | #define AR9170_TXRX_PHY_RATE_HT_MCS1 0x1 | ||
162 | #define AR9170_TXRX_PHY_RATE_HT_MCS2 0x2 | ||
163 | #define AR9170_TXRX_PHY_RATE_HT_MCS3 0x3 | ||
164 | #define AR9170_TXRX_PHY_RATE_HT_MCS4 0x4 | ||
165 | #define AR9170_TXRX_PHY_RATE_HT_MCS5 0x5 | ||
166 | #define AR9170_TXRX_PHY_RATE_HT_MCS6 0x6 | ||
167 | #define AR9170_TXRX_PHY_RATE_HT_MCS7 0x7 | ||
168 | #define AR9170_TXRX_PHY_RATE_HT_MCS8 0x8 | ||
169 | #define AR9170_TXRX_PHY_RATE_HT_MCS9 0x9 | ||
170 | #define AR9170_TXRX_PHY_RATE_HT_MCS10 0xa | ||
171 | #define AR9170_TXRX_PHY_RATE_HT_MCS11 0xb | ||
172 | #define AR9170_TXRX_PHY_RATE_HT_MCS12 0xc | ||
173 | #define AR9170_TXRX_PHY_RATE_HT_MCS13 0xd | ||
174 | #define AR9170_TXRX_PHY_RATE_HT_MCS14 0xe | ||
175 | #define AR9170_TXRX_PHY_RATE_HT_MCS15 0xf | ||
176 | |||
177 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 | ||
178 | |||
179 | #ifdef __CARL9170FW__ | ||
180 | struct ar9170_tx_hw_mac_control { | ||
181 | union { | ||
182 | struct { | ||
183 | /* | ||
184 | * Beware of compiler bugs in all gcc pre 4.4! | ||
185 | */ | ||
186 | |||
187 | u8 erp_prot:2; | ||
188 | u8 no_ack:1; | ||
189 | u8 backoff:1; | ||
190 | u8 burst:1; | ||
191 | u8 ampdu:1; | ||
192 | |||
193 | u8 enc_mode:2; | ||
194 | |||
195 | u8 hw_mmic:1; | ||
196 | u8 hw_duration:1; | ||
197 | |||
198 | u8 qos_queue:2; | ||
199 | |||
200 | u8 disable_txop:1; | ||
201 | u8 txop_rifs:1; | ||
202 | |||
203 | u8 ba_end:1; | ||
204 | u8 probe:1; | ||
205 | } __packed; | ||
206 | |||
207 | __le16 set; | ||
208 | } __packed; | ||
209 | } __packed; | ||
210 | |||
211 | struct ar9170_tx_hw_phy_control { | ||
212 | union { | ||
213 | struct { | ||
214 | /* | ||
215 | * Beware of compiler bugs in all gcc pre 4.4! | ||
216 | */ | ||
217 | |||
218 | u8 modulation:2; | ||
219 | u8 preamble:1; | ||
220 | u8 bandwidth:2; | ||
221 | u8:1; | ||
222 | u8 heavy_clip:3; | ||
223 | u8 tx_power:6; | ||
224 | u8 chains:3; | ||
225 | u8 mcs:7; | ||
226 | u8:6; | ||
227 | u8 short_gi:1; | ||
228 | } __packed; | ||
229 | |||
230 | __le32 set; | ||
231 | } __packed; | ||
232 | } __packed; | ||
233 | |||
234 | struct ar9170_tx_rate_info { | ||
235 | u8 tries:3; | ||
236 | u8 erp_prot:2; | ||
237 | u8 ampdu:1; | ||
238 | u8 free:2; /* free for use (e.g.:RIFS/TXOP/AMPDU) */ | ||
239 | } __packed; | ||
240 | |||
241 | struct carl9170_tx_superdesc { | ||
242 | __le16 len; | ||
243 | u8 rix; | ||
244 | u8 cnt; | ||
245 | u8 cookie; | ||
246 | u8 ampdu_density:3; | ||
247 | u8 ampdu_factor:2; | ||
248 | u8 ampdu_commit_density:1; | ||
249 | u8 ampdu_commit_factor:1; | ||
250 | u8 ampdu_unused_bit:1; | ||
251 | u8 queue:2; | ||
252 | u8 reserved:1; | ||
253 | u8 vif_id:3; | ||
254 | u8 fill_in_tsf:1; | ||
255 | u8 cab:1; | ||
256 | u8 padding2; | ||
257 | struct ar9170_tx_rate_info ri[CARL9170_TX_MAX_RATES]; | ||
258 | struct ar9170_tx_hw_phy_control rr[CARL9170_TX_MAX_RETRY_RATES]; | ||
259 | } __packed; | ||
260 | |||
261 | struct ar9170_tx_hwdesc { | ||
262 | __le16 length; | ||
263 | struct ar9170_tx_hw_mac_control mac; | ||
264 | struct ar9170_tx_hw_phy_control phy; | ||
265 | } __packed; | ||
266 | |||
267 | struct ar9170_tx_frame { | ||
268 | struct ar9170_tx_hwdesc hdr; | ||
269 | |||
270 | union { | ||
271 | struct ieee80211_hdr i3e; | ||
272 | u8 payload[0]; | ||
273 | } data; | ||
274 | } __packed; | ||
275 | |||
276 | struct carl9170_tx_superframe { | ||
277 | struct carl9170_tx_superdesc s; | ||
278 | struct ar9170_tx_frame f; | ||
279 | } __packed; | ||
280 | |||
281 | #endif /* __CARL9170FW__ */ | ||
282 | |||
283 | struct _ar9170_tx_hwdesc { | ||
284 | __le16 length; | ||
285 | __le16 mac_control; | ||
286 | __le32 phy_control; | ||
287 | } __packed; | ||
288 | |||
289 | #define CARL9170_TX_SUPER_AMPDU_DENSITY_S 0 | ||
290 | #define CARL9170_TX_SUPER_AMPDU_DENSITY 0x7 | ||
291 | #define CARL9170_TX_SUPER_AMPDU_FACTOR 0x18 | ||
292 | #define CARL9170_TX_SUPER_AMPDU_FACTOR_S 3 | ||
293 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY 0x20 | ||
294 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY_S 5 | ||
295 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR 0x40 | ||
296 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR_S 6 | ||
297 | |||
298 | #define CARL9170_TX_SUPER_MISC_QUEUE 0x3 | ||
299 | #define CARL9170_TX_SUPER_MISC_QUEUE_S 0 | ||
300 | #define CARL9170_TX_SUPER_MISC_VIF_ID 0x38 | ||
301 | #define CARL9170_TX_SUPER_MISC_VIF_ID_S 3 | ||
302 | #define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40 | ||
303 | #define CARL9170_TX_SUPER_MISC_CAB 0x80 | ||
304 | |||
305 | #define CARL9170_TX_SUPER_RI_TRIES 0x7 | ||
306 | #define CARL9170_TX_SUPER_RI_TRIES_S 0 | ||
307 | #define CARL9170_TX_SUPER_RI_ERP_PROT 0x18 | ||
308 | #define CARL9170_TX_SUPER_RI_ERP_PROT_S 3 | ||
309 | #define CARL9170_TX_SUPER_RI_AMPDU 0x20 | ||
310 | #define CARL9170_TX_SUPER_RI_AMPDU_S 5 | ||
311 | |||
312 | struct _carl9170_tx_superdesc { | ||
313 | __le16 len; | ||
314 | u8 rix; | ||
315 | u8 cnt; | ||
316 | u8 cookie; | ||
317 | u8 ampdu_settings; | ||
318 | u8 misc; | ||
319 | u8 padding; | ||
320 | u8 ri[CARL9170_TX_MAX_RATES]; | ||
321 | __le32 rr[CARL9170_TX_MAX_RETRY_RATES]; | ||
322 | } __packed; | ||
323 | |||
324 | struct _carl9170_tx_superframe { | ||
325 | struct _carl9170_tx_superdesc s; | ||
326 | struct _ar9170_tx_hwdesc f; | ||
327 | u8 frame_data[0]; | ||
328 | } __packed; | ||
329 | |||
330 | #define CARL9170_TX_SUPERDESC_LEN 24 | ||
331 | #define AR9170_TX_HWDESC_LEN 8 | ||
332 | #define AR9170_TX_SUPERFRAME_LEN (CARL9170_TX_HWDESC_LEN + \ | ||
333 | AR9170_TX_SUPERDESC_LEN) | ||
334 | |||
335 | struct ar9170_rx_head { | ||
336 | u8 plcp[12]; | ||
337 | } __packed; | ||
338 | |||
339 | struct ar9170_rx_phystatus { | ||
340 | union { | ||
341 | struct { | ||
342 | u8 rssi_ant0, rssi_ant1, rssi_ant2, | ||
343 | rssi_ant0x, rssi_ant1x, rssi_ant2x, | ||
344 | rssi_combined; | ||
345 | } __packed; | ||
346 | u8 rssi[7]; | ||
347 | } __packed; | ||
348 | |||
349 | u8 evm_stream0[6], evm_stream1[6]; | ||
350 | u8 phy_err; | ||
351 | } __packed; | ||
352 | |||
353 | struct ar9170_rx_macstatus { | ||
354 | u8 SAidx, DAidx; | ||
355 | u8 error; | ||
356 | u8 status; | ||
357 | } __packed; | ||
358 | |||
359 | struct ar9170_rx_frame_single { | ||
360 | struct ar9170_rx_head phy_head; | ||
361 | struct ieee80211_hdr i3e; | ||
362 | struct ar9170_rx_phystatus phy_tail; | ||
363 | struct ar9170_rx_macstatus macstatus; | ||
364 | } __packed; | ||
365 | |||
366 | struct ar9170_rx_frame_head { | ||
367 | struct ar9170_rx_head phy_head; | ||
368 | struct ieee80211_hdr i3e; | ||
369 | struct ar9170_rx_macstatus macstatus; | ||
370 | } __packed; | ||
371 | |||
372 | struct ar9170_rx_frame_middle { | ||
373 | struct ieee80211_hdr i3e; | ||
374 | struct ar9170_rx_macstatus macstatus; | ||
375 | } __packed; | ||
376 | |||
377 | struct ar9170_rx_frame_tail { | ||
378 | struct ieee80211_hdr i3e; | ||
379 | struct ar9170_rx_phystatus phy_tail; | ||
380 | struct ar9170_rx_macstatus macstatus; | ||
381 | } __packed; | ||
382 | |||
383 | struct ar9170_rx_frame { | ||
384 | union { | ||
385 | struct ar9170_rx_frame_single single; | ||
386 | struct ar9170_rx_frame_head head; | ||
387 | struct ar9170_rx_frame_middle middle; | ||
388 | struct ar9170_rx_frame_tail tail; | ||
389 | } __packed; | ||
390 | } __packed; | ||
391 | |||
392 | static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) | ||
393 | { | ||
394 | return (t->SAidx & 0xc0) >> 4 | | ||
395 | (t->DAidx & 0xc0) >> 6; | ||
396 | } | ||
397 | |||
398 | enum ar9170_txq { | ||
399 | AR9170_TXQ_BE, | ||
400 | |||
401 | AR9170_TXQ_VI, | ||
402 | AR9170_TXQ_VO, | ||
403 | AR9170_TXQ_BK, | ||
404 | |||
405 | __AR9170_NUM_TXQ, | ||
406 | }; | ||
407 | |||
408 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 }; | ||
409 | |||
410 | #define AR9170_TXQ_DEPTH 32 | ||
411 | |||
412 | #endif /* __CARL9170_SHARED_WLAN_H */ | ||
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c new file mode 100644 index 000000000000..bd21a4d82085 --- /dev/null +++ b/drivers/net/wireless/ath/key.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009 Atheros Communications Inc. | ||
3 | * Copyright (c) 2010 Bruno Randolf <br1@einfach.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <asm/unaligned.h> | ||
19 | #include <net/mac80211.h> | ||
20 | |||
21 | #include "ath.h" | ||
22 | #include "reg.h" | ||
23 | #include "debug.h" | ||
24 | |||
25 | #define REG_READ (common->ops->read) | ||
26 | #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) | ||
27 | |||
28 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | ||
29 | |||
30 | /************************/ | ||
31 | /* Key Cache Management */ | ||
32 | /************************/ | ||
33 | |||
34 | bool ath_hw_keyreset(struct ath_common *common, u16 entry) | ||
35 | { | ||
36 | u32 keyType; | ||
37 | void *ah = common->ah; | ||
38 | |||
39 | if (entry >= common->keymax) { | ||
40 | ath_print(common, ATH_DBG_FATAL, | ||
41 | "keychache entry %u out of range\n", entry); | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | ||
46 | |||
47 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | ||
48 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
49 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
50 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
51 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
52 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
53 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
54 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
55 | |||
56 | if (keyType == AR_KEYTABLE_TYPE_TKIP) { | ||
57 | u16 micentry = entry + 64; | ||
58 | |||
59 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
60 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
61 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
62 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
63 | |||
64 | } | ||
65 | |||
66 | return true; | ||
67 | } | ||
68 | EXPORT_SYMBOL(ath_hw_keyreset); | ||
69 | |||
70 | bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac) | ||
71 | { | ||
72 | u32 macHi, macLo; | ||
73 | u32 unicast_flag = AR_KEYTABLE_VALID; | ||
74 | void *ah = common->ah; | ||
75 | |||
76 | if (entry >= common->keymax) { | ||
77 | ath_print(common, ATH_DBG_FATAL, | ||
78 | "keychache entry %u out of range\n", entry); | ||
79 | return false; | ||
80 | } | ||
81 | |||
82 | if (mac != NULL) { | ||
83 | /* | ||
84 | * AR_KEYTABLE_VALID indicates that the address is a unicast | ||
85 | * address, which must match the transmitter address for | ||
86 | * decrypting frames. | ||
87 | * Not setting this bit allows the hardware to use the key | ||
88 | * for multicast frame decryption. | ||
89 | */ | ||
90 | if (mac[0] & 0x01) | ||
91 | unicast_flag = 0; | ||
92 | |||
93 | macHi = (mac[5] << 8) | mac[4]; | ||
94 | macLo = (mac[3] << 24) | | ||
95 | (mac[2] << 16) | | ||
96 | (mac[1] << 8) | | ||
97 | mac[0]; | ||
98 | macLo >>= 1; | ||
99 | macLo |= (macHi & 1) << 31; | ||
100 | macHi >>= 1; | ||
101 | } else { | ||
102 | macLo = macHi = 0; | ||
103 | } | ||
104 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
105 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); | ||
106 | |||
107 | return true; | ||
108 | } | ||
109 | |||
110 | bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, | ||
111 | const struct ath_keyval *k, | ||
112 | const u8 *mac) | ||
113 | { | ||
114 | void *ah = common->ah; | ||
115 | u32 key0, key1, key2, key3, key4; | ||
116 | u32 keyType; | ||
117 | |||
118 | if (entry >= common->keymax) { | ||
119 | ath_print(common, ATH_DBG_FATAL, | ||
120 | "keycache entry %u out of range\n", entry); | ||
121 | return false; | ||
122 | } | ||
123 | |||
124 | switch (k->kv_type) { | ||
125 | case ATH_CIPHER_AES_OCB: | ||
126 | keyType = AR_KEYTABLE_TYPE_AES; | ||
127 | break; | ||
128 | case ATH_CIPHER_AES_CCM: | ||
129 | if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) { | ||
130 | ath_print(common, ATH_DBG_ANY, | ||
131 | "AES-CCM not supported by this mac rev\n"); | ||
132 | return false; | ||
133 | } | ||
134 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
135 | break; | ||
136 | case ATH_CIPHER_TKIP: | ||
137 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
138 | if (entry + 64 >= common->keymax) { | ||
139 | ath_print(common, ATH_DBG_ANY, | ||
140 | "entry %u inappropriate for TKIP\n", entry); | ||
141 | return false; | ||
142 | } | ||
143 | break; | ||
144 | case ATH_CIPHER_WEP: | ||
145 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { | ||
146 | ath_print(common, ATH_DBG_ANY, | ||
147 | "WEP key length %u too small\n", k->kv_len); | ||
148 | return false; | ||
149 | } | ||
150 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) | ||
151 | keyType = AR_KEYTABLE_TYPE_40; | ||
152 | else if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
153 | keyType = AR_KEYTABLE_TYPE_104; | ||
154 | else | ||
155 | keyType = AR_KEYTABLE_TYPE_128; | ||
156 | break; | ||
157 | case ATH_CIPHER_CLR: | ||
158 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
159 | break; | ||
160 | default: | ||
161 | ath_print(common, ATH_DBG_FATAL, | ||
162 | "cipher %u not supported\n", k->kv_type); | ||
163 | return false; | ||
164 | } | ||
165 | |||
166 | key0 = get_unaligned_le32(k->kv_val + 0); | ||
167 | key1 = get_unaligned_le16(k->kv_val + 4); | ||
168 | key2 = get_unaligned_le32(k->kv_val + 6); | ||
169 | key3 = get_unaligned_le16(k->kv_val + 10); | ||
170 | key4 = get_unaligned_le32(k->kv_val + 12); | ||
171 | if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
172 | key4 &= 0xff; | ||
173 | |||
174 | /* | ||
175 | * Note: Key cache registers access special memory area that requires | ||
176 | * two 32-bit writes to actually update the values in the internal | ||
177 | * memory. Consequently, the exact order and pairs used here must be | ||
178 | * maintained. | ||
179 | */ | ||
180 | |||
181 | if (keyType == AR_KEYTABLE_TYPE_TKIP) { | ||
182 | u16 micentry = entry + 64; | ||
183 | |||
184 | /* | ||
185 | * Write inverted key[47:0] first to avoid Michael MIC errors | ||
186 | * on frames that could be sent or received at the same time. | ||
187 | * The correct key will be written in the end once everything | ||
188 | * else is ready. | ||
189 | */ | ||
190 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
191 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
192 | |||
193 | /* Write key[95:48] */ | ||
194 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
195 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
196 | |||
197 | /* Write key[127:96] and key type */ | ||
198 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
199 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
200 | |||
201 | /* Write MAC address for the entry */ | ||
202 | (void) ath_hw_keysetmac(common, entry, mac); | ||
203 | |||
204 | if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { | ||
205 | /* | ||
206 | * TKIP uses two key cache entries: | ||
207 | * Michael MIC TX/RX keys in the same key cache entry | ||
208 | * (idx = main index + 64): | ||
209 | * key0 [31:0] = RX key [31:0] | ||
210 | * key1 [15:0] = TX key [31:16] | ||
211 | * key1 [31:16] = reserved | ||
212 | * key2 [31:0] = RX key [63:32] | ||
213 | * key3 [15:0] = TX key [15:0] | ||
214 | * key3 [31:16] = reserved | ||
215 | * key4 [31:0] = TX key [63:32] | ||
216 | */ | ||
217 | u32 mic0, mic1, mic2, mic3, mic4; | ||
218 | |||
219 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
220 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
221 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
222 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
223 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
224 | |||
225 | /* Write RX[31:0] and TX[31:16] */ | ||
226 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
227 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
228 | |||
229 | /* Write RX[63:32] and TX[15:0] */ | ||
230 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
231 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
232 | |||
233 | /* Write TX[63:32] and keyType(reserved) */ | ||
234 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
235 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
236 | AR_KEYTABLE_TYPE_CLR); | ||
237 | |||
238 | } else { | ||
239 | /* | ||
240 | * TKIP uses four key cache entries (two for group | ||
241 | * keys): | ||
242 | * Michael MIC TX/RX keys are in different key cache | ||
243 | * entries (idx = main index + 64 for TX and | ||
244 | * main index + 32 + 96 for RX): | ||
245 | * key0 [31:0] = TX/RX MIC key [31:0] | ||
246 | * key1 [31:0] = reserved | ||
247 | * key2 [31:0] = TX/RX MIC key [63:32] | ||
248 | * key3 [31:0] = reserved | ||
249 | * key4 [31:0] = reserved | ||
250 | * | ||
251 | * Upper layer code will call this function separately | ||
252 | * for TX and RX keys when these registers offsets are | ||
253 | * used. | ||
254 | */ | ||
255 | u32 mic0, mic2; | ||
256 | |||
257 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
258 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
259 | |||
260 | /* Write MIC key[31:0] */ | ||
261 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
262 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
263 | |||
264 | /* Write MIC key[63:32] */ | ||
265 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
266 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
267 | |||
268 | /* Write TX[63:32] and keyType(reserved) */ | ||
269 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
270 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
271 | AR_KEYTABLE_TYPE_CLR); | ||
272 | } | ||
273 | |||
274 | /* MAC address registers are reserved for the MIC entry */ | ||
275 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
276 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
277 | |||
278 | /* | ||
279 | * Write the correct (un-inverted) key[47:0] last to enable | ||
280 | * TKIP now that all other registers are set with correct | ||
281 | * values. | ||
282 | */ | ||
283 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
284 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
285 | } else { | ||
286 | /* Write key[47:0] */ | ||
287 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
288 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
289 | |||
290 | /* Write key[95:48] */ | ||
291 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
292 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
293 | |||
294 | /* Write key[127:96] and key type */ | ||
295 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
296 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
297 | |||
298 | /* Write MAC address for the entry */ | ||
299 | (void) ath_hw_keysetmac(common, entry, mac); | ||
300 | } | ||
301 | |||
302 | return true; | ||
303 | } | ||
304 | |||
305 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
306 | struct ath_keyval *hk, const u8 *addr, | ||
307 | bool authenticator) | ||
308 | { | ||
309 | const u8 *key_rxmic; | ||
310 | const u8 *key_txmic; | ||
311 | |||
312 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
313 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
314 | |||
315 | if (addr == NULL) { | ||
316 | /* | ||
317 | * Group key installation - only two key cache entries are used | ||
318 | * regardless of splitmic capability since group key is only | ||
319 | * used either for TX or RX. | ||
320 | */ | ||
321 | if (authenticator) { | ||
322 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
323 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
324 | } else { | ||
325 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
326 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
327 | } | ||
328 | return ath_hw_set_keycache_entry(common, keyix, hk, addr); | ||
329 | } | ||
330 | if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { | ||
331 | /* TX and RX keys share the same key cache entry. */ | ||
332 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
333 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
334 | return ath_hw_set_keycache_entry(common, keyix, hk, addr); | ||
335 | } | ||
336 | |||
337 | /* Separate key cache entries for TX and RX */ | ||
338 | |||
339 | /* TX key goes at first index, RX key at +32. */ | ||
340 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
341 | if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) { | ||
342 | /* TX MIC entry failed. No need to proceed further */ | ||
343 | ath_print(common, ATH_DBG_FATAL, | ||
344 | "Setting TX MIC Key Failed\n"); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
349 | /* XXX delete tx key on failure? */ | ||
350 | return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr); | ||
351 | } | ||
352 | |||
353 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
354 | { | ||
355 | int i; | ||
356 | |||
357 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
358 | if (test_bit(i, common->keymap) || | ||
359 | test_bit(i + 64, common->keymap)) | ||
360 | continue; /* At least one part of TKIP key allocated */ | ||
361 | if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) && | ||
362 | (test_bit(i + 32, common->keymap) || | ||
363 | test_bit(i + 64 + 32, common->keymap))) | ||
364 | continue; /* At least one part of TKIP key allocated */ | ||
365 | |||
366 | /* Found a free slot for a TKIP key */ | ||
367 | return i; | ||
368 | } | ||
369 | return -1; | ||
370 | } | ||
371 | |||
372 | static int ath_reserve_key_cache_slot(struct ath_common *common, | ||
373 | u32 cipher) | ||
374 | { | ||
375 | int i; | ||
376 | |||
377 | if (cipher == WLAN_CIPHER_SUITE_TKIP) | ||
378 | return ath_reserve_key_cache_slot_tkip(common); | ||
379 | |||
380 | /* First, try to find slots that would not be available for TKIP. */ | ||
381 | if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { | ||
382 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
383 | if (!test_bit(i, common->keymap) && | ||
384 | (test_bit(i + 32, common->keymap) || | ||
385 | test_bit(i + 64, common->keymap) || | ||
386 | test_bit(i + 64 + 32, common->keymap))) | ||
387 | return i; | ||
388 | if (!test_bit(i + 32, common->keymap) && | ||
389 | (test_bit(i, common->keymap) || | ||
390 | test_bit(i + 64, common->keymap) || | ||
391 | test_bit(i + 64 + 32, common->keymap))) | ||
392 | return i + 32; | ||
393 | if (!test_bit(i + 64, common->keymap) && | ||
394 | (test_bit(i , common->keymap) || | ||
395 | test_bit(i + 32, common->keymap) || | ||
396 | test_bit(i + 64 + 32, common->keymap))) | ||
397 | return i + 64; | ||
398 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
399 | (test_bit(i, common->keymap) || | ||
400 | test_bit(i + 32, common->keymap) || | ||
401 | test_bit(i + 64, common->keymap))) | ||
402 | return i + 64 + 32; | ||
403 | } | ||
404 | } else { | ||
405 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
406 | if (!test_bit(i, common->keymap) && | ||
407 | test_bit(i + 64, common->keymap)) | ||
408 | return i; | ||
409 | if (test_bit(i, common->keymap) && | ||
410 | !test_bit(i + 64, common->keymap)) | ||
411 | return i + 64; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | /* No partially used TKIP slots, pick any available slot */ | ||
416 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
417 | /* Do not allow slots that could be needed for TKIP group keys | ||
418 | * to be used. This limitation could be removed if we know that | ||
419 | * TKIP will not be used. */ | ||
420 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
421 | continue; | ||
422 | if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { | ||
423 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
424 | continue; | ||
425 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
426 | continue; | ||
427 | } | ||
428 | |||
429 | if (!test_bit(i, common->keymap)) | ||
430 | return i; /* Found a free slot for a key */ | ||
431 | } | ||
432 | |||
433 | /* No free slot found */ | ||
434 | return -1; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * Configure encryption in the HW. | ||
439 | */ | ||
440 | int ath_key_config(struct ath_common *common, | ||
441 | struct ieee80211_vif *vif, | ||
442 | struct ieee80211_sta *sta, | ||
443 | struct ieee80211_key_conf *key) | ||
444 | { | ||
445 | struct ath_keyval hk; | ||
446 | const u8 *mac = NULL; | ||
447 | u8 gmac[ETH_ALEN]; | ||
448 | int ret = 0; | ||
449 | int idx; | ||
450 | |||
451 | memset(&hk, 0, sizeof(hk)); | ||
452 | |||
453 | switch (key->cipher) { | ||
454 | case WLAN_CIPHER_SUITE_WEP40: | ||
455 | case WLAN_CIPHER_SUITE_WEP104: | ||
456 | hk.kv_type = ATH_CIPHER_WEP; | ||
457 | break; | ||
458 | case WLAN_CIPHER_SUITE_TKIP: | ||
459 | hk.kv_type = ATH_CIPHER_TKIP; | ||
460 | break; | ||
461 | case WLAN_CIPHER_SUITE_CCMP: | ||
462 | hk.kv_type = ATH_CIPHER_AES_CCM; | ||
463 | break; | ||
464 | default: | ||
465 | return -EOPNOTSUPP; | ||
466 | } | ||
467 | |||
468 | hk.kv_len = key->keylen; | ||
469 | memcpy(hk.kv_val, key->key, key->keylen); | ||
470 | |||
471 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
472 | switch (vif->type) { | ||
473 | case NL80211_IFTYPE_AP: | ||
474 | memcpy(gmac, vif->addr, ETH_ALEN); | ||
475 | gmac[0] |= 0x01; | ||
476 | mac = gmac; | ||
477 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
478 | break; | ||
479 | case NL80211_IFTYPE_ADHOC: | ||
480 | if (!sta) { | ||
481 | idx = key->keyidx; | ||
482 | break; | ||
483 | } | ||
484 | memcpy(gmac, sta->addr, ETH_ALEN); | ||
485 | gmac[0] |= 0x01; | ||
486 | mac = gmac; | ||
487 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
488 | break; | ||
489 | default: | ||
490 | idx = key->keyidx; | ||
491 | break; | ||
492 | } | ||
493 | } else if (key->keyidx) { | ||
494 | if (WARN_ON(!sta)) | ||
495 | return -EOPNOTSUPP; | ||
496 | mac = sta->addr; | ||
497 | |||
498 | if (vif->type != NL80211_IFTYPE_AP) { | ||
499 | /* Only keyidx 0 should be used with unicast key, but | ||
500 | * allow this for client mode for now. */ | ||
501 | idx = key->keyidx; | ||
502 | } else | ||
503 | return -EIO; | ||
504 | } else { | ||
505 | if (WARN_ON(!sta)) | ||
506 | return -EOPNOTSUPP; | ||
507 | mac = sta->addr; | ||
508 | |||
509 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
510 | } | ||
511 | |||
512 | if (idx < 0) | ||
513 | return -ENOSPC; /* no free key cache entries */ | ||
514 | |||
515 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
516 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
517 | vif->type == NL80211_IFTYPE_AP); | ||
518 | else | ||
519 | ret = ath_hw_set_keycache_entry(common, idx, &hk, mac); | ||
520 | |||
521 | if (!ret) | ||
522 | return -EIO; | ||
523 | |||
524 | set_bit(idx, common->keymap); | ||
525 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
526 | set_bit(idx + 64, common->keymap); | ||
527 | set_bit(idx, common->tkip_keymap); | ||
528 | set_bit(idx + 64, common->tkip_keymap); | ||
529 | if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { | ||
530 | set_bit(idx + 32, common->keymap); | ||
531 | set_bit(idx + 64 + 32, common->keymap); | ||
532 | set_bit(idx + 32, common->tkip_keymap); | ||
533 | set_bit(idx + 64 + 32, common->tkip_keymap); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | return idx; | ||
538 | } | ||
539 | EXPORT_SYMBOL(ath_key_config); | ||
540 | |||
541 | /* | ||
542 | * Delete Key. | ||
543 | */ | ||
544 | void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) | ||
545 | { | ||
546 | ath_hw_keyreset(common, key->hw_key_idx); | ||
547 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
548 | return; | ||
549 | |||
550 | clear_bit(key->hw_key_idx, common->keymap); | ||
551 | if (key->cipher != WLAN_CIPHER_SUITE_TKIP) | ||
552 | return; | ||
553 | |||
554 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
555 | |||
556 | clear_bit(key->hw_key_idx, common->tkip_keymap); | ||
557 | clear_bit(key->hw_key_idx + 64, common->tkip_keymap); | ||
558 | |||
559 | if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { | ||
560 | ath_hw_keyreset(common, key->hw_key_idx + 32); | ||
561 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
562 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
563 | |||
564 | clear_bit(key->hw_key_idx + 32, common->tkip_keymap); | ||
565 | clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); | ||
566 | } | ||
567 | } | ||
568 | EXPORT_SYMBOL(ath_key_delete); | ||
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h index dfe1fbec24f5..e798ef476581 100644 --- a/drivers/net/wireless/ath/reg.h +++ b/drivers/net/wireless/ath/reg.h | |||
@@ -24,4 +24,27 @@ | |||
24 | #define AR_BSSMSKL 0x80e0 | 24 | #define AR_BSSMSKL 0x80e0 |
25 | #define AR_BSSMSKU 0x80e4 | 25 | #define AR_BSSMSKU 0x80e4 |
26 | 26 | ||
27 | #define AR_KEYTABLE_0 0x8800 | ||
28 | #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) | ||
29 | #define AR_KEY_CACHE_SIZE 128 | ||
30 | #define AR_RSVD_KEYTABLE_ENTRIES 4 | ||
31 | #define AR_KEY_TYPE 0x00000007 | ||
32 | #define AR_KEYTABLE_TYPE_40 0x00000000 | ||
33 | #define AR_KEYTABLE_TYPE_104 0x00000001 | ||
34 | #define AR_KEYTABLE_TYPE_128 0x00000003 | ||
35 | #define AR_KEYTABLE_TYPE_TKIP 0x00000004 | ||
36 | #define AR_KEYTABLE_TYPE_AES 0x00000005 | ||
37 | #define AR_KEYTABLE_TYPE_CCM 0x00000006 | ||
38 | #define AR_KEYTABLE_TYPE_CLR 0x00000007 | ||
39 | #define AR_KEYTABLE_ANT 0x00000008 | ||
40 | #define AR_KEYTABLE_VALID 0x00008000 | ||
41 | #define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) | ||
42 | #define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) | ||
43 | #define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) | ||
44 | #define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) | ||
45 | #define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) | ||
46 | #define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) | ||
47 | #define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) | ||
48 | #define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) | ||
49 | |||
27 | #endif /* ATH_REGISTERS_H */ | 50 | #endif /* ATH_REGISTERS_H */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 674fb93ae17f..56ef4ed0db47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -223,6 +223,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
223 | .tx_stats_read = iwl_ucode_tx_stats_read, | 223 | .tx_stats_read = iwl_ucode_tx_stats_read, |
224 | .general_stats_read = iwl_ucode_general_stats_read, | 224 | .general_stats_read = iwl_ucode_general_stats_read, |
225 | .bt_stats_read = iwl_ucode_bt_stats_read, | 225 | .bt_stats_read = iwl_ucode_bt_stats_read, |
226 | .reply_tx_error = iwl_reply_tx_error_read, | ||
226 | }, | 227 | }, |
227 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 228 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
228 | .check_plcp_health = iwl_good_plcp_health, | 229 | .check_plcp_health = iwl_good_plcp_health, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index bb2aeebf3652..98509c5e708d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -295,7 +295,7 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info( | |||
295 | extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); | 295 | extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); |
296 | 296 | ||
297 | /* scanning */ | 297 | /* scanning */ |
298 | void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | 298 | int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); |
299 | 299 | ||
300 | /* Requires full declaration of iwl_priv before including */ | 300 | /* Requires full declaration of iwl_priv before including */ |
301 | #include "iwl-io.h" | 301 | #include "iwl-io.h" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1d6a46d4db59..943a9c7bfa7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2289,6 +2289,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2289 | .tx_stats_read = iwl_ucode_tx_stats_read, | 2289 | .tx_stats_read = iwl_ucode_tx_stats_read, |
2290 | .general_stats_read = iwl_ucode_general_stats_read, | 2290 | .general_stats_read = iwl_ucode_general_stats_read, |
2291 | .bt_stats_read = iwl_ucode_bt_stats_read, | 2291 | .bt_stats_read = iwl_ucode_bt_stats_read, |
2292 | .reply_tx_error = iwl_reply_tx_error_read, | ||
2292 | }, | 2293 | }, |
2293 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 2294 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
2294 | .check_plcp_health = iwl_good_plcp_health, | 2295 | .check_plcp_health = iwl_good_plcp_health, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1dbb1246c083..21b4b23368e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -404,6 +404,7 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
404 | .tx_stats_read = iwl_ucode_tx_stats_read, | 404 | .tx_stats_read = iwl_ucode_tx_stats_read, |
405 | .general_stats_read = iwl_ucode_general_stats_read, | 405 | .general_stats_read = iwl_ucode_general_stats_read, |
406 | .bt_stats_read = iwl_ucode_bt_stats_read, | 406 | .bt_stats_read = iwl_ucode_bt_stats_read, |
407 | .reply_tx_error = iwl_reply_tx_error_read, | ||
407 | }, | 408 | }, |
408 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 409 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
409 | .check_plcp_health = iwl_good_plcp_health, | 410 | .check_plcp_health = iwl_good_plcp_health, |
@@ -474,6 +475,8 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
474 | .rx_stats_read = iwl_ucode_rx_stats_read, | 475 | .rx_stats_read = iwl_ucode_rx_stats_read, |
475 | .tx_stats_read = iwl_ucode_tx_stats_read, | 476 | .tx_stats_read = iwl_ucode_tx_stats_read, |
476 | .general_stats_read = iwl_ucode_general_stats_read, | 477 | .general_stats_read = iwl_ucode_general_stats_read, |
478 | .bt_stats_read = iwl_ucode_bt_stats_read, | ||
479 | .reply_tx_error = iwl_reply_tx_error_read, | ||
477 | }, | 480 | }, |
478 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 481 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
479 | .check_plcp_health = iwl_good_plcp_health, | 482 | .check_plcp_health = iwl_good_plcp_health, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 2fdba088bd27..9f43f2770c96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -329,6 +329,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
329 | .tx_stats_read = iwl_ucode_tx_stats_read, | 329 | .tx_stats_read = iwl_ucode_tx_stats_read, |
330 | .general_stats_read = iwl_ucode_general_stats_read, | 330 | .general_stats_read = iwl_ucode_general_stats_read, |
331 | .bt_stats_read = iwl_ucode_bt_stats_read, | 331 | .bt_stats_read = iwl_ucode_bt_stats_read, |
332 | .reply_tx_error = iwl_reply_tx_error_read, | ||
332 | }, | 333 | }, |
333 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 334 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
334 | .check_plcp_health = iwl_good_plcp_health, | 335 | .check_plcp_health = iwl_good_plcp_health, |
@@ -404,6 +405,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = { | |||
404 | .tx_stats_read = iwl_ucode_tx_stats_read, | 405 | .tx_stats_read = iwl_ucode_tx_stats_read, |
405 | .general_stats_read = iwl_ucode_general_stats_read, | 406 | .general_stats_read = iwl_ucode_general_stats_read, |
406 | .bt_stats_read = iwl_ucode_bt_stats_read, | 407 | .bt_stats_read = iwl_ucode_bt_stats_read, |
408 | .reply_tx_error = iwl_reply_tx_error_read, | ||
407 | }, | 409 | }, |
408 | .recover_from_tx_stall = iwl_bg_monitor_recover, | 410 | .recover_from_tx_stall = iwl_bg_monitor_recover, |
409 | .check_plcp_health = iwl_good_plcp_health, | 411 | .check_plcp_health = iwl_good_plcp_health, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index d706b8afbe5a..5391b4627397 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -25,9 +25,15 @@ | |||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | 28 | #include "iwl-agn.h" | |
29 | #include "iwl-agn-debugfs.h" | 29 | #include "iwl-agn-debugfs.h" |
30 | 30 | ||
31 | static const char *fmt_value = " %-30s %10u\n"; | ||
32 | static const char *fmt_hex = " %-30s 0x%02X\n"; | ||
33 | static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; | ||
34 | static const char *fmt_header = | ||
35 | "%-32s current cumulative delta max\n"; | ||
36 | |||
31 | static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | 37 | static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) |
32 | { | 38 | { |
33 | int p = 0; | 39 | int p = 0; |
@@ -121,436 +127,380 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
121 | } | 127 | } |
122 | 128 | ||
123 | pos += iwl_statistics_flag(priv, buf, bufsz); | 129 | pos += iwl_statistics_flag(priv, buf, bufsz); |
124 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
125 | "acumulative delta max\n", | ||
126 | "Statistics_Rx - OFDM:"); | ||
127 | pos += scnprintf(buf + pos, bufsz - pos, | 130 | pos += scnprintf(buf + pos, bufsz - pos, |
128 | " %-30s %10u %10u %10u %10u\n", | 131 | fmt_header, "Statistics_Rx - OFDM:"); |
129 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), | 132 | pos += scnprintf(buf + pos, bufsz - pos, |
133 | fmt_table, "ina_cnt:", | ||
134 | le32_to_cpu(ofdm->ina_cnt), | ||
130 | accum_ofdm->ina_cnt, | 135 | accum_ofdm->ina_cnt, |
131 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); | 136 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); |
132 | pos += scnprintf(buf + pos, bufsz - pos, | 137 | pos += scnprintf(buf + pos, bufsz - pos, |
133 | " %-30s %10u %10u %10u %10u\n", | 138 | fmt_table, "fina_cnt:", |
134 | "fina_cnt:", | ||
135 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, | 139 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, |
136 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); | 140 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); |
137 | pos += scnprintf(buf + pos, bufsz - pos, | 141 | pos += scnprintf(buf + pos, bufsz - pos, |
138 | " %-30s %10u %10u %10u %10u\n", | 142 | fmt_table, "plcp_err:", |
139 | "plcp_err:", | ||
140 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, | 143 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, |
141 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | 144 | delta_ofdm->plcp_err, max_ofdm->plcp_err); |
142 | pos += scnprintf(buf + pos, bufsz - pos, | 145 | pos += scnprintf(buf + pos, bufsz - pos, |
143 | " %-30s %10u %10u %10u %10u\n", "crc32_err:", | 146 | fmt_table, "crc32_err:", |
144 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | 147 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, |
145 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | 148 | delta_ofdm->crc32_err, max_ofdm->crc32_err); |
146 | pos += scnprintf(buf + pos, bufsz - pos, | 149 | pos += scnprintf(buf + pos, bufsz - pos, |
147 | " %-30s %10u %10u %10u %10u\n", "overrun_err:", | 150 | fmt_table, "overrun_err:", |
148 | le32_to_cpu(ofdm->overrun_err), | 151 | le32_to_cpu(ofdm->overrun_err), |
149 | accum_ofdm->overrun_err, delta_ofdm->overrun_err, | 152 | accum_ofdm->overrun_err, delta_ofdm->overrun_err, |
150 | max_ofdm->overrun_err); | 153 | max_ofdm->overrun_err); |
151 | pos += scnprintf(buf + pos, bufsz - pos, | 154 | pos += scnprintf(buf + pos, bufsz - pos, |
152 | " %-30s %10u %10u %10u %10u\n", | 155 | fmt_table, "early_overrun_err:", |
153 | "early_overrun_err:", | ||
154 | le32_to_cpu(ofdm->early_overrun_err), | 156 | le32_to_cpu(ofdm->early_overrun_err), |
155 | accum_ofdm->early_overrun_err, | 157 | accum_ofdm->early_overrun_err, |
156 | delta_ofdm->early_overrun_err, | 158 | delta_ofdm->early_overrun_err, |
157 | max_ofdm->early_overrun_err); | 159 | max_ofdm->early_overrun_err); |
158 | pos += scnprintf(buf + pos, bufsz - pos, | 160 | pos += scnprintf(buf + pos, bufsz - pos, |
159 | " %-30s %10u %10u %10u %10u\n", | 161 | fmt_table, "crc32_good:", |
160 | "crc32_good:", le32_to_cpu(ofdm->crc32_good), | 162 | le32_to_cpu(ofdm->crc32_good), |
161 | accum_ofdm->crc32_good, delta_ofdm->crc32_good, | 163 | accum_ofdm->crc32_good, delta_ofdm->crc32_good, |
162 | max_ofdm->crc32_good); | 164 | max_ofdm->crc32_good); |
163 | pos += scnprintf(buf + pos, bufsz - pos, | 165 | pos += scnprintf(buf + pos, bufsz - pos, |
164 | " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", | 166 | fmt_table, "false_alarm_cnt:", |
165 | le32_to_cpu(ofdm->false_alarm_cnt), | 167 | le32_to_cpu(ofdm->false_alarm_cnt), |
166 | accum_ofdm->false_alarm_cnt, | 168 | accum_ofdm->false_alarm_cnt, |
167 | delta_ofdm->false_alarm_cnt, | 169 | delta_ofdm->false_alarm_cnt, |
168 | max_ofdm->false_alarm_cnt); | 170 | max_ofdm->false_alarm_cnt); |
169 | pos += scnprintf(buf + pos, bufsz - pos, | 171 | pos += scnprintf(buf + pos, bufsz - pos, |
170 | " %-30s %10u %10u %10u %10u\n", | 172 | fmt_table, "fina_sync_err_cnt:", |
171 | "fina_sync_err_cnt:", | ||
172 | le32_to_cpu(ofdm->fina_sync_err_cnt), | 173 | le32_to_cpu(ofdm->fina_sync_err_cnt), |
173 | accum_ofdm->fina_sync_err_cnt, | 174 | accum_ofdm->fina_sync_err_cnt, |
174 | delta_ofdm->fina_sync_err_cnt, | 175 | delta_ofdm->fina_sync_err_cnt, |
175 | max_ofdm->fina_sync_err_cnt); | 176 | max_ofdm->fina_sync_err_cnt); |
176 | pos += scnprintf(buf + pos, bufsz - pos, | 177 | pos += scnprintf(buf + pos, bufsz - pos, |
177 | " %-30s %10u %10u %10u %10u\n", "sfd_timeout:", | 178 | fmt_table, "sfd_timeout:", |
178 | le32_to_cpu(ofdm->sfd_timeout), | 179 | le32_to_cpu(ofdm->sfd_timeout), |
179 | accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, | 180 | accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, |
180 | max_ofdm->sfd_timeout); | 181 | max_ofdm->sfd_timeout); |
181 | pos += scnprintf(buf + pos, bufsz - pos, | 182 | pos += scnprintf(buf + pos, bufsz - pos, |
182 | " %-30s %10u %10u %10u %10u\n", "fina_timeout:", | 183 | fmt_table, "fina_timeout:", |
183 | le32_to_cpu(ofdm->fina_timeout), | 184 | le32_to_cpu(ofdm->fina_timeout), |
184 | accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, | 185 | accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, |
185 | max_ofdm->fina_timeout); | 186 | max_ofdm->fina_timeout); |
186 | pos += scnprintf(buf + pos, bufsz - pos, | 187 | pos += scnprintf(buf + pos, bufsz - pos, |
187 | " %-30s %10u %10u %10u %10u\n", | 188 | fmt_table, "unresponded_rts:", |
188 | "unresponded_rts:", | ||
189 | le32_to_cpu(ofdm->unresponded_rts), | 189 | le32_to_cpu(ofdm->unresponded_rts), |
190 | accum_ofdm->unresponded_rts, | 190 | accum_ofdm->unresponded_rts, |
191 | delta_ofdm->unresponded_rts, | 191 | delta_ofdm->unresponded_rts, |
192 | max_ofdm->unresponded_rts); | 192 | max_ofdm->unresponded_rts); |
193 | pos += scnprintf(buf + pos, bufsz - pos, | 193 | pos += scnprintf(buf + pos, bufsz - pos, |
194 | " %-30s %10u %10u %10u %10u\n", | 194 | fmt_table, "rxe_frame_lmt_ovrun:", |
195 | "rxe_frame_lmt_ovrun:", | ||
196 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | 195 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), |
197 | accum_ofdm->rxe_frame_limit_overrun, | 196 | accum_ofdm->rxe_frame_limit_overrun, |
198 | delta_ofdm->rxe_frame_limit_overrun, | 197 | delta_ofdm->rxe_frame_limit_overrun, |
199 | max_ofdm->rxe_frame_limit_overrun); | 198 | max_ofdm->rxe_frame_limit_overrun); |
200 | pos += scnprintf(buf + pos, bufsz - pos, | 199 | pos += scnprintf(buf + pos, bufsz - pos, |
201 | " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", | 200 | fmt_table, "sent_ack_cnt:", |
202 | le32_to_cpu(ofdm->sent_ack_cnt), | 201 | le32_to_cpu(ofdm->sent_ack_cnt), |
203 | accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, | 202 | accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, |
204 | max_ofdm->sent_ack_cnt); | 203 | max_ofdm->sent_ack_cnt); |
205 | pos += scnprintf(buf + pos, bufsz - pos, | 204 | pos += scnprintf(buf + pos, bufsz - pos, |
206 | " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", | 205 | fmt_table, "sent_cts_cnt:", |
207 | le32_to_cpu(ofdm->sent_cts_cnt), | 206 | le32_to_cpu(ofdm->sent_cts_cnt), |
208 | accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, | 207 | accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, |
209 | max_ofdm->sent_cts_cnt); | 208 | max_ofdm->sent_cts_cnt); |
210 | pos += scnprintf(buf + pos, bufsz - pos, | 209 | pos += scnprintf(buf + pos, bufsz - pos, |
211 | " %-30s %10u %10u %10u %10u\n", | 210 | fmt_table, "sent_ba_rsp_cnt:", |
212 | "sent_ba_rsp_cnt:", | ||
213 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), | 211 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), |
214 | accum_ofdm->sent_ba_rsp_cnt, | 212 | accum_ofdm->sent_ba_rsp_cnt, |
215 | delta_ofdm->sent_ba_rsp_cnt, | 213 | delta_ofdm->sent_ba_rsp_cnt, |
216 | max_ofdm->sent_ba_rsp_cnt); | 214 | max_ofdm->sent_ba_rsp_cnt); |
217 | pos += scnprintf(buf + pos, bufsz - pos, | 215 | pos += scnprintf(buf + pos, bufsz - pos, |
218 | " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", | 216 | fmt_table, "dsp_self_kill:", |
219 | le32_to_cpu(ofdm->dsp_self_kill), | 217 | le32_to_cpu(ofdm->dsp_self_kill), |
220 | accum_ofdm->dsp_self_kill, | 218 | accum_ofdm->dsp_self_kill, |
221 | delta_ofdm->dsp_self_kill, | 219 | delta_ofdm->dsp_self_kill, |
222 | max_ofdm->dsp_self_kill); | 220 | max_ofdm->dsp_self_kill); |
223 | pos += scnprintf(buf + pos, bufsz - pos, | 221 | pos += scnprintf(buf + pos, bufsz - pos, |
224 | " %-30s %10u %10u %10u %10u\n", | 222 | fmt_table, "mh_format_err:", |
225 | "mh_format_err:", | ||
226 | le32_to_cpu(ofdm->mh_format_err), | 223 | le32_to_cpu(ofdm->mh_format_err), |
227 | accum_ofdm->mh_format_err, | 224 | accum_ofdm->mh_format_err, |
228 | delta_ofdm->mh_format_err, | 225 | delta_ofdm->mh_format_err, |
229 | max_ofdm->mh_format_err); | 226 | max_ofdm->mh_format_err); |
230 | pos += scnprintf(buf + pos, bufsz - pos, | 227 | pos += scnprintf(buf + pos, bufsz - pos, |
231 | " %-30s %10u %10u %10u %10u\n", | 228 | fmt_table, "re_acq_main_rssi_sum:", |
232 | "re_acq_main_rssi_sum:", | ||
233 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), | 229 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), |
234 | accum_ofdm->re_acq_main_rssi_sum, | 230 | accum_ofdm->re_acq_main_rssi_sum, |
235 | delta_ofdm->re_acq_main_rssi_sum, | 231 | delta_ofdm->re_acq_main_rssi_sum, |
236 | max_ofdm->re_acq_main_rssi_sum); | 232 | max_ofdm->re_acq_main_rssi_sum); |
237 | 233 | ||
238 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
239 | "acumulative delta max\n", | ||
240 | "Statistics_Rx - CCK:"); | ||
241 | pos += scnprintf(buf + pos, bufsz - pos, | 234 | pos += scnprintf(buf + pos, bufsz - pos, |
242 | " %-30s %10u %10u %10u %10u\n", | 235 | fmt_header, "Statistics_Rx - CCK:"); |
243 | "ina_cnt:", | 236 | pos += scnprintf(buf + pos, bufsz - pos, |
237 | fmt_table, "ina_cnt:", | ||
244 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, | 238 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, |
245 | delta_cck->ina_cnt, max_cck->ina_cnt); | 239 | delta_cck->ina_cnt, max_cck->ina_cnt); |
246 | pos += scnprintf(buf + pos, bufsz - pos, | 240 | pos += scnprintf(buf + pos, bufsz - pos, |
247 | " %-30s %10u %10u %10u %10u\n", | 241 | fmt_table, "fina_cnt:", |
248 | "fina_cnt:", | ||
249 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, | 242 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, |
250 | delta_cck->fina_cnt, max_cck->fina_cnt); | 243 | delta_cck->fina_cnt, max_cck->fina_cnt); |
251 | pos += scnprintf(buf + pos, bufsz - pos, | 244 | pos += scnprintf(buf + pos, bufsz - pos, |
252 | " %-30s %10u %10u %10u %10u\n", | 245 | fmt_table, "plcp_err:", |
253 | "plcp_err:", | ||
254 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | 246 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, |
255 | delta_cck->plcp_err, max_cck->plcp_err); | 247 | delta_cck->plcp_err, max_cck->plcp_err); |
256 | pos += scnprintf(buf + pos, bufsz - pos, | 248 | pos += scnprintf(buf + pos, bufsz - pos, |
257 | " %-30s %10u %10u %10u %10u\n", | 249 | fmt_table, "crc32_err:", |
258 | "crc32_err:", | ||
259 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | 250 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, |
260 | delta_cck->crc32_err, max_cck->crc32_err); | 251 | delta_cck->crc32_err, max_cck->crc32_err); |
261 | pos += scnprintf(buf + pos, bufsz - pos, | 252 | pos += scnprintf(buf + pos, bufsz - pos, |
262 | " %-30s %10u %10u %10u %10u\n", | 253 | fmt_table, "overrun_err:", |
263 | "overrun_err:", | ||
264 | le32_to_cpu(cck->overrun_err), | 254 | le32_to_cpu(cck->overrun_err), |
265 | accum_cck->overrun_err, delta_cck->overrun_err, | 255 | accum_cck->overrun_err, delta_cck->overrun_err, |
266 | max_cck->overrun_err); | 256 | max_cck->overrun_err); |
267 | pos += scnprintf(buf + pos, bufsz - pos, | 257 | pos += scnprintf(buf + pos, bufsz - pos, |
268 | " %-30s %10u %10u %10u %10u\n", | 258 | fmt_table, "early_overrun_err:", |
269 | "early_overrun_err:", | ||
270 | le32_to_cpu(cck->early_overrun_err), | 259 | le32_to_cpu(cck->early_overrun_err), |
271 | accum_cck->early_overrun_err, | 260 | accum_cck->early_overrun_err, |
272 | delta_cck->early_overrun_err, | 261 | delta_cck->early_overrun_err, |
273 | max_cck->early_overrun_err); | 262 | max_cck->early_overrun_err); |
274 | pos += scnprintf(buf + pos, bufsz - pos, | 263 | pos += scnprintf(buf + pos, bufsz - pos, |
275 | " %-30s %10u %10u %10u %10u\n", | 264 | fmt_table, "crc32_good:", |
276 | "crc32_good:", | ||
277 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | 265 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, |
278 | delta_cck->crc32_good, max_cck->crc32_good); | 266 | delta_cck->crc32_good, max_cck->crc32_good); |
279 | pos += scnprintf(buf + pos, bufsz - pos, | 267 | pos += scnprintf(buf + pos, bufsz - pos, |
280 | " %-30s %10u %10u %10u %10u\n", | 268 | fmt_table, "false_alarm_cnt:", |
281 | "false_alarm_cnt:", | ||
282 | le32_to_cpu(cck->false_alarm_cnt), | 269 | le32_to_cpu(cck->false_alarm_cnt), |
283 | accum_cck->false_alarm_cnt, | 270 | accum_cck->false_alarm_cnt, |
284 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); | 271 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); |
285 | pos += scnprintf(buf + pos, bufsz - pos, | 272 | pos += scnprintf(buf + pos, bufsz - pos, |
286 | " %-30s %10u %10u %10u %10u\n", | 273 | fmt_table, "fina_sync_err_cnt:", |
287 | "fina_sync_err_cnt:", | ||
288 | le32_to_cpu(cck->fina_sync_err_cnt), | 274 | le32_to_cpu(cck->fina_sync_err_cnt), |
289 | accum_cck->fina_sync_err_cnt, | 275 | accum_cck->fina_sync_err_cnt, |
290 | delta_cck->fina_sync_err_cnt, | 276 | delta_cck->fina_sync_err_cnt, |
291 | max_cck->fina_sync_err_cnt); | 277 | max_cck->fina_sync_err_cnt); |
292 | pos += scnprintf(buf + pos, bufsz - pos, | 278 | pos += scnprintf(buf + pos, bufsz - pos, |
293 | " %-30s %10u %10u %10u %10u\n", | 279 | fmt_table, "sfd_timeout:", |
294 | "sfd_timeout:", | ||
295 | le32_to_cpu(cck->sfd_timeout), | 280 | le32_to_cpu(cck->sfd_timeout), |
296 | accum_cck->sfd_timeout, delta_cck->sfd_timeout, | 281 | accum_cck->sfd_timeout, delta_cck->sfd_timeout, |
297 | max_cck->sfd_timeout); | 282 | max_cck->sfd_timeout); |
298 | pos += scnprintf(buf + pos, bufsz - pos, | 283 | pos += scnprintf(buf + pos, bufsz - pos, |
299 | " %-30s %10u %10u %10u %10u\n", "fina_timeout:", | 284 | fmt_table, "fina_timeout:", |
300 | le32_to_cpu(cck->fina_timeout), | 285 | le32_to_cpu(cck->fina_timeout), |
301 | accum_cck->fina_timeout, delta_cck->fina_timeout, | 286 | accum_cck->fina_timeout, delta_cck->fina_timeout, |
302 | max_cck->fina_timeout); | 287 | max_cck->fina_timeout); |
303 | pos += scnprintf(buf + pos, bufsz - pos, | 288 | pos += scnprintf(buf + pos, bufsz - pos, |
304 | " %-30s %10u %10u %10u %10u\n", | 289 | fmt_table, "unresponded_rts:", |
305 | "unresponded_rts:", | ||
306 | le32_to_cpu(cck->unresponded_rts), | 290 | le32_to_cpu(cck->unresponded_rts), |
307 | accum_cck->unresponded_rts, delta_cck->unresponded_rts, | 291 | accum_cck->unresponded_rts, delta_cck->unresponded_rts, |
308 | max_cck->unresponded_rts); | 292 | max_cck->unresponded_rts); |
309 | pos += scnprintf(buf + pos, bufsz - pos, | 293 | pos += scnprintf(buf + pos, bufsz - pos, |
310 | " %-30s %10u %10u %10u %10u\n", | 294 | fmt_table, "rxe_frame_lmt_ovrun:", |
311 | "rxe_frame_lmt_ovrun:", | ||
312 | le32_to_cpu(cck->rxe_frame_limit_overrun), | 295 | le32_to_cpu(cck->rxe_frame_limit_overrun), |
313 | accum_cck->rxe_frame_limit_overrun, | 296 | accum_cck->rxe_frame_limit_overrun, |
314 | delta_cck->rxe_frame_limit_overrun, | 297 | delta_cck->rxe_frame_limit_overrun, |
315 | max_cck->rxe_frame_limit_overrun); | 298 | max_cck->rxe_frame_limit_overrun); |
316 | pos += scnprintf(buf + pos, bufsz - pos, | 299 | pos += scnprintf(buf + pos, bufsz - pos, |
317 | " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", | 300 | fmt_table, "sent_ack_cnt:", |
318 | le32_to_cpu(cck->sent_ack_cnt), | 301 | le32_to_cpu(cck->sent_ack_cnt), |
319 | accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, | 302 | accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, |
320 | max_cck->sent_ack_cnt); | 303 | max_cck->sent_ack_cnt); |
321 | pos += scnprintf(buf + pos, bufsz - pos, | 304 | pos += scnprintf(buf + pos, bufsz - pos, |
322 | " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", | 305 | fmt_table, "sent_cts_cnt:", |
323 | le32_to_cpu(cck->sent_cts_cnt), | 306 | le32_to_cpu(cck->sent_cts_cnt), |
324 | accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, | 307 | accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, |
325 | max_cck->sent_cts_cnt); | 308 | max_cck->sent_cts_cnt); |
326 | pos += scnprintf(buf + pos, bufsz - pos, | 309 | pos += scnprintf(buf + pos, bufsz - pos, |
327 | " %-30s %10u %10u %10u %10u\n", "sent_ba_rsp_cnt:", | 310 | fmt_table, "sent_ba_rsp_cnt:", |
328 | le32_to_cpu(cck->sent_ba_rsp_cnt), | 311 | le32_to_cpu(cck->sent_ba_rsp_cnt), |
329 | accum_cck->sent_ba_rsp_cnt, | 312 | accum_cck->sent_ba_rsp_cnt, |
330 | delta_cck->sent_ba_rsp_cnt, | 313 | delta_cck->sent_ba_rsp_cnt, |
331 | max_cck->sent_ba_rsp_cnt); | 314 | max_cck->sent_ba_rsp_cnt); |
332 | pos += scnprintf(buf + pos, bufsz - pos, | 315 | pos += scnprintf(buf + pos, bufsz - pos, |
333 | " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", | 316 | fmt_table, "dsp_self_kill:", |
334 | le32_to_cpu(cck->dsp_self_kill), | 317 | le32_to_cpu(cck->dsp_self_kill), |
335 | accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, | 318 | accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, |
336 | max_cck->dsp_self_kill); | 319 | max_cck->dsp_self_kill); |
337 | pos += scnprintf(buf + pos, bufsz - pos, | 320 | pos += scnprintf(buf + pos, bufsz - pos, |
338 | " %-30s %10u %10u %10u %10u\n", "mh_format_err:", | 321 | fmt_table, "mh_format_err:", |
339 | le32_to_cpu(cck->mh_format_err), | 322 | le32_to_cpu(cck->mh_format_err), |
340 | accum_cck->mh_format_err, delta_cck->mh_format_err, | 323 | accum_cck->mh_format_err, delta_cck->mh_format_err, |
341 | max_cck->mh_format_err); | 324 | max_cck->mh_format_err); |
342 | pos += scnprintf(buf + pos, bufsz - pos, | 325 | pos += scnprintf(buf + pos, bufsz - pos, |
343 | " %-30s %10u %10u %10u %10u\n", | 326 | fmt_table, "re_acq_main_rssi_sum:", |
344 | "re_acq_main_rssi_sum:", | ||
345 | le32_to_cpu(cck->re_acq_main_rssi_sum), | 327 | le32_to_cpu(cck->re_acq_main_rssi_sum), |
346 | accum_cck->re_acq_main_rssi_sum, | 328 | accum_cck->re_acq_main_rssi_sum, |
347 | delta_cck->re_acq_main_rssi_sum, | 329 | delta_cck->re_acq_main_rssi_sum, |
348 | max_cck->re_acq_main_rssi_sum); | 330 | max_cck->re_acq_main_rssi_sum); |
349 | 331 | ||
350 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
351 | "acumulative delta max\n", | ||
352 | "Statistics_Rx - GENERAL:"); | ||
353 | pos += scnprintf(buf + pos, bufsz - pos, | 332 | pos += scnprintf(buf + pos, bufsz - pos, |
354 | " %-30s %10u %10u %10u %10u\n", "bogus_cts:", | 333 | fmt_header, "Statistics_Rx - GENERAL:"); |
334 | pos += scnprintf(buf + pos, bufsz - pos, | ||
335 | fmt_table, "bogus_cts:", | ||
355 | le32_to_cpu(general->bogus_cts), | 336 | le32_to_cpu(general->bogus_cts), |
356 | accum_general->bogus_cts, delta_general->bogus_cts, | 337 | accum_general->bogus_cts, delta_general->bogus_cts, |
357 | max_general->bogus_cts); | 338 | max_general->bogus_cts); |
358 | pos += scnprintf(buf + pos, bufsz - pos, | 339 | pos += scnprintf(buf + pos, bufsz - pos, |
359 | " %-30s %10u %10u %10u %10u\n", "bogus_ack:", | 340 | fmt_table, "bogus_ack:", |
360 | le32_to_cpu(general->bogus_ack), | 341 | le32_to_cpu(general->bogus_ack), |
361 | accum_general->bogus_ack, delta_general->bogus_ack, | 342 | accum_general->bogus_ack, delta_general->bogus_ack, |
362 | max_general->bogus_ack); | 343 | max_general->bogus_ack); |
363 | pos += scnprintf(buf + pos, bufsz - pos, | 344 | pos += scnprintf(buf + pos, bufsz - pos, |
364 | " %-30s %10u %10u %10u %10u\n", | 345 | fmt_table, "non_bssid_frames:", |
365 | "non_bssid_frames:", | ||
366 | le32_to_cpu(general->non_bssid_frames), | 346 | le32_to_cpu(general->non_bssid_frames), |
367 | accum_general->non_bssid_frames, | 347 | accum_general->non_bssid_frames, |
368 | delta_general->non_bssid_frames, | 348 | delta_general->non_bssid_frames, |
369 | max_general->non_bssid_frames); | 349 | max_general->non_bssid_frames); |
370 | pos += scnprintf(buf + pos, bufsz - pos, | 350 | pos += scnprintf(buf + pos, bufsz - pos, |
371 | " %-30s %10u %10u %10u %10u\n", | 351 | fmt_table, "filtered_frames:", |
372 | "filtered_frames:", | ||
373 | le32_to_cpu(general->filtered_frames), | 352 | le32_to_cpu(general->filtered_frames), |
374 | accum_general->filtered_frames, | 353 | accum_general->filtered_frames, |
375 | delta_general->filtered_frames, | 354 | delta_general->filtered_frames, |
376 | max_general->filtered_frames); | 355 | max_general->filtered_frames); |
377 | pos += scnprintf(buf + pos, bufsz - pos, | 356 | pos += scnprintf(buf + pos, bufsz - pos, |
378 | " %-30s %10u %10u %10u %10u\n", | 357 | fmt_table, "non_channel_beacons:", |
379 | "non_channel_beacons:", | ||
380 | le32_to_cpu(general->non_channel_beacons), | 358 | le32_to_cpu(general->non_channel_beacons), |
381 | accum_general->non_channel_beacons, | 359 | accum_general->non_channel_beacons, |
382 | delta_general->non_channel_beacons, | 360 | delta_general->non_channel_beacons, |
383 | max_general->non_channel_beacons); | 361 | max_general->non_channel_beacons); |
384 | pos += scnprintf(buf + pos, bufsz - pos, | 362 | pos += scnprintf(buf + pos, bufsz - pos, |
385 | " %-30s %10u %10u %10u %10u\n", | 363 | fmt_table, "channel_beacons:", |
386 | "channel_beacons:", | ||
387 | le32_to_cpu(general->channel_beacons), | 364 | le32_to_cpu(general->channel_beacons), |
388 | accum_general->channel_beacons, | 365 | accum_general->channel_beacons, |
389 | delta_general->channel_beacons, | 366 | delta_general->channel_beacons, |
390 | max_general->channel_beacons); | 367 | max_general->channel_beacons); |
391 | pos += scnprintf(buf + pos, bufsz - pos, | 368 | pos += scnprintf(buf + pos, bufsz - pos, |
392 | " %-30s %10u %10u %10u %10u\n", | 369 | fmt_table, "num_missed_bcon:", |
393 | "num_missed_bcon:", | ||
394 | le32_to_cpu(general->num_missed_bcon), | 370 | le32_to_cpu(general->num_missed_bcon), |
395 | accum_general->num_missed_bcon, | 371 | accum_general->num_missed_bcon, |
396 | delta_general->num_missed_bcon, | 372 | delta_general->num_missed_bcon, |
397 | max_general->num_missed_bcon); | 373 | max_general->num_missed_bcon); |
398 | pos += scnprintf(buf + pos, bufsz - pos, | 374 | pos += scnprintf(buf + pos, bufsz - pos, |
399 | " %-30s %10u %10u %10u %10u\n", | 375 | fmt_table, "adc_rx_saturation_time:", |
400 | "adc_rx_saturation_time:", | ||
401 | le32_to_cpu(general->adc_rx_saturation_time), | 376 | le32_to_cpu(general->adc_rx_saturation_time), |
402 | accum_general->adc_rx_saturation_time, | 377 | accum_general->adc_rx_saturation_time, |
403 | delta_general->adc_rx_saturation_time, | 378 | delta_general->adc_rx_saturation_time, |
404 | max_general->adc_rx_saturation_time); | 379 | max_general->adc_rx_saturation_time); |
405 | pos += scnprintf(buf + pos, bufsz - pos, | 380 | pos += scnprintf(buf + pos, bufsz - pos, |
406 | " %-30s %10u %10u %10u %10u\n", | 381 | fmt_table, "ina_detect_search_tm:", |
407 | "ina_detect_search_tm:", | ||
408 | le32_to_cpu(general->ina_detection_search_time), | 382 | le32_to_cpu(general->ina_detection_search_time), |
409 | accum_general->ina_detection_search_time, | 383 | accum_general->ina_detection_search_time, |
410 | delta_general->ina_detection_search_time, | 384 | delta_general->ina_detection_search_time, |
411 | max_general->ina_detection_search_time); | 385 | max_general->ina_detection_search_time); |
412 | pos += scnprintf(buf + pos, bufsz - pos, | 386 | pos += scnprintf(buf + pos, bufsz - pos, |
413 | " %-30s %10u %10u %10u %10u\n", | 387 | fmt_table, "beacon_silence_rssi_a:", |
414 | "beacon_silence_rssi_a:", | ||
415 | le32_to_cpu(general->beacon_silence_rssi_a), | 388 | le32_to_cpu(general->beacon_silence_rssi_a), |
416 | accum_general->beacon_silence_rssi_a, | 389 | accum_general->beacon_silence_rssi_a, |
417 | delta_general->beacon_silence_rssi_a, | 390 | delta_general->beacon_silence_rssi_a, |
418 | max_general->beacon_silence_rssi_a); | 391 | max_general->beacon_silence_rssi_a); |
419 | pos += scnprintf(buf + pos, bufsz - pos, | 392 | pos += scnprintf(buf + pos, bufsz - pos, |
420 | " %-30s %10u %10u %10u %10u\n", | 393 | fmt_table, "beacon_silence_rssi_b:", |
421 | "beacon_silence_rssi_b:", | ||
422 | le32_to_cpu(general->beacon_silence_rssi_b), | 394 | le32_to_cpu(general->beacon_silence_rssi_b), |
423 | accum_general->beacon_silence_rssi_b, | 395 | accum_general->beacon_silence_rssi_b, |
424 | delta_general->beacon_silence_rssi_b, | 396 | delta_general->beacon_silence_rssi_b, |
425 | max_general->beacon_silence_rssi_b); | 397 | max_general->beacon_silence_rssi_b); |
426 | pos += scnprintf(buf + pos, bufsz - pos, | 398 | pos += scnprintf(buf + pos, bufsz - pos, |
427 | " %-30s %10u %10u %10u %10u\n", | 399 | fmt_table, "beacon_silence_rssi_c:", |
428 | "beacon_silence_rssi_c:", | ||
429 | le32_to_cpu(general->beacon_silence_rssi_c), | 400 | le32_to_cpu(general->beacon_silence_rssi_c), |
430 | accum_general->beacon_silence_rssi_c, | 401 | accum_general->beacon_silence_rssi_c, |
431 | delta_general->beacon_silence_rssi_c, | 402 | delta_general->beacon_silence_rssi_c, |
432 | max_general->beacon_silence_rssi_c); | 403 | max_general->beacon_silence_rssi_c); |
433 | pos += scnprintf(buf + pos, bufsz - pos, | 404 | pos += scnprintf(buf + pos, bufsz - pos, |
434 | " %-30s %10u %10u %10u %10u\n", | 405 | fmt_table, "interference_data_flag:", |
435 | "interference_data_flag:", | ||
436 | le32_to_cpu(general->interference_data_flag), | 406 | le32_to_cpu(general->interference_data_flag), |
437 | accum_general->interference_data_flag, | 407 | accum_general->interference_data_flag, |
438 | delta_general->interference_data_flag, | 408 | delta_general->interference_data_flag, |
439 | max_general->interference_data_flag); | 409 | max_general->interference_data_flag); |
440 | pos += scnprintf(buf + pos, bufsz - pos, | 410 | pos += scnprintf(buf + pos, bufsz - pos, |
441 | " %-30s %10u %10u %10u %10u\n", | 411 | fmt_table, "channel_load:", |
442 | "channel_load:", | ||
443 | le32_to_cpu(general->channel_load), | 412 | le32_to_cpu(general->channel_load), |
444 | accum_general->channel_load, | 413 | accum_general->channel_load, |
445 | delta_general->channel_load, | 414 | delta_general->channel_load, |
446 | max_general->channel_load); | 415 | max_general->channel_load); |
447 | pos += scnprintf(buf + pos, bufsz - pos, | 416 | pos += scnprintf(buf + pos, bufsz - pos, |
448 | " %-30s %10u %10u %10u %10u\n", | 417 | fmt_table, "dsp_false_alarms:", |
449 | "dsp_false_alarms:", | ||
450 | le32_to_cpu(general->dsp_false_alarms), | 418 | le32_to_cpu(general->dsp_false_alarms), |
451 | accum_general->dsp_false_alarms, | 419 | accum_general->dsp_false_alarms, |
452 | delta_general->dsp_false_alarms, | 420 | delta_general->dsp_false_alarms, |
453 | max_general->dsp_false_alarms); | 421 | max_general->dsp_false_alarms); |
454 | pos += scnprintf(buf + pos, bufsz - pos, | 422 | pos += scnprintf(buf + pos, bufsz - pos, |
455 | " %-30s %10u %10u %10u %10u\n", | 423 | fmt_table, "beacon_rssi_a:", |
456 | "beacon_rssi_a:", | ||
457 | le32_to_cpu(general->beacon_rssi_a), | 424 | le32_to_cpu(general->beacon_rssi_a), |
458 | accum_general->beacon_rssi_a, | 425 | accum_general->beacon_rssi_a, |
459 | delta_general->beacon_rssi_a, | 426 | delta_general->beacon_rssi_a, |
460 | max_general->beacon_rssi_a); | 427 | max_general->beacon_rssi_a); |
461 | pos += scnprintf(buf + pos, bufsz - pos, | 428 | pos += scnprintf(buf + pos, bufsz - pos, |
462 | " %-30s %10u %10u %10u %10u\n", | 429 | fmt_table, "beacon_rssi_b:", |
463 | "beacon_rssi_b:", | ||
464 | le32_to_cpu(general->beacon_rssi_b), | 430 | le32_to_cpu(general->beacon_rssi_b), |
465 | accum_general->beacon_rssi_b, | 431 | accum_general->beacon_rssi_b, |
466 | delta_general->beacon_rssi_b, | 432 | delta_general->beacon_rssi_b, |
467 | max_general->beacon_rssi_b); | 433 | max_general->beacon_rssi_b); |
468 | pos += scnprintf(buf + pos, bufsz - pos, | 434 | pos += scnprintf(buf + pos, bufsz - pos, |
469 | " %-30s %10u %10u %10u %10u\n", | 435 | fmt_table, "beacon_rssi_c:", |
470 | "beacon_rssi_c:", | ||
471 | le32_to_cpu(general->beacon_rssi_c), | 436 | le32_to_cpu(general->beacon_rssi_c), |
472 | accum_general->beacon_rssi_c, | 437 | accum_general->beacon_rssi_c, |
473 | delta_general->beacon_rssi_c, | 438 | delta_general->beacon_rssi_c, |
474 | max_general->beacon_rssi_c); | 439 | max_general->beacon_rssi_c); |
475 | pos += scnprintf(buf + pos, bufsz - pos, | 440 | pos += scnprintf(buf + pos, bufsz - pos, |
476 | " %-30s %10u %10u %10u %10u\n", | 441 | fmt_table, "beacon_energy_a:", |
477 | "beacon_energy_a:", | ||
478 | le32_to_cpu(general->beacon_energy_a), | 442 | le32_to_cpu(general->beacon_energy_a), |
479 | accum_general->beacon_energy_a, | 443 | accum_general->beacon_energy_a, |
480 | delta_general->beacon_energy_a, | 444 | delta_general->beacon_energy_a, |
481 | max_general->beacon_energy_a); | 445 | max_general->beacon_energy_a); |
482 | pos += scnprintf(buf + pos, bufsz - pos, | 446 | pos += scnprintf(buf + pos, bufsz - pos, |
483 | " %-30s %10u %10u %10u %10u\n", | 447 | fmt_table, "beacon_energy_b:", |
484 | "beacon_energy_b:", | ||
485 | le32_to_cpu(general->beacon_energy_b), | 448 | le32_to_cpu(general->beacon_energy_b), |
486 | accum_general->beacon_energy_b, | 449 | accum_general->beacon_energy_b, |
487 | delta_general->beacon_energy_b, | 450 | delta_general->beacon_energy_b, |
488 | max_general->beacon_energy_b); | 451 | max_general->beacon_energy_b); |
489 | pos += scnprintf(buf + pos, bufsz - pos, | 452 | pos += scnprintf(buf + pos, bufsz - pos, |
490 | " %-30s %10u %10u %10u %10u\n", | 453 | fmt_table, "beacon_energy_c:", |
491 | "beacon_energy_c:", | ||
492 | le32_to_cpu(general->beacon_energy_c), | 454 | le32_to_cpu(general->beacon_energy_c), |
493 | accum_general->beacon_energy_c, | 455 | accum_general->beacon_energy_c, |
494 | delta_general->beacon_energy_c, | 456 | delta_general->beacon_energy_c, |
495 | max_general->beacon_energy_c); | 457 | max_general->beacon_energy_c); |
496 | 458 | ||
497 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | ||
498 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
499 | "acumulative delta max\n", | ||
500 | "Statistics_Rx - OFDM_HT:"); | ||
501 | pos += scnprintf(buf + pos, bufsz - pos, | 459 | pos += scnprintf(buf + pos, bufsz - pos, |
502 | " %-30s %10u %10u %10u %10u\n", | 460 | fmt_header, "Statistics_Rx - OFDM_HT:"); |
503 | "plcp_err:", | 461 | pos += scnprintf(buf + pos, bufsz - pos, |
462 | fmt_table, "plcp_err:", | ||
504 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, | 463 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, |
505 | delta_ht->plcp_err, max_ht->plcp_err); | 464 | delta_ht->plcp_err, max_ht->plcp_err); |
506 | pos += scnprintf(buf + pos, bufsz - pos, | 465 | pos += scnprintf(buf + pos, bufsz - pos, |
507 | " %-30s %10u %10u %10u %10u\n", | 466 | fmt_table, "overrun_err:", |
508 | "overrun_err:", | ||
509 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, | 467 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, |
510 | delta_ht->overrun_err, max_ht->overrun_err); | 468 | delta_ht->overrun_err, max_ht->overrun_err); |
511 | pos += scnprintf(buf + pos, bufsz - pos, | 469 | pos += scnprintf(buf + pos, bufsz - pos, |
512 | " %-30s %10u %10u %10u %10u\n", | 470 | fmt_table, "early_overrun_err:", |
513 | "early_overrun_err:", | ||
514 | le32_to_cpu(ht->early_overrun_err), | 471 | le32_to_cpu(ht->early_overrun_err), |
515 | accum_ht->early_overrun_err, | 472 | accum_ht->early_overrun_err, |
516 | delta_ht->early_overrun_err, | 473 | delta_ht->early_overrun_err, |
517 | max_ht->early_overrun_err); | 474 | max_ht->early_overrun_err); |
518 | pos += scnprintf(buf + pos, bufsz - pos, | 475 | pos += scnprintf(buf + pos, bufsz - pos, |
519 | " %-30s %10u %10u %10u %10u\n", | 476 | fmt_table, "crc32_good:", |
520 | "crc32_good:", | ||
521 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, | 477 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, |
522 | delta_ht->crc32_good, max_ht->crc32_good); | 478 | delta_ht->crc32_good, max_ht->crc32_good); |
523 | pos += scnprintf(buf + pos, bufsz - pos, | 479 | pos += scnprintf(buf + pos, bufsz - pos, |
524 | " %-30s %10u %10u %10u %10u\n", | 480 | fmt_table, "crc32_err:", |
525 | "crc32_err:", | ||
526 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, | 481 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, |
527 | delta_ht->crc32_err, max_ht->crc32_err); | 482 | delta_ht->crc32_err, max_ht->crc32_err); |
528 | pos += scnprintf(buf + pos, bufsz - pos, | 483 | pos += scnprintf(buf + pos, bufsz - pos, |
529 | " %-30s %10u %10u %10u %10u\n", | 484 | fmt_table, "mh_format_err:", |
530 | "mh_format_err:", | ||
531 | le32_to_cpu(ht->mh_format_err), | 485 | le32_to_cpu(ht->mh_format_err), |
532 | accum_ht->mh_format_err, | 486 | accum_ht->mh_format_err, |
533 | delta_ht->mh_format_err, max_ht->mh_format_err); | 487 | delta_ht->mh_format_err, max_ht->mh_format_err); |
534 | pos += scnprintf(buf + pos, bufsz - pos, | 488 | pos += scnprintf(buf + pos, bufsz - pos, |
535 | " %-30s %10u %10u %10u %10u\n", | 489 | fmt_table, "agg_crc32_good:", |
536 | "agg_crc32_good:", | ||
537 | le32_to_cpu(ht->agg_crc32_good), | 490 | le32_to_cpu(ht->agg_crc32_good), |
538 | accum_ht->agg_crc32_good, | 491 | accum_ht->agg_crc32_good, |
539 | delta_ht->agg_crc32_good, max_ht->agg_crc32_good); | 492 | delta_ht->agg_crc32_good, max_ht->agg_crc32_good); |
540 | pos += scnprintf(buf + pos, bufsz - pos, | 493 | pos += scnprintf(buf + pos, bufsz - pos, |
541 | " %-30s %10u %10u %10u %10u\n", | 494 | fmt_table, "agg_mpdu_cnt:", |
542 | "agg_mpdu_cnt:", | ||
543 | le32_to_cpu(ht->agg_mpdu_cnt), | 495 | le32_to_cpu(ht->agg_mpdu_cnt), |
544 | accum_ht->agg_mpdu_cnt, | 496 | accum_ht->agg_mpdu_cnt, |
545 | delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); | 497 | delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); |
546 | pos += scnprintf(buf + pos, bufsz - pos, | 498 | pos += scnprintf(buf + pos, bufsz - pos, |
547 | " %-30s %10u %10u %10u %10u\n", | 499 | fmt_table, "agg_cnt:", |
548 | "agg_cnt:", | ||
549 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, | 500 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, |
550 | delta_ht->agg_cnt, max_ht->agg_cnt); | 501 | delta_ht->agg_cnt, max_ht->agg_cnt); |
551 | pos += scnprintf(buf + pos, bufsz - pos, | 502 | pos += scnprintf(buf + pos, bufsz - pos, |
552 | " %-30s %10u %10u %10u %10u\n", | 503 | fmt_table, "unsupport_mcs:", |
553 | "unsupport_mcs:", | ||
554 | le32_to_cpu(ht->unsupport_mcs), | 504 | le32_to_cpu(ht->unsupport_mcs), |
555 | accum_ht->unsupport_mcs, | 505 | accum_ht->unsupport_mcs, |
556 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); | 506 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); |
@@ -597,166 +547,141 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
597 | } | 547 | } |
598 | 548 | ||
599 | pos += iwl_statistics_flag(priv, buf, bufsz); | 549 | pos += iwl_statistics_flag(priv, buf, bufsz); |
600 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
601 | "acumulative delta max\n", | ||
602 | "Statistics_Tx:"); | ||
603 | pos += scnprintf(buf + pos, bufsz - pos, | 550 | pos += scnprintf(buf + pos, bufsz - pos, |
604 | " %-30s %10u %10u %10u %10u\n", | 551 | fmt_header, "Statistics_Tx:"); |
605 | "preamble:", | 552 | pos += scnprintf(buf + pos, bufsz - pos, |
553 | fmt_table, "preamble:", | ||
606 | le32_to_cpu(tx->preamble_cnt), | 554 | le32_to_cpu(tx->preamble_cnt), |
607 | accum_tx->preamble_cnt, | 555 | accum_tx->preamble_cnt, |
608 | delta_tx->preamble_cnt, max_tx->preamble_cnt); | 556 | delta_tx->preamble_cnt, max_tx->preamble_cnt); |
609 | pos += scnprintf(buf + pos, bufsz - pos, | 557 | pos += scnprintf(buf + pos, bufsz - pos, |
610 | " %-30s %10u %10u %10u %10u\n", | 558 | fmt_table, "rx_detected_cnt:", |
611 | "rx_detected_cnt:", | ||
612 | le32_to_cpu(tx->rx_detected_cnt), | 559 | le32_to_cpu(tx->rx_detected_cnt), |
613 | accum_tx->rx_detected_cnt, | 560 | accum_tx->rx_detected_cnt, |
614 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); | 561 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); |
615 | pos += scnprintf(buf + pos, bufsz - pos, | 562 | pos += scnprintf(buf + pos, bufsz - pos, |
616 | " %-30s %10u %10u %10u %10u\n", | 563 | fmt_table, "bt_prio_defer_cnt:", |
617 | "bt_prio_defer_cnt:", | ||
618 | le32_to_cpu(tx->bt_prio_defer_cnt), | 564 | le32_to_cpu(tx->bt_prio_defer_cnt), |
619 | accum_tx->bt_prio_defer_cnt, | 565 | accum_tx->bt_prio_defer_cnt, |
620 | delta_tx->bt_prio_defer_cnt, | 566 | delta_tx->bt_prio_defer_cnt, |
621 | max_tx->bt_prio_defer_cnt); | 567 | max_tx->bt_prio_defer_cnt); |
622 | pos += scnprintf(buf + pos, bufsz - pos, | 568 | pos += scnprintf(buf + pos, bufsz - pos, |
623 | " %-30s %10u %10u %10u %10u\n", | 569 | fmt_table, "bt_prio_kill_cnt:", |
624 | "bt_prio_kill_cnt:", | ||
625 | le32_to_cpu(tx->bt_prio_kill_cnt), | 570 | le32_to_cpu(tx->bt_prio_kill_cnt), |
626 | accum_tx->bt_prio_kill_cnt, | 571 | accum_tx->bt_prio_kill_cnt, |
627 | delta_tx->bt_prio_kill_cnt, | 572 | delta_tx->bt_prio_kill_cnt, |
628 | max_tx->bt_prio_kill_cnt); | 573 | max_tx->bt_prio_kill_cnt); |
629 | pos += scnprintf(buf + pos, bufsz - pos, | 574 | pos += scnprintf(buf + pos, bufsz - pos, |
630 | " %-30s %10u %10u %10u %10u\n", | 575 | fmt_table, "few_bytes_cnt:", |
631 | "few_bytes_cnt:", | ||
632 | le32_to_cpu(tx->few_bytes_cnt), | 576 | le32_to_cpu(tx->few_bytes_cnt), |
633 | accum_tx->few_bytes_cnt, | 577 | accum_tx->few_bytes_cnt, |
634 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); | 578 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); |
635 | pos += scnprintf(buf + pos, bufsz - pos, | 579 | pos += scnprintf(buf + pos, bufsz - pos, |
636 | " %-30s %10u %10u %10u %10u\n", | 580 | fmt_table, "cts_timeout:", |
637 | "cts_timeout:", | ||
638 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, | 581 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, |
639 | delta_tx->cts_timeout, max_tx->cts_timeout); | 582 | delta_tx->cts_timeout, max_tx->cts_timeout); |
640 | pos += scnprintf(buf + pos, bufsz - pos, | 583 | pos += scnprintf(buf + pos, bufsz - pos, |
641 | " %-30s %10u %10u %10u %10u\n", | 584 | fmt_table, "ack_timeout:", |
642 | "ack_timeout:", | ||
643 | le32_to_cpu(tx->ack_timeout), | 585 | le32_to_cpu(tx->ack_timeout), |
644 | accum_tx->ack_timeout, | 586 | accum_tx->ack_timeout, |
645 | delta_tx->ack_timeout, max_tx->ack_timeout); | 587 | delta_tx->ack_timeout, max_tx->ack_timeout); |
646 | pos += scnprintf(buf + pos, bufsz - pos, | 588 | pos += scnprintf(buf + pos, bufsz - pos, |
647 | " %-30s %10u %10u %10u %10u\n", | 589 | fmt_table, "expected_ack_cnt:", |
648 | "expected_ack_cnt:", | ||
649 | le32_to_cpu(tx->expected_ack_cnt), | 590 | le32_to_cpu(tx->expected_ack_cnt), |
650 | accum_tx->expected_ack_cnt, | 591 | accum_tx->expected_ack_cnt, |
651 | delta_tx->expected_ack_cnt, | 592 | delta_tx->expected_ack_cnt, |
652 | max_tx->expected_ack_cnt); | 593 | max_tx->expected_ack_cnt); |
653 | pos += scnprintf(buf + pos, bufsz - pos, | 594 | pos += scnprintf(buf + pos, bufsz - pos, |
654 | " %-30s %10u %10u %10u %10u\n", | 595 | fmt_table, "actual_ack_cnt:", |
655 | "actual_ack_cnt:", | ||
656 | le32_to_cpu(tx->actual_ack_cnt), | 596 | le32_to_cpu(tx->actual_ack_cnt), |
657 | accum_tx->actual_ack_cnt, | 597 | accum_tx->actual_ack_cnt, |
658 | delta_tx->actual_ack_cnt, | 598 | delta_tx->actual_ack_cnt, |
659 | max_tx->actual_ack_cnt); | 599 | max_tx->actual_ack_cnt); |
660 | pos += scnprintf(buf + pos, bufsz - pos, | 600 | pos += scnprintf(buf + pos, bufsz - pos, |
661 | " %-30s %10u %10u %10u %10u\n", | 601 | fmt_table, "dump_msdu_cnt:", |
662 | "dump_msdu_cnt:", | ||
663 | le32_to_cpu(tx->dump_msdu_cnt), | 602 | le32_to_cpu(tx->dump_msdu_cnt), |
664 | accum_tx->dump_msdu_cnt, | 603 | accum_tx->dump_msdu_cnt, |
665 | delta_tx->dump_msdu_cnt, | 604 | delta_tx->dump_msdu_cnt, |
666 | max_tx->dump_msdu_cnt); | 605 | max_tx->dump_msdu_cnt); |
667 | pos += scnprintf(buf + pos, bufsz - pos, | 606 | pos += scnprintf(buf + pos, bufsz - pos, |
668 | " %-30s %10u %10u %10u %10u\n", | 607 | fmt_table, "abort_nxt_frame_mismatch:", |
669 | "abort_nxt_frame_mismatch:", | ||
670 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), | 608 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), |
671 | accum_tx->burst_abort_next_frame_mismatch_cnt, | 609 | accum_tx->burst_abort_next_frame_mismatch_cnt, |
672 | delta_tx->burst_abort_next_frame_mismatch_cnt, | 610 | delta_tx->burst_abort_next_frame_mismatch_cnt, |
673 | max_tx->burst_abort_next_frame_mismatch_cnt); | 611 | max_tx->burst_abort_next_frame_mismatch_cnt); |
674 | pos += scnprintf(buf + pos, bufsz - pos, | 612 | pos += scnprintf(buf + pos, bufsz - pos, |
675 | " %-30s %10u %10u %10u %10u\n", | 613 | fmt_table, "abort_missing_nxt_frame:", |
676 | "abort_missing_nxt_frame:", | ||
677 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), | 614 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), |
678 | accum_tx->burst_abort_missing_next_frame_cnt, | 615 | accum_tx->burst_abort_missing_next_frame_cnt, |
679 | delta_tx->burst_abort_missing_next_frame_cnt, | 616 | delta_tx->burst_abort_missing_next_frame_cnt, |
680 | max_tx->burst_abort_missing_next_frame_cnt); | 617 | max_tx->burst_abort_missing_next_frame_cnt); |
681 | pos += scnprintf(buf + pos, bufsz - pos, | 618 | pos += scnprintf(buf + pos, bufsz - pos, |
682 | " %-30s %10u %10u %10u %10u\n", | 619 | fmt_table, "cts_timeout_collision:", |
683 | "cts_timeout_collision:", | ||
684 | le32_to_cpu(tx->cts_timeout_collision), | 620 | le32_to_cpu(tx->cts_timeout_collision), |
685 | accum_tx->cts_timeout_collision, | 621 | accum_tx->cts_timeout_collision, |
686 | delta_tx->cts_timeout_collision, | 622 | delta_tx->cts_timeout_collision, |
687 | max_tx->cts_timeout_collision); | 623 | max_tx->cts_timeout_collision); |
688 | pos += scnprintf(buf + pos, bufsz - pos, | 624 | pos += scnprintf(buf + pos, bufsz - pos, |
689 | " %-30s %10u %10u %10u %10u\n", | 625 | fmt_table, "ack_ba_timeout_collision:", |
690 | "ack_ba_timeout_collision:", | ||
691 | le32_to_cpu(tx->ack_or_ba_timeout_collision), | 626 | le32_to_cpu(tx->ack_or_ba_timeout_collision), |
692 | accum_tx->ack_or_ba_timeout_collision, | 627 | accum_tx->ack_or_ba_timeout_collision, |
693 | delta_tx->ack_or_ba_timeout_collision, | 628 | delta_tx->ack_or_ba_timeout_collision, |
694 | max_tx->ack_or_ba_timeout_collision); | 629 | max_tx->ack_or_ba_timeout_collision); |
695 | pos += scnprintf(buf + pos, bufsz - pos, | 630 | pos += scnprintf(buf + pos, bufsz - pos, |
696 | " %-30s %10u %10u %10u %10u\n", | 631 | fmt_table, "agg ba_timeout:", |
697 | "agg ba_timeout:", | ||
698 | le32_to_cpu(tx->agg.ba_timeout), | 632 | le32_to_cpu(tx->agg.ba_timeout), |
699 | accum_tx->agg.ba_timeout, | 633 | accum_tx->agg.ba_timeout, |
700 | delta_tx->agg.ba_timeout, | 634 | delta_tx->agg.ba_timeout, |
701 | max_tx->agg.ba_timeout); | 635 | max_tx->agg.ba_timeout); |
702 | pos += scnprintf(buf + pos, bufsz - pos, | 636 | pos += scnprintf(buf + pos, bufsz - pos, |
703 | " %-30s %10u %10u %10u %10u\n", | 637 | fmt_table, "agg ba_resched_frames:", |
704 | "agg ba_resched_frames:", | ||
705 | le32_to_cpu(tx->agg.ba_reschedule_frames), | 638 | le32_to_cpu(tx->agg.ba_reschedule_frames), |
706 | accum_tx->agg.ba_reschedule_frames, | 639 | accum_tx->agg.ba_reschedule_frames, |
707 | delta_tx->agg.ba_reschedule_frames, | 640 | delta_tx->agg.ba_reschedule_frames, |
708 | max_tx->agg.ba_reschedule_frames); | 641 | max_tx->agg.ba_reschedule_frames); |
709 | pos += scnprintf(buf + pos, bufsz - pos, | 642 | pos += scnprintf(buf + pos, bufsz - pos, |
710 | " %-30s %10u %10u %10u %10u\n", | 643 | fmt_table, "agg scd_query_agg_frame:", |
711 | "agg scd_query_agg_frame:", | ||
712 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), | 644 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), |
713 | accum_tx->agg.scd_query_agg_frame_cnt, | 645 | accum_tx->agg.scd_query_agg_frame_cnt, |
714 | delta_tx->agg.scd_query_agg_frame_cnt, | 646 | delta_tx->agg.scd_query_agg_frame_cnt, |
715 | max_tx->agg.scd_query_agg_frame_cnt); | 647 | max_tx->agg.scd_query_agg_frame_cnt); |
716 | pos += scnprintf(buf + pos, bufsz - pos, | 648 | pos += scnprintf(buf + pos, bufsz - pos, |
717 | " %-30s %10u %10u %10u %10u\n", | 649 | fmt_table, "agg scd_query_no_agg:", |
718 | "agg scd_query_no_agg:", | ||
719 | le32_to_cpu(tx->agg.scd_query_no_agg), | 650 | le32_to_cpu(tx->agg.scd_query_no_agg), |
720 | accum_tx->agg.scd_query_no_agg, | 651 | accum_tx->agg.scd_query_no_agg, |
721 | delta_tx->agg.scd_query_no_agg, | 652 | delta_tx->agg.scd_query_no_agg, |
722 | max_tx->agg.scd_query_no_agg); | 653 | max_tx->agg.scd_query_no_agg); |
723 | pos += scnprintf(buf + pos, bufsz - pos, | 654 | pos += scnprintf(buf + pos, bufsz - pos, |
724 | " %-30s %10u %10u %10u %10u\n", | 655 | fmt_table, "agg scd_query_agg:", |
725 | "agg scd_query_agg:", | ||
726 | le32_to_cpu(tx->agg.scd_query_agg), | 656 | le32_to_cpu(tx->agg.scd_query_agg), |
727 | accum_tx->agg.scd_query_agg, | 657 | accum_tx->agg.scd_query_agg, |
728 | delta_tx->agg.scd_query_agg, | 658 | delta_tx->agg.scd_query_agg, |
729 | max_tx->agg.scd_query_agg); | 659 | max_tx->agg.scd_query_agg); |
730 | pos += scnprintf(buf + pos, bufsz - pos, | 660 | pos += scnprintf(buf + pos, bufsz - pos, |
731 | " %-30s %10u %10u %10u %10u\n", | 661 | fmt_table, "agg scd_query_mismatch:", |
732 | "agg scd_query_mismatch:", | ||
733 | le32_to_cpu(tx->agg.scd_query_mismatch), | 662 | le32_to_cpu(tx->agg.scd_query_mismatch), |
734 | accum_tx->agg.scd_query_mismatch, | 663 | accum_tx->agg.scd_query_mismatch, |
735 | delta_tx->agg.scd_query_mismatch, | 664 | delta_tx->agg.scd_query_mismatch, |
736 | max_tx->agg.scd_query_mismatch); | 665 | max_tx->agg.scd_query_mismatch); |
737 | pos += scnprintf(buf + pos, bufsz - pos, | 666 | pos += scnprintf(buf + pos, bufsz - pos, |
738 | " %-30s %10u %10u %10u %10u\n", | 667 | fmt_table, "agg frame_not_ready:", |
739 | "agg frame_not_ready:", | ||
740 | le32_to_cpu(tx->agg.frame_not_ready), | 668 | le32_to_cpu(tx->agg.frame_not_ready), |
741 | accum_tx->agg.frame_not_ready, | 669 | accum_tx->agg.frame_not_ready, |
742 | delta_tx->agg.frame_not_ready, | 670 | delta_tx->agg.frame_not_ready, |
743 | max_tx->agg.frame_not_ready); | 671 | max_tx->agg.frame_not_ready); |
744 | pos += scnprintf(buf + pos, bufsz - pos, | 672 | pos += scnprintf(buf + pos, bufsz - pos, |
745 | " %-30s %10u %10u %10u %10u\n", | 673 | fmt_table, "agg underrun:", |
746 | "agg underrun:", | ||
747 | le32_to_cpu(tx->agg.underrun), | 674 | le32_to_cpu(tx->agg.underrun), |
748 | accum_tx->agg.underrun, | 675 | accum_tx->agg.underrun, |
749 | delta_tx->agg.underrun, max_tx->agg.underrun); | 676 | delta_tx->agg.underrun, max_tx->agg.underrun); |
750 | pos += scnprintf(buf + pos, bufsz - pos, | 677 | pos += scnprintf(buf + pos, bufsz - pos, |
751 | " %-30s %10u %10u %10u %10u\n", | 678 | fmt_table, "agg bt_prio_kill:", |
752 | "agg bt_prio_kill:", | ||
753 | le32_to_cpu(tx->agg.bt_prio_kill), | 679 | le32_to_cpu(tx->agg.bt_prio_kill), |
754 | accum_tx->agg.bt_prio_kill, | 680 | accum_tx->agg.bt_prio_kill, |
755 | delta_tx->agg.bt_prio_kill, | 681 | delta_tx->agg.bt_prio_kill, |
756 | max_tx->agg.bt_prio_kill); | 682 | max_tx->agg.bt_prio_kill); |
757 | pos += scnprintf(buf + pos, bufsz - pos, | 683 | pos += scnprintf(buf + pos, bufsz - pos, |
758 | " %-30s %10u %10u %10u %10u\n", | 684 | fmt_table, "agg rx_ba_rsp_cnt:", |
759 | "agg rx_ba_rsp_cnt:", | ||
760 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), | 685 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), |
761 | accum_tx->agg.rx_ba_rsp_cnt, | 686 | accum_tx->agg.rx_ba_rsp_cnt, |
762 | delta_tx->agg.rx_ba_rsp_cnt, | 687 | delta_tx->agg.rx_ba_rsp_cnt, |
@@ -767,15 +692,15 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
767 | "tx power: (1/2 dB step)\n"); | 692 | "tx power: (1/2 dB step)\n"); |
768 | if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) | 693 | if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) |
769 | pos += scnprintf(buf + pos, bufsz - pos, | 694 | pos += scnprintf(buf + pos, bufsz - pos, |
770 | "\tantenna A: 0x%X\n", | 695 | fmt_hex, "antenna A:", |
771 | tx->tx_power.ant_a); | 696 | tx->tx_power.ant_a); |
772 | if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) | 697 | if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) |
773 | pos += scnprintf(buf + pos, bufsz - pos, | 698 | pos += scnprintf(buf + pos, bufsz - pos, |
774 | "\tantenna B: 0x%X\n", | 699 | fmt_hex, "antenna B:", |
775 | tx->tx_power.ant_b); | 700 | tx->tx_power.ant_b); |
776 | if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) | 701 | if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) |
777 | pos += scnprintf(buf + pos, bufsz - pos, | 702 | pos += scnprintf(buf + pos, bufsz - pos, |
778 | "\tantenna C: 0x%X\n", | 703 | fmt_hex, "antenna C:", |
779 | tx->tx_power.ant_c); | 704 | tx->tx_power.ant_c); |
780 | } | 705 | } |
781 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 706 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
@@ -838,84 +763,72 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
838 | } | 763 | } |
839 | 764 | ||
840 | pos += iwl_statistics_flag(priv, buf, bufsz); | 765 | pos += iwl_statistics_flag(priv, buf, bufsz); |
841 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 766 | pos += scnprintf(buf + pos, bufsz - pos, |
842 | "acumulative delta max\n", | 767 | fmt_header, "Statistics_General:"); |
843 | "Statistics_General:"); | 768 | pos += scnprintf(buf + pos, bufsz - pos, |
844 | pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", | 769 | fmt_value, "temperature:", |
845 | "temperature:", | ||
846 | le32_to_cpu(general->temperature)); | 770 | le32_to_cpu(general->temperature)); |
847 | pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", | 771 | pos += scnprintf(buf + pos, bufsz - pos, |
848 | "temperature_m:", | 772 | fmt_value, "temperature_m:", |
849 | le32_to_cpu(general->temperature_m)); | 773 | le32_to_cpu(general->temperature_m)); |
850 | pos += scnprintf(buf + pos, bufsz - pos, | 774 | pos += scnprintf(buf + pos, bufsz - pos, |
851 | " %-30s %10u %10u %10u %10u\n", | 775 | fmt_value, "ttl_timestamp:", |
852 | "burst_check:", | 776 | le32_to_cpu(general->ttl_timestamp)); |
777 | pos += scnprintf(buf + pos, bufsz - pos, | ||
778 | fmt_table, "burst_check:", | ||
853 | le32_to_cpu(dbg->burst_check), | 779 | le32_to_cpu(dbg->burst_check), |
854 | accum_dbg->burst_check, | 780 | accum_dbg->burst_check, |
855 | delta_dbg->burst_check, max_dbg->burst_check); | 781 | delta_dbg->burst_check, max_dbg->burst_check); |
856 | pos += scnprintf(buf + pos, bufsz - pos, | 782 | pos += scnprintf(buf + pos, bufsz - pos, |
857 | " %-30s %10u %10u %10u %10u\n", | 783 | fmt_table, "burst_count:", |
858 | "burst_count:", | ||
859 | le32_to_cpu(dbg->burst_count), | 784 | le32_to_cpu(dbg->burst_count), |
860 | accum_dbg->burst_count, | 785 | accum_dbg->burst_count, |
861 | delta_dbg->burst_count, max_dbg->burst_count); | 786 | delta_dbg->burst_count, max_dbg->burst_count); |
862 | pos += scnprintf(buf + pos, bufsz - pos, | 787 | pos += scnprintf(buf + pos, bufsz - pos, |
863 | " %-30s %10u %10u %10u %10u\n", | 788 | fmt_table, "wait_for_silence_timeout_count:", |
864 | "wait_for_silence_timeout_count:", | ||
865 | le32_to_cpu(dbg->wait_for_silence_timeout_cnt), | 789 | le32_to_cpu(dbg->wait_for_silence_timeout_cnt), |
866 | accum_dbg->wait_for_silence_timeout_cnt, | 790 | accum_dbg->wait_for_silence_timeout_cnt, |
867 | delta_dbg->wait_for_silence_timeout_cnt, | 791 | delta_dbg->wait_for_silence_timeout_cnt, |
868 | max_dbg->wait_for_silence_timeout_cnt); | 792 | max_dbg->wait_for_silence_timeout_cnt); |
869 | pos += scnprintf(buf + pos, bufsz - pos, | 793 | pos += scnprintf(buf + pos, bufsz - pos, |
870 | " %-30s %10u %10u %10u %10u\n", | 794 | fmt_table, "sleep_time:", |
871 | "sleep_time:", | ||
872 | le32_to_cpu(general->sleep_time), | 795 | le32_to_cpu(general->sleep_time), |
873 | accum_general->sleep_time, | 796 | accum_general->sleep_time, |
874 | delta_general->sleep_time, max_general->sleep_time); | 797 | delta_general->sleep_time, max_general->sleep_time); |
875 | pos += scnprintf(buf + pos, bufsz - pos, | 798 | pos += scnprintf(buf + pos, bufsz - pos, |
876 | " %-30s %10u %10u %10u %10u\n", | 799 | fmt_table, "slots_out:", |
877 | "slots_out:", | ||
878 | le32_to_cpu(general->slots_out), | 800 | le32_to_cpu(general->slots_out), |
879 | accum_general->slots_out, | 801 | accum_general->slots_out, |
880 | delta_general->slots_out, max_general->slots_out); | 802 | delta_general->slots_out, max_general->slots_out); |
881 | pos += scnprintf(buf + pos, bufsz - pos, | 803 | pos += scnprintf(buf + pos, bufsz - pos, |
882 | " %-30s %10u %10u %10u %10u\n", | 804 | fmt_table, "slots_idle:", |
883 | "slots_idle:", | ||
884 | le32_to_cpu(general->slots_idle), | 805 | le32_to_cpu(general->slots_idle), |
885 | accum_general->slots_idle, | 806 | accum_general->slots_idle, |
886 | delta_general->slots_idle, max_general->slots_idle); | 807 | delta_general->slots_idle, max_general->slots_idle); |
887 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
888 | le32_to_cpu(general->ttl_timestamp)); | ||
889 | pos += scnprintf(buf + pos, bufsz - pos, | 808 | pos += scnprintf(buf + pos, bufsz - pos, |
890 | " %-30s %10u %10u %10u %10u\n", | 809 | fmt_table, "tx_on_a:", |
891 | "tx_on_a:", | ||
892 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, | 810 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, |
893 | delta_div->tx_on_a, max_div->tx_on_a); | 811 | delta_div->tx_on_a, max_div->tx_on_a); |
894 | pos += scnprintf(buf + pos, bufsz - pos, | 812 | pos += scnprintf(buf + pos, bufsz - pos, |
895 | " %-30s %10u %10u %10u %10u\n", | 813 | fmt_table, "tx_on_b:", |
896 | "tx_on_b:", | ||
897 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, | 814 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, |
898 | delta_div->tx_on_b, max_div->tx_on_b); | 815 | delta_div->tx_on_b, max_div->tx_on_b); |
899 | pos += scnprintf(buf + pos, bufsz - pos, | 816 | pos += scnprintf(buf + pos, bufsz - pos, |
900 | " %-30s %10u %10u %10u %10u\n", | 817 | fmt_table, "exec_time:", |
901 | "exec_time:", | ||
902 | le32_to_cpu(div->exec_time), accum_div->exec_time, | 818 | le32_to_cpu(div->exec_time), accum_div->exec_time, |
903 | delta_div->exec_time, max_div->exec_time); | 819 | delta_div->exec_time, max_div->exec_time); |
904 | pos += scnprintf(buf + pos, bufsz - pos, | 820 | pos += scnprintf(buf + pos, bufsz - pos, |
905 | " %-30s %10u %10u %10u %10u\n", | 821 | fmt_table, "probe_time:", |
906 | "probe_time:", | ||
907 | le32_to_cpu(div->probe_time), accum_div->probe_time, | 822 | le32_to_cpu(div->probe_time), accum_div->probe_time, |
908 | delta_div->probe_time, max_div->probe_time); | 823 | delta_div->probe_time, max_div->probe_time); |
909 | pos += scnprintf(buf + pos, bufsz - pos, | 824 | pos += scnprintf(buf + pos, bufsz - pos, |
910 | " %-30s %10u %10u %10u %10u\n", | 825 | fmt_table, "rx_enable_counter:", |
911 | "rx_enable_counter:", | ||
912 | le32_to_cpu(general->rx_enable_counter), | 826 | le32_to_cpu(general->rx_enable_counter), |
913 | accum_general->rx_enable_counter, | 827 | accum_general->rx_enable_counter, |
914 | delta_general->rx_enable_counter, | 828 | delta_general->rx_enable_counter, |
915 | max_general->rx_enable_counter); | 829 | max_general->rx_enable_counter); |
916 | pos += scnprintf(buf + pos, bufsz - pos, | 830 | pos += scnprintf(buf + pos, bufsz - pos, |
917 | " %-30s %10u %10u %10u %10u\n", | 831 | fmt_table, "num_of_sos_states:", |
918 | "num_of_sos_states:", | ||
919 | le32_to_cpu(general->num_of_sos_states), | 832 | le32_to_cpu(general->num_of_sos_states), |
920 | accum_general->num_of_sos_states, | 833 | accum_general->num_of_sos_states, |
921 | delta_general->num_of_sos_states, | 834 | delta_general->num_of_sos_states, |
@@ -1011,3 +924,147 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, | |||
1011 | kfree(buf); | 924 | kfree(buf); |
1012 | return ret; | 925 | return ret; |
1013 | } | 926 | } |
927 | |||
928 | ssize_t iwl_reply_tx_error_read(struct file *file, | ||
929 | char __user *user_buf, | ||
930 | size_t count, loff_t *ppos) | ||
931 | { | ||
932 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
933 | int pos = 0; | ||
934 | char *buf; | ||
935 | int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + | ||
936 | (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; | ||
937 | ssize_t ret; | ||
938 | |||
939 | if (!iwl_is_alive(priv)) | ||
940 | return -EAGAIN; | ||
941 | |||
942 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
943 | if (!buf) { | ||
944 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
945 | return -ENOMEM; | ||
946 | } | ||
947 | |||
948 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); | ||
949 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", | ||
950 | iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), | ||
951 | priv->_agn.reply_tx_stats.pp_delay); | ||
952 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
953 | iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), | ||
954 | priv->_agn.reply_tx_stats.pp_few_bytes); | ||
955 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
956 | iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), | ||
957 | priv->_agn.reply_tx_stats.pp_bt_prio); | ||
958 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
959 | iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), | ||
960 | priv->_agn.reply_tx_stats.pp_quiet_period); | ||
961 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
962 | iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), | ||
963 | priv->_agn.reply_tx_stats.pp_calc_ttak); | ||
964 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
965 | iwl_get_tx_fail_reason( | ||
966 | TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), | ||
967 | priv->_agn.reply_tx_stats.int_crossed_retry); | ||
968 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
969 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), | ||
970 | priv->_agn.reply_tx_stats.short_limit); | ||
971 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
972 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), | ||
973 | priv->_agn.reply_tx_stats.long_limit); | ||
974 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
975 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), | ||
976 | priv->_agn.reply_tx_stats.fifo_underrun); | ||
977 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
978 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), | ||
979 | priv->_agn.reply_tx_stats.drain_flow); | ||
980 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
981 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), | ||
982 | priv->_agn.reply_tx_stats.rfkill_flush); | ||
983 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
984 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), | ||
985 | priv->_agn.reply_tx_stats.life_expire); | ||
986 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
987 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), | ||
988 | priv->_agn.reply_tx_stats.dest_ps); | ||
989 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
990 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), | ||
991 | priv->_agn.reply_tx_stats.host_abort); | ||
992 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
993 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), | ||
994 | priv->_agn.reply_tx_stats.pp_delay); | ||
995 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
996 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), | ||
997 | priv->_agn.reply_tx_stats.sta_invalid); | ||
998 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
999 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), | ||
1000 | priv->_agn.reply_tx_stats.frag_drop); | ||
1001 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1002 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), | ||
1003 | priv->_agn.reply_tx_stats.tid_disable); | ||
1004 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1005 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), | ||
1006 | priv->_agn.reply_tx_stats.fifo_flush); | ||
1007 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1008 | iwl_get_tx_fail_reason( | ||
1009 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), | ||
1010 | priv->_agn.reply_tx_stats.insuff_cf_poll); | ||
1011 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1012 | iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), | ||
1013 | priv->_agn.reply_tx_stats.fail_hw_drop); | ||
1014 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1015 | iwl_get_tx_fail_reason( | ||
1016 | TX_STATUS_FAIL_NO_BEACON_ON_RADAR), | ||
1017 | priv->_agn.reply_tx_stats.sta_color_mismatch); | ||
1018 | pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", | ||
1019 | priv->_agn.reply_tx_stats.unknown); | ||
1020 | |||
1021 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1022 | "\nStatistics_Agg_TX_Error:\n"); | ||
1023 | |||
1024 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1025 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), | ||
1026 | priv->_agn.reply_agg_tx_stats.underrun); | ||
1027 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1028 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), | ||
1029 | priv->_agn.reply_agg_tx_stats.bt_prio); | ||
1030 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1031 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), | ||
1032 | priv->_agn.reply_agg_tx_stats.few_bytes); | ||
1033 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1034 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), | ||
1035 | priv->_agn.reply_agg_tx_stats.abort); | ||
1036 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1037 | iwl_get_agg_tx_fail_reason( | ||
1038 | AGG_TX_STATE_LAST_SENT_TTL_MSK), | ||
1039 | priv->_agn.reply_agg_tx_stats.last_sent_ttl); | ||
1040 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1041 | iwl_get_agg_tx_fail_reason( | ||
1042 | AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), | ||
1043 | priv->_agn.reply_agg_tx_stats.last_sent_try); | ||
1044 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1045 | iwl_get_agg_tx_fail_reason( | ||
1046 | AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), | ||
1047 | priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); | ||
1048 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1049 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), | ||
1050 | priv->_agn.reply_agg_tx_stats.scd_query); | ||
1051 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", | ||
1052 | iwl_get_agg_tx_fail_reason( | ||
1053 | AGG_TX_STATE_TEST_BAD_CRC32_MSK), | ||
1054 | priv->_agn.reply_agg_tx_stats.bad_crc32); | ||
1055 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1056 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), | ||
1057 | priv->_agn.reply_agg_tx_stats.response); | ||
1058 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1059 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), | ||
1060 | priv->_agn.reply_agg_tx_stats.dump_tx); | ||
1061 | pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", | ||
1062 | iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), | ||
1063 | priv->_agn.reply_agg_tx_stats.delay_tx); | ||
1064 | pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", | ||
1065 | priv->_agn.reply_agg_tx_stats.unknown); | ||
1066 | |||
1067 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1068 | kfree(buf); | ||
1069 | return ret; | ||
1070 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h index bbdce5913ac7..f2573b5486cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h | |||
@@ -39,6 +39,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
39 | size_t count, loff_t *ppos); | 39 | size_t count, loff_t *ppos); |
40 | ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, | 40 | ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, |
41 | size_t count, loff_t *ppos); | 41 | size_t count, loff_t *ppos); |
42 | ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, | ||
43 | size_t count, loff_t *ppos); | ||
42 | #else | 44 | #else |
43 | static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | 45 | static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, |
44 | size_t count, loff_t *ppos) | 46 | size_t count, loff_t *ppos) |
@@ -60,4 +62,9 @@ static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, | |||
60 | { | 62 | { |
61 | return 0; | 63 | return 0; |
62 | } | 64 | } |
65 | static ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, | ||
66 | size_t count, loff_t *ppos) | ||
67 | { | ||
68 | return 0; | ||
69 | } | ||
63 | #endif | 70 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 6fb52abafc8d..d86902b83630 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -287,6 +287,15 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
287 | ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; | 287 | ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; |
288 | ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; | 288 | ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; |
289 | 289 | ||
290 | /* | ||
291 | * If the PAN context is inactive, then we don't need | ||
292 | * to update the PAN parameters, the last thing we'll | ||
293 | * have done before it goes inactive is making the PAN | ||
294 | * parameters be WLAN-only. | ||
295 | */ | ||
296 | if (!ctx_pan->is_active) | ||
297 | return 0; | ||
298 | |||
290 | memset(&cmd, 0, sizeof(cmd)); | 299 | memset(&cmd, 0, sizeof(cmd)); |
291 | 300 | ||
292 | /* only 2 slots are currently allowed */ | 301 | /* only 2 slots are currently allowed */ |
@@ -312,7 +321,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
312 | bcnint = max_t(int, bcnint, | 321 | bcnint = max_t(int, bcnint, |
313 | ctx_bss->vif->bss_conf.beacon_int); | 322 | ctx_bss->vif->bss_conf.beacon_int); |
314 | if (!bcnint) | 323 | if (!bcnint) |
315 | bcnint = 100; | 324 | bcnint = DEFAULT_BEACON_INTERVAL; |
316 | slot0 = bcnint / 2; | 325 | slot0 = bcnint / 2; |
317 | slot1 = bcnint - slot0; | 326 | slot1 = bcnint - slot0; |
318 | 327 | ||
@@ -330,7 +339,12 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
330 | slot0 = 0; | 339 | slot0 = 0; |
331 | slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * | 340 | slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) * |
332 | ctx_pan->vif->bss_conf.beacon_int; | 341 | ctx_pan->vif->bss_conf.beacon_int; |
333 | slot1 = max_t(int, 100, slot1); | 342 | slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); |
343 | |||
344 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
345 | slot0 = slot1 * 3 - 20; | ||
346 | slot1 = 20; | ||
347 | } | ||
334 | } | 348 | } |
335 | 349 | ||
336 | cmd.slots[0].width = cpu_to_le16(slot0); | 350 | cmd.slots[0].width = cpu_to_le16(slot0); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a8f2adfd799e..299fd9d59604 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -46,6 +46,181 @@ static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | |||
46 | tx_resp->frame_count) & MAX_SN; | 46 | tx_resp->frame_count) & MAX_SN; |
47 | } | 47 | } |
48 | 48 | ||
49 | static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) | ||
50 | { | ||
51 | status &= TX_STATUS_MSK; | ||
52 | |||
53 | switch (status) { | ||
54 | case TX_STATUS_POSTPONE_DELAY: | ||
55 | priv->_agn.reply_tx_stats.pp_delay++; | ||
56 | break; | ||
57 | case TX_STATUS_POSTPONE_FEW_BYTES: | ||
58 | priv->_agn.reply_tx_stats.pp_few_bytes++; | ||
59 | break; | ||
60 | case TX_STATUS_POSTPONE_BT_PRIO: | ||
61 | priv->_agn.reply_tx_stats.pp_bt_prio++; | ||
62 | break; | ||
63 | case TX_STATUS_POSTPONE_QUIET_PERIOD: | ||
64 | priv->_agn.reply_tx_stats.pp_quiet_period++; | ||
65 | break; | ||
66 | case TX_STATUS_POSTPONE_CALC_TTAK: | ||
67 | priv->_agn.reply_tx_stats.pp_calc_ttak++; | ||
68 | break; | ||
69 | case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: | ||
70 | priv->_agn.reply_tx_stats.int_crossed_retry++; | ||
71 | break; | ||
72 | case TX_STATUS_FAIL_SHORT_LIMIT: | ||
73 | priv->_agn.reply_tx_stats.short_limit++; | ||
74 | break; | ||
75 | case TX_STATUS_FAIL_LONG_LIMIT: | ||
76 | priv->_agn.reply_tx_stats.long_limit++; | ||
77 | break; | ||
78 | case TX_STATUS_FAIL_FIFO_UNDERRUN: | ||
79 | priv->_agn.reply_tx_stats.fifo_underrun++; | ||
80 | break; | ||
81 | case TX_STATUS_FAIL_DRAIN_FLOW: | ||
82 | priv->_agn.reply_tx_stats.drain_flow++; | ||
83 | break; | ||
84 | case TX_STATUS_FAIL_RFKILL_FLUSH: | ||
85 | priv->_agn.reply_tx_stats.rfkill_flush++; | ||
86 | break; | ||
87 | case TX_STATUS_FAIL_LIFE_EXPIRE: | ||
88 | priv->_agn.reply_tx_stats.life_expire++; | ||
89 | break; | ||
90 | case TX_STATUS_FAIL_DEST_PS: | ||
91 | priv->_agn.reply_tx_stats.dest_ps++; | ||
92 | break; | ||
93 | case TX_STATUS_FAIL_HOST_ABORTED: | ||
94 | priv->_agn.reply_tx_stats.host_abort++; | ||
95 | break; | ||
96 | case TX_STATUS_FAIL_BT_RETRY: | ||
97 | priv->_agn.reply_tx_stats.bt_retry++; | ||
98 | break; | ||
99 | case TX_STATUS_FAIL_STA_INVALID: | ||
100 | priv->_agn.reply_tx_stats.sta_invalid++; | ||
101 | break; | ||
102 | case TX_STATUS_FAIL_FRAG_DROPPED: | ||
103 | priv->_agn.reply_tx_stats.frag_drop++; | ||
104 | break; | ||
105 | case TX_STATUS_FAIL_TID_DISABLE: | ||
106 | priv->_agn.reply_tx_stats.tid_disable++; | ||
107 | break; | ||
108 | case TX_STATUS_FAIL_FIFO_FLUSHED: | ||
109 | priv->_agn.reply_tx_stats.fifo_flush++; | ||
110 | break; | ||
111 | case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: | ||
112 | priv->_agn.reply_tx_stats.insuff_cf_poll++; | ||
113 | break; | ||
114 | case TX_STATUS_FAIL_PASSIVE_NO_RX: | ||
115 | priv->_agn.reply_tx_stats.fail_hw_drop++; | ||
116 | break; | ||
117 | case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: | ||
118 | priv->_agn.reply_tx_stats.sta_color_mismatch++; | ||
119 | break; | ||
120 | default: | ||
121 | priv->_agn.reply_tx_stats.unknown++; | ||
122 | break; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | ||
127 | { | ||
128 | status &= AGG_TX_STATUS_MSK; | ||
129 | |||
130 | switch (status) { | ||
131 | case AGG_TX_STATE_UNDERRUN_MSK: | ||
132 | priv->_agn.reply_agg_tx_stats.underrun++; | ||
133 | break; | ||
134 | case AGG_TX_STATE_BT_PRIO_MSK: | ||
135 | priv->_agn.reply_agg_tx_stats.bt_prio++; | ||
136 | break; | ||
137 | case AGG_TX_STATE_FEW_BYTES_MSK: | ||
138 | priv->_agn.reply_agg_tx_stats.few_bytes++; | ||
139 | break; | ||
140 | case AGG_TX_STATE_ABORT_MSK: | ||
141 | priv->_agn.reply_agg_tx_stats.abort++; | ||
142 | break; | ||
143 | case AGG_TX_STATE_LAST_SENT_TTL_MSK: | ||
144 | priv->_agn.reply_agg_tx_stats.last_sent_ttl++; | ||
145 | break; | ||
146 | case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: | ||
147 | priv->_agn.reply_agg_tx_stats.last_sent_try++; | ||
148 | break; | ||
149 | case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: | ||
150 | priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++; | ||
151 | break; | ||
152 | case AGG_TX_STATE_SCD_QUERY_MSK: | ||
153 | priv->_agn.reply_agg_tx_stats.scd_query++; | ||
154 | break; | ||
155 | case AGG_TX_STATE_TEST_BAD_CRC32_MSK: | ||
156 | priv->_agn.reply_agg_tx_stats.bad_crc32++; | ||
157 | break; | ||
158 | case AGG_TX_STATE_RESPONSE_MSK: | ||
159 | priv->_agn.reply_agg_tx_stats.response++; | ||
160 | break; | ||
161 | case AGG_TX_STATE_DUMP_TX_MSK: | ||
162 | priv->_agn.reply_agg_tx_stats.dump_tx++; | ||
163 | break; | ||
164 | case AGG_TX_STATE_DELAY_TX_MSK: | ||
165 | priv->_agn.reply_agg_tx_stats.delay_tx++; | ||
166 | break; | ||
167 | default: | ||
168 | priv->_agn.reply_agg_tx_stats.unknown++; | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static void iwlagn_set_tx_status(struct iwl_priv *priv, | ||
174 | struct ieee80211_tx_info *info, | ||
175 | struct iwl5000_tx_resp *tx_resp, | ||
176 | int txq_id, bool is_agg) | ||
177 | { | ||
178 | u16 status = le16_to_cpu(tx_resp->status.status); | ||
179 | |||
180 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
181 | if (is_agg) | ||
182 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
183 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
184 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | ||
185 | info); | ||
186 | if (!iwl_is_tx_success(status)) | ||
187 | iwlagn_count_tx_err_status(priv, status); | ||
188 | |||
189 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
190 | "0x%x retries %d\n", | ||
191 | txq_id, | ||
192 | iwl_get_tx_fail_reason(status), status, | ||
193 | le32_to_cpu(tx_resp->rate_n_flags), | ||
194 | tx_resp->failure_frame); | ||
195 | } | ||
196 | |||
197 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
198 | #define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x | ||
199 | |||
200 | const char *iwl_get_agg_tx_fail_reason(u16 status) | ||
201 | { | ||
202 | status &= AGG_TX_STATUS_MSK; | ||
203 | switch (status) { | ||
204 | case AGG_TX_STATE_TRANSMITTED: | ||
205 | return "SUCCESS"; | ||
206 | AGG_TX_STATE_FAIL(UNDERRUN_MSK); | ||
207 | AGG_TX_STATE_FAIL(BT_PRIO_MSK); | ||
208 | AGG_TX_STATE_FAIL(FEW_BYTES_MSK); | ||
209 | AGG_TX_STATE_FAIL(ABORT_MSK); | ||
210 | AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); | ||
211 | AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); | ||
212 | AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); | ||
213 | AGG_TX_STATE_FAIL(SCD_QUERY_MSK); | ||
214 | AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); | ||
215 | AGG_TX_STATE_FAIL(RESPONSE_MSK); | ||
216 | AGG_TX_STATE_FAIL(DUMP_TX_MSK); | ||
217 | AGG_TX_STATE_FAIL(DELAY_TX_MSK); | ||
218 | } | ||
219 | |||
220 | return "UNKNOWN"; | ||
221 | } | ||
222 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
223 | |||
49 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | 224 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, |
50 | struct iwl_ht_agg *agg, | 225 | struct iwl_ht_agg *agg, |
51 | struct iwl5000_tx_resp *tx_resp, | 226 | struct iwl5000_tx_resp *tx_resp, |
@@ -53,9 +228,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
53 | { | 228 | { |
54 | u16 status; | 229 | u16 status; |
55 | struct agg_tx_status *frame_status = &tx_resp->status; | 230 | struct agg_tx_status *frame_status = &tx_resp->status; |
56 | struct ieee80211_tx_info *info = NULL; | ||
57 | struct ieee80211_hdr *hdr = NULL; | 231 | struct ieee80211_hdr *hdr = NULL; |
58 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
59 | int i, sh, idx; | 232 | int i, sh, idx; |
60 | u16 seq; | 233 | u16 seq; |
61 | 234 | ||
@@ -64,31 +237,20 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
64 | 237 | ||
65 | agg->frame_count = tx_resp->frame_count; | 238 | agg->frame_count = tx_resp->frame_count; |
66 | agg->start_idx = start_idx; | 239 | agg->start_idx = start_idx; |
67 | agg->rate_n_flags = rate_n_flags; | 240 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); |
68 | agg->bitmap = 0; | 241 | agg->bitmap = 0; |
69 | 242 | ||
70 | /* # frames attempted by Tx command */ | 243 | /* # frames attempted by Tx command */ |
71 | if (agg->frame_count == 1) { | 244 | if (agg->frame_count == 1) { |
72 | /* Only one frame was attempted; no block-ack will arrive */ | 245 | /* Only one frame was attempted; no block-ack will arrive */ |
73 | status = le16_to_cpu(frame_status[0].status); | ||
74 | idx = start_idx; | 246 | idx = start_idx; |
75 | 247 | ||
76 | /* FIXME: code repetition */ | ||
77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | 248 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", |
78 | agg->frame_count, agg->start_idx, idx); | 249 | agg->frame_count, agg->start_idx, idx); |
79 | 250 | iwlagn_set_tx_status(priv, | |
80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); | 251 | IEEE80211_SKB_CB( |
81 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 252 | priv->txq[txq_id].txb[idx].skb), |
82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 253 | tx_resp, txq_id, true); |
83 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
84 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
85 | |||
86 | /* FIXME: code repetition end */ | ||
87 | |||
88 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
89 | status & 0xff, tx_resp->failure_frame); | ||
90 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
91 | |||
92 | agg->wait_for_ba = 0; | 254 | agg->wait_for_ba = 0; |
93 | } else { | 255 | } else { |
94 | /* Two or more frames were attempted; expect block-ack */ | 256 | /* Two or more frames were attempted; expect block-ack */ |
@@ -109,12 +271,20 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
109 | idx = SEQ_TO_INDEX(seq); | 271 | idx = SEQ_TO_INDEX(seq); |
110 | txq_id = SEQ_TO_QUEUE(seq); | 272 | txq_id = SEQ_TO_QUEUE(seq); |
111 | 273 | ||
274 | if (status & AGG_TX_STATUS_MSK) | ||
275 | iwlagn_count_agg_tx_err_status(priv, status); | ||
276 | |||
112 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | 277 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | |
113 | AGG_TX_STATE_ABORT_MSK)) | 278 | AGG_TX_STATE_ABORT_MSK)) |
114 | continue; | 279 | continue; |
115 | 280 | ||
116 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | 281 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", |
117 | agg->frame_count, txq_id, idx); | 282 | agg->frame_count, txq_id, idx); |
283 | IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " | ||
284 | "try-count (0x%08x)\n", | ||
285 | iwl_get_agg_tx_fail_reason(status), | ||
286 | status & AGG_TX_STATUS_MSK, | ||
287 | status & AGG_TX_TRY_MSK); | ||
118 | 288 | ||
119 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 289 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); |
120 | if (!hdr) { | 290 | if (!hdr) { |
@@ -281,20 +451,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
281 | } | 451 | } |
282 | } else { | 452 | } else { |
283 | BUG_ON(txq_id != txq->swq_id); | 453 | BUG_ON(txq_id != txq->swq_id); |
284 | 454 | iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); | |
285 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
286 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
287 | iwlagn_hwrate_to_tx_control(priv, | ||
288 | le32_to_cpu(tx_resp->rate_n_flags), | ||
289 | info); | ||
290 | |||
291 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
292 | "0x%x retries %d\n", | ||
293 | txq_id, | ||
294 | iwl_get_tx_fail_reason(status), status, | ||
295 | le32_to_cpu(tx_resp->rate_n_flags), | ||
296 | tx_resp->failure_frame); | ||
297 | |||
298 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | 455 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
299 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 456 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
300 | 457 | ||
@@ -1154,7 +1311,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
1154 | return added; | 1311 | return added; |
1155 | } | 1312 | } |
1156 | 1313 | ||
1157 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | 1314 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) |
1158 | { | 1315 | { |
1159 | struct iwl_host_cmd cmd = { | 1316 | struct iwl_host_cmd cmd = { |
1160 | .id = REPLY_SCAN_CMD, | 1317 | .id = REPLY_SCAN_CMD, |
@@ -1162,7 +1319,6 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1162 | .flags = CMD_SIZE_HUGE, | 1319 | .flags = CMD_SIZE_HUGE, |
1163 | }; | 1320 | }; |
1164 | struct iwl_scan_cmd *scan; | 1321 | struct iwl_scan_cmd *scan; |
1165 | struct ieee80211_conf *conf = NULL; | ||
1166 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 1322 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
1167 | u32 rate_flags = 0; | 1323 | u32 rate_flags = 0; |
1168 | u16 cmd_len; | 1324 | u16 cmd_len; |
@@ -1175,59 +1331,20 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1175 | int chan_mod; | 1331 | int chan_mod; |
1176 | u8 active_chains; | 1332 | u8 active_chains; |
1177 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 1333 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; |
1334 | int ret; | ||
1335 | |||
1336 | lockdep_assert_held(&priv->mutex); | ||
1178 | 1337 | ||
1179 | if (vif) | 1338 | if (vif) |
1180 | ctx = iwl_rxon_ctx_from_vif(vif); | 1339 | ctx = iwl_rxon_ctx_from_vif(vif); |
1181 | 1340 | ||
1182 | conf = ieee80211_get_hw_conf(priv->hw); | ||
1183 | |||
1184 | cancel_delayed_work(&priv->scan_check); | ||
1185 | |||
1186 | if (!iwl_is_ready(priv)) { | ||
1187 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
1188 | goto done; | ||
1189 | } | ||
1190 | |||
1191 | /* Make sure the scan wasn't canceled before this queued work | ||
1192 | * was given the chance to run... */ | ||
1193 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
1194 | goto done; | ||
1195 | |||
1196 | /* This should never be called or scheduled if there is currently | ||
1197 | * a scan active in the hardware. */ | ||
1198 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
1199 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " | ||
1200 | "Ignoring second request.\n"); | ||
1201 | goto done; | ||
1202 | } | ||
1203 | |||
1204 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
1205 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
1206 | goto done; | ||
1207 | } | ||
1208 | |||
1209 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
1210 | IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); | ||
1211 | goto done; | ||
1212 | } | ||
1213 | |||
1214 | if (iwl_is_rfkill(priv)) { | ||
1215 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
1216 | goto done; | ||
1217 | } | ||
1218 | |||
1219 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
1220 | IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); | ||
1221 | goto done; | ||
1222 | } | ||
1223 | |||
1224 | if (!priv->scan_cmd) { | 1341 | if (!priv->scan_cmd) { |
1225 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | 1342 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + |
1226 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | 1343 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); |
1227 | if (!priv->scan_cmd) { | 1344 | if (!priv->scan_cmd) { |
1228 | IWL_DEBUG_SCAN(priv, | 1345 | IWL_DEBUG_SCAN(priv, |
1229 | "fail to allocate memory for scan\n"); | 1346 | "fail to allocate memory for scan\n"); |
1230 | goto done; | 1347 | return -ENOMEM; |
1231 | } | 1348 | } |
1232 | } | 1349 | } |
1233 | scan = priv->scan_cmd; | 1350 | scan = priv->scan_cmd; |
@@ -1334,8 +1451,8 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1334 | IWL_GOOD_CRC_TH_NEVER; | 1451 | IWL_GOOD_CRC_TH_NEVER; |
1335 | break; | 1452 | break; |
1336 | default: | 1453 | default: |
1337 | IWL_WARN(priv, "Invalid scan band count\n"); | 1454 | IWL_WARN(priv, "Invalid scan band\n"); |
1338 | goto done; | 1455 | return -EIO; |
1339 | } | 1456 | } |
1340 | 1457 | ||
1341 | band = priv->scan_band; | 1458 | band = priv->scan_band; |
@@ -1415,7 +1532,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1415 | } | 1532 | } |
1416 | if (scan->channel_count == 0) { | 1533 | if (scan->channel_count == 0) { |
1417 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 1534 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
1418 | goto done; | 1535 | return -EIO; |
1419 | } | 1536 | } |
1420 | 1537 | ||
1421 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | 1538 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + |
@@ -1423,30 +1540,21 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1423 | cmd.data = scan; | 1540 | cmd.data = scan; |
1424 | scan->len = cpu_to_le16(cmd.len); | 1541 | scan->len = cpu_to_le16(cmd.len); |
1425 | 1542 | ||
1426 | set_bit(STATUS_SCAN_HW, &priv->status); | 1543 | if (priv->cfg->ops->hcmd->set_pan_params) { |
1427 | 1544 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | |
1428 | if (priv->cfg->ops->hcmd->set_pan_params && | 1545 | if (ret) |
1429 | priv->cfg->ops->hcmd->set_pan_params(priv)) | 1546 | return ret; |
1430 | goto done; | 1547 | } |
1431 | 1548 | ||
1432 | if (iwl_send_cmd_sync(priv, &cmd)) | 1549 | set_bit(STATUS_SCAN_HW, &priv->status); |
1433 | goto done; | 1550 | ret = iwl_send_cmd_sync(priv, &cmd); |
1551 | if (ret) { | ||
1552 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
1553 | if (priv->cfg->ops->hcmd->set_pan_params) | ||
1554 | priv->cfg->ops->hcmd->set_pan_params(priv); | ||
1555 | } | ||
1434 | 1556 | ||
1435 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 1557 | return ret; |
1436 | IWL_SCAN_CHECK_WATCHDOG); | ||
1437 | |||
1438 | return; | ||
1439 | |||
1440 | done: | ||
1441 | /* Cannot perform scan. Make sure we clear scanning | ||
1442 | * bits from status so next scan request can be performed. | ||
1443 | * If we don't clear scanning status bit here all next scan | ||
1444 | * will fail | ||
1445 | */ | ||
1446 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
1447 | clear_bit(STATUS_SCANNING, &priv->status); | ||
1448 | /* inform mac80211 scan aborted */ | ||
1449 | queue_work(priv->workqueue, &priv->scan_completed); | ||
1450 | } | 1558 | } |
1451 | 1559 | ||
1452 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 1560 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
@@ -1673,6 +1781,8 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
1673 | bt_cmd.kill_ack_mask = priv->kill_ack_mask; | 1781 | bt_cmd.kill_ack_mask = priv->kill_ack_mask; |
1674 | bt_cmd.kill_cts_mask = priv->kill_cts_mask; | 1782 | bt_cmd.kill_cts_mask = priv->kill_cts_mask; |
1675 | bt_cmd.valid = priv->bt_valid; | 1783 | bt_cmd.valid = priv->bt_valid; |
1784 | bt_cmd.tx_prio_boost = 0; | ||
1785 | bt_cmd.rx_prio_boost = 0; | ||
1676 | 1786 | ||
1677 | /* | 1787 | /* |
1678 | * Configure BT coex mode to "no coexistence" when the | 1788 | * Configure BT coex mode to "no coexistence" when the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 3970ab1deaf9..357cdb26f16d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -453,15 +453,6 @@ static inline u8 first_antenna(u8 mask) | |||
453 | } | 453 | } |
454 | 454 | ||
455 | 455 | ||
456 | static inline u8 iwl_get_prev_ieee_rate(u8 rate_index) | ||
457 | { | ||
458 | u8 rate = iwl_rates[rate_index].prev_ieee; | ||
459 | |||
460 | if (rate == IWL_RATE_INVALID) | ||
461 | rate = rate_index; | ||
462 | return rate; | ||
463 | } | ||
464 | |||
465 | static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) | 456 | static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) |
466 | { | 457 | { |
467 | u8 rate = iwl3945_rates[rate_index].prev_ieee; | 458 | u8 rate = iwl3945_rates[rate_index].prev_ieee; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a7961bf395fc..8bfb0495a76b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -307,6 +307,17 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) | |||
307 | goto restart; | 307 | goto restart; |
308 | } | 308 | } |
309 | 309 | ||
310 | if (priv->cfg->advanced_bt_coexist) { | ||
311 | /* | ||
312 | * Tell uCode we are ready to perform calibration | ||
313 | * need to perform this before any calibration | ||
314 | * no need to close the envlope since we are going | ||
315 | * to load the runtime uCode later. | ||
316 | */ | ||
317 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, | ||
318 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
319 | |||
320 | } | ||
310 | iwlagn_send_calib_cfg(priv); | 321 | iwlagn_send_calib_cfg(priv); |
311 | return; | 322 | return; |
312 | 323 | ||
@@ -364,7 +375,7 @@ static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
364 | 0, 0, 0, 0, 0, 0, 0 | 375 | 0, 0, 0, 0, 0, 0, 0 |
365 | }; | 376 | }; |
366 | 377 | ||
367 | static void iwlagn_send_prio_tbl(struct iwl_priv *priv) | 378 | void iwlagn_send_prio_tbl(struct iwl_priv *priv) |
368 | { | 379 | { |
369 | struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; | 380 | struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; |
370 | 381 | ||
@@ -375,7 +386,7 @@ static void iwlagn_send_prio_tbl(struct iwl_priv *priv) | |||
375 | IWL_ERR(priv, "failed to send BT prio tbl command\n"); | 386 | IWL_ERR(priv, "failed to send BT prio tbl command\n"); |
376 | } | 387 | } |
377 | 388 | ||
378 | static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) | 389 | void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) |
379 | { | 390 | { |
380 | struct iwl_bt_coex_prot_env_cmd env_cmd; | 391 | struct iwl_bt_coex_prot_env_cmd env_cmd; |
381 | 392 | ||
@@ -482,25 +493,6 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
482 | 493 | ||
483 | spin_unlock_irqrestore(&priv->lock, flags); | 494 | spin_unlock_irqrestore(&priv->lock, flags); |
484 | 495 | ||
485 | if (priv->cfg->advanced_bt_coexist) { | ||
486 | /* Configure Bluetooth device coexistence support */ | ||
487 | /* need to perform this before any calibration */ | ||
488 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | ||
489 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | ||
490 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | ||
491 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
492 | priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; | ||
493 | |||
494 | if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
495 | iwlagn_send_prio_tbl(priv); | ||
496 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, | ||
497 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
498 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, | ||
499 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
500 | } | ||
501 | |||
502 | } | ||
503 | |||
504 | iwlagn_send_wimax_coex(priv); | 496 | iwlagn_send_wimax_coex(priv); |
505 | 497 | ||
506 | iwlagn_set_Xtal_calib(priv); | 498 | iwlagn_set_Xtal_calib(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ad0e67f5c0d4..646864a26eaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -110,6 +110,9 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
110 | if (!iwl_is_alive(priv)) | 110 | if (!iwl_is_alive(priv)) |
111 | return -EBUSY; | 111 | return -EBUSY; |
112 | 112 | ||
113 | if (!ctx->is_active) | ||
114 | return 0; | ||
115 | |||
113 | /* always get timestamp with Rx frame */ | 116 | /* always get timestamp with Rx frame */ |
114 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; | 117 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; |
115 | 118 | ||
@@ -223,9 +226,8 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
223 | return ret; | 226 | return ret; |
224 | } | 227 | } |
225 | } | 228 | } |
226 | |||
227 | priv->start_calib = 0; | ||
228 | if (new_assoc) { | 229 | if (new_assoc) { |
230 | priv->start_calib = 0; | ||
229 | /* Apply the new configuration | 231 | /* Apply the new configuration |
230 | * RXON assoc doesn't clear the station table in uCode, | 232 | * RXON assoc doesn't clear the station table in uCode, |
231 | */ | 233 | */ |
@@ -369,7 +371,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
369 | 371 | ||
370 | if (!priv->beacon_ctx) { | 372 | if (!priv->beacon_ctx) { |
371 | IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); | 373 | IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); |
372 | return -EINVAL; | 374 | return 0; |
373 | } | 375 | } |
374 | 376 | ||
375 | /* Initialize memory */ | 377 | /* Initialize memory */ |
@@ -1278,7 +1280,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1278 | IWL_ERR(priv, "Microcode SW error detected. " | 1280 | IWL_ERR(priv, "Microcode SW error detected. " |
1279 | " Restarting 0x%X.\n", inta); | 1281 | " Restarting 0x%X.\n", inta); |
1280 | priv->isr_stats.sw++; | 1282 | priv->isr_stats.sw++; |
1281 | priv->isr_stats.sw_err = inta; | ||
1282 | iwl_irq_handle_error(priv); | 1283 | iwl_irq_handle_error(priv); |
1283 | handled |= CSR_INT_BIT_SW_ERR; | 1284 | handled |= CSR_INT_BIT_SW_ERR; |
1284 | } | 1285 | } |
@@ -1459,7 +1460,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1459 | IWL_ERR(priv, "Microcode SW error detected. " | 1460 | IWL_ERR(priv, "Microcode SW error detected. " |
1460 | " Restarting 0x%X.\n", inta); | 1461 | " Restarting 0x%X.\n", inta); |
1461 | priv->isr_stats.sw++; | 1462 | priv->isr_stats.sw++; |
1462 | priv->isr_stats.sw_err = inta; | ||
1463 | iwl_irq_handle_error(priv); | 1463 | iwl_irq_handle_error(priv); |
1464 | handled |= CSR_INT_BIT_SW_ERR; | 1464 | handled |= CSR_INT_BIT_SW_ERR; |
1465 | } | 1465 | } |
@@ -2467,6 +2467,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2467 | } | 2467 | } |
2468 | 2468 | ||
2469 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | 2469 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); |
2470 | priv->isr_stats.err_code = desc; | ||
2470 | pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); | 2471 | pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); |
2471 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | 2472 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); |
2472 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | 2473 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); |
@@ -2813,6 +2814,22 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2813 | if (iwl_is_rfkill(priv)) | 2814 | if (iwl_is_rfkill(priv)) |
2814 | return; | 2815 | return; |
2815 | 2816 | ||
2817 | if (priv->cfg->advanced_bt_coexist) { | ||
2818 | /* Configure Bluetooth device coexistence support */ | ||
2819 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | ||
2820 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | ||
2821 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | ||
2822 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
2823 | priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; | ||
2824 | if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) | ||
2825 | iwlagn_send_prio_tbl(priv); | ||
2826 | |||
2827 | /* FIXME: w/a to force change uCode BT state machine */ | ||
2828 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, | ||
2829 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
2830 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, | ||
2831 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
2832 | } | ||
2816 | ieee80211_wake_queues(priv->hw); | 2833 | ieee80211_wake_queues(priv->hw); |
2817 | 2834 | ||
2818 | priv->active_rate = IWL_RATES_MASK; | 2835 | priv->active_rate = IWL_RATES_MASK; |
@@ -2875,8 +2892,9 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2875 | 2892 | ||
2876 | IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); | 2893 | IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); |
2877 | 2894 | ||
2878 | if (!exit_pending) | 2895 | iwl_scan_cancel_timeout(priv, 200); |
2879 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2896 | |
2897 | exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2880 | 2898 | ||
2881 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set | 2899 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set |
2882 | * to prevent rearm timer */ | 2900 | * to prevent rearm timer */ |
@@ -3486,15 +3504,6 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) | |||
3486 | 3504 | ||
3487 | priv->is_open = 0; | 3505 | priv->is_open = 0; |
3488 | 3506 | ||
3489 | if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
3490 | /* stop mac, cancel any scan request and clear | ||
3491 | * RXON_FILTER_ASSOC_MSK BIT | ||
3492 | */ | ||
3493 | mutex_lock(&priv->mutex); | ||
3494 | iwl_scan_cancel_timeout(priv, 100); | ||
3495 | mutex_unlock(&priv->mutex); | ||
3496 | } | ||
3497 | |||
3498 | iwl_down(priv); | 3507 | iwl_down(priv); |
3499 | 3508 | ||
3500 | flush_workqueue(priv->workqueue); | 3509 | flush_workqueue(priv->workqueue); |
@@ -4062,13 +4071,15 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
4062 | priv->cfg->ops->lib->cancel_deferred_work(priv); | 4071 | priv->cfg->ops->lib->cancel_deferred_work(priv); |
4063 | 4072 | ||
4064 | cancel_delayed_work_sync(&priv->init_alive_start); | 4073 | cancel_delayed_work_sync(&priv->init_alive_start); |
4065 | cancel_delayed_work(&priv->scan_check); | ||
4066 | cancel_work_sync(&priv->start_internal_scan); | ||
4067 | cancel_delayed_work(&priv->alive_start); | 4074 | cancel_delayed_work(&priv->alive_start); |
4068 | cancel_work_sync(&priv->run_time_calib_work); | 4075 | cancel_work_sync(&priv->run_time_calib_work); |
4069 | cancel_work_sync(&priv->beacon_update); | 4076 | cancel_work_sync(&priv->beacon_update); |
4077 | |||
4078 | iwl_cancel_scan_deferred_work(priv); | ||
4079 | |||
4070 | cancel_work_sync(&priv->bt_full_concurrency); | 4080 | cancel_work_sync(&priv->bt_full_concurrency); |
4071 | cancel_work_sync(&priv->bt_runtime_config); | 4081 | cancel_work_sync(&priv->bt_runtime_config); |
4082 | |||
4072 | del_timer_sync(&priv->statistics_periodic); | 4083 | del_timer_sync(&priv->statistics_periodic); |
4073 | del_timer_sync(&priv->ucode_trace); | 4084 | del_timer_sync(&priv->ucode_trace); |
4074 | } | 4085 | } |
@@ -4286,6 +4297,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4286 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) | 4297 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) |
4287 | priv->contexts[i].ctxid = i; | 4298 | priv->contexts[i].ctxid = i; |
4288 | 4299 | ||
4300 | priv->contexts[IWL_RXON_CTX_BSS].always_active = true; | ||
4301 | priv->contexts[IWL_RXON_CTX_BSS].is_active = true; | ||
4289 | priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; | 4302 | priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; |
4290 | priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; | 4303 | priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; |
4291 | priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; | 4304 | priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 7c542a8c8f81..a372184ac210 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -134,6 +134,8 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, | |||
134 | void iwlagn_init_alive_start(struct iwl_priv *priv); | 134 | void iwlagn_init_alive_start(struct iwl_priv *priv); |
135 | int iwlagn_alive_notify(struct iwl_priv *priv); | 135 | int iwlagn_alive_notify(struct iwl_priv *priv); |
136 | int iwl_verify_ucode(struct iwl_priv *priv); | 136 | int iwl_verify_ucode(struct iwl_priv *priv); |
137 | void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | ||
138 | void iwlagn_send_prio_tbl(struct iwl_priv *priv); | ||
137 | 139 | ||
138 | /* lib */ | 140 | /* lib */ |
139 | void iwl_check_abort_status(struct iwl_priv *priv, | 141 | void iwl_check_abort_status(struct iwl_priv *priv, |
@@ -217,7 +219,7 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
217 | struct iwl_rx_mem_buffer *rxb); | 219 | struct iwl_rx_mem_buffer *rxb); |
218 | 220 | ||
219 | /* scan */ | 221 | /* scan */ |
220 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | 222 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); |
221 | 223 | ||
222 | /* station mgmt */ | 224 | /* station mgmt */ |
223 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 225 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
@@ -236,4 +238,9 @@ void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); | |||
236 | void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); | 238 | void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); |
237 | void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); | 239 | void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); |
238 | 240 | ||
241 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
242 | const char *iwl_get_agg_tx_fail_reason(u16 status); | ||
243 | #else | ||
244 | static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; } | ||
245 | #endif | ||
239 | #endif /* __iwl_agn_h__ */ | 246 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 3e4ba31b5d59..27e250c8d4b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1820,13 +1820,8 @@ enum { | |||
1820 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, | 1820 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, |
1821 | TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, | 1821 | TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, |
1822 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, | 1822 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, |
1823 | /* uCode drop due to FW drop request */ | 1823 | TX_STATUS_FAIL_PASSIVE_NO_RX = 0x90, |
1824 | TX_STATUS_FAIL_FW_DROP = 0x90, | 1824 | TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, |
1825 | /* | ||
1826 | * uCode drop due to station color mismatch | ||
1827 | * between tx command and station table | ||
1828 | */ | ||
1829 | TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91, | ||
1830 | }; | 1825 | }; |
1831 | 1826 | ||
1832 | #define TX_PACKET_MODE_REGULAR 0x0000 | 1827 | #define TX_PACKET_MODE_REGULAR 0x0000 |
@@ -1868,6 +1863,9 @@ enum { | |||
1868 | AGG_TX_STATE_DELAY_TX_MSK = 0x400 | 1863 | AGG_TX_STATE_DELAY_TX_MSK = 0x400 |
1869 | }; | 1864 | }; |
1870 | 1865 | ||
1866 | #define AGG_TX_STATUS_MSK 0x00000fff /* bits 0:11 */ | ||
1867 | #define AGG_TX_TRY_MSK 0x0000f000 /* bits 12:15 */ | ||
1868 | |||
1871 | #define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \ | 1869 | #define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \ |
1872 | AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ | 1870 | AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ |
1873 | AGG_TX_STATE_LAST_SENT_BT_KILL_MSK) | 1871 | AGG_TX_STATE_LAST_SENT_BT_KILL_MSK) |
@@ -2488,7 +2486,12 @@ struct iwlagn_bt_cmd { | |||
2488 | __le16 bt4_decision_time; /* unused */ | 2486 | __le16 bt4_decision_time; /* unused */ |
2489 | __le16 valid; | 2487 | __le16 valid; |
2490 | u8 prio_boost; | 2488 | u8 prio_boost; |
2491 | u8 reserved[3]; | 2489 | /* |
2490 | * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask | ||
2491 | * if configure the following patterns | ||
2492 | */ | ||
2493 | u8 tx_prio_boost; /* SW boost of WiFi tx priority */ | ||
2494 | __le16 rx_prio_boost; /* SW boost of WiFi rx priority */ | ||
2492 | }; | 2495 | }; |
2493 | 2496 | ||
2494 | #define IWLAGN_BT_SCO_ACTIVE cpu_to_le32(BIT(0)) | 2497 | #define IWLAGN_BT_SCO_ACTIVE cpu_to_le32(BIT(0)) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 87a2e40972ba..393f02d94c4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -196,6 +196,9 @@ static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
196 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 196 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
197 | return; | 197 | return; |
198 | 198 | ||
199 | if (!ctx->is_active) | ||
200 | return; | ||
201 | |||
199 | ctx->qos_data.def_qos_parm.qos_flags = 0; | 202 | ctx->qos_data.def_qos_parm.qos_flags = 0; |
200 | 203 | ||
201 | if (ctx->qos_data.qos_active) | 204 | if (ctx->qos_data.qos_active) |
@@ -488,8 +491,29 @@ EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); | |||
488 | 491 | ||
489 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | 492 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) |
490 | { | 493 | { |
491 | u16 new_val = 0; | 494 | u16 new_val; |
492 | u16 beacon_factor = 0; | 495 | u16 beacon_factor; |
496 | |||
497 | /* | ||
498 | * If mac80211 hasn't given us a beacon interval, program | ||
499 | * the default into the device (not checking this here | ||
500 | * would cause the adjustment below to return the maximum | ||
501 | * value, which may break PAN.) | ||
502 | */ | ||
503 | if (!beacon_val) | ||
504 | return DEFAULT_BEACON_INTERVAL; | ||
505 | |||
506 | /* | ||
507 | * If the beacon interval we obtained from the peer | ||
508 | * is too large, we'll have to wake up more often | ||
509 | * (and in IBSS case, we'll beacon too much) | ||
510 | * | ||
511 | * For example, if max_beacon_val is 4096, and the | ||
512 | * requested beacon interval is 7000, we'll have to | ||
513 | * use 3500 to be able to wake up on the beacons. | ||
514 | * | ||
515 | * This could badly influence beacon detection stats. | ||
516 | */ | ||
493 | 517 | ||
494 | beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; | 518 | beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; |
495 | new_val = beacon_val / beacon_factor; | 519 | new_val = beacon_val / beacon_factor; |
@@ -526,10 +550,22 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
526 | ctx->timing.atim_window = 0; | 550 | ctx->timing.atim_window = 0; |
527 | 551 | ||
528 | if (ctx->ctxid == IWL_RXON_CTX_PAN && | 552 | if (ctx->ctxid == IWL_RXON_CTX_PAN && |
529 | (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION)) { | 553 | (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) && |
554 | iwl_is_associated(priv, IWL_RXON_CTX_BSS) && | ||
555 | priv->contexts[IWL_RXON_CTX_BSS].vif && | ||
556 | priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) { | ||
530 | ctx->timing.beacon_interval = | 557 | ctx->timing.beacon_interval = |
531 | priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; | 558 | priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; |
532 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | 559 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); |
560 | } else if (ctx->ctxid == IWL_RXON_CTX_BSS && | ||
561 | iwl_is_associated(priv, IWL_RXON_CTX_PAN) && | ||
562 | priv->contexts[IWL_RXON_CTX_PAN].vif && | ||
563 | priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int && | ||
564 | (!iwl_is_associated_ctx(ctx) || !ctx->vif || | ||
565 | !ctx->vif->bss_conf.beacon_int)) { | ||
566 | ctx->timing.beacon_interval = | ||
567 | priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval; | ||
568 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
533 | } else { | 569 | } else { |
534 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | 570 | beacon_int = iwl_adjust_beacon_interval(beacon_int, |
535 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); | 571 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); |
@@ -1797,9 +1833,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
1797 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); | 1833 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
1798 | } | 1834 | } |
1799 | 1835 | ||
1800 | if (changes & BSS_CHANGED_BEACON_INT) { | 1836 | if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) |
1801 | /* TODO: in AP mode, do something to make this take effect */ | 1837 | iwl_send_rxon_timing(priv, ctx); |
1802 | } | ||
1803 | 1838 | ||
1804 | if (changes & BSS_CHANGED_BSSID) { | 1839 | if (changes & BSS_CHANGED_BSSID) { |
1805 | IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); | 1840 | IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); |
@@ -2009,9 +2044,14 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2009 | */ | 2044 | */ |
2010 | priv->iw_mode = vif->type; | 2045 | priv->iw_mode = vif->type; |
2011 | 2046 | ||
2047 | ctx->is_active = true; | ||
2048 | |||
2012 | err = iwl_set_mode(priv, vif); | 2049 | err = iwl_set_mode(priv, vif); |
2013 | if (err) | 2050 | if (err) { |
2051 | if (!ctx->always_active) | ||
2052 | ctx->is_active = false; | ||
2014 | goto out_err; | 2053 | goto out_err; |
2054 | } | ||
2015 | 2055 | ||
2016 | if (priv->cfg->advanced_bt_coexist && | 2056 | if (priv->cfg->advanced_bt_coexist && |
2017 | vif->type == NL80211_IFTYPE_ADHOC) { | 2057 | vif->type == NL80211_IFTYPE_ADHOC) { |
@@ -2041,7 +2081,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2041 | { | 2081 | { |
2042 | struct iwl_priv *priv = hw->priv; | 2082 | struct iwl_priv *priv = hw->priv; |
2043 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 2083 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
2044 | bool scan_completed = false; | ||
2045 | 2084 | ||
2046 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2085 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2047 | 2086 | ||
@@ -2050,14 +2089,14 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2050 | WARN_ON(ctx->vif != vif); | 2089 | WARN_ON(ctx->vif != vif); |
2051 | ctx->vif = NULL; | 2090 | ctx->vif = NULL; |
2052 | 2091 | ||
2053 | iwl_scan_cancel_timeout(priv, 100); | ||
2054 | iwl_set_mode(priv, vif); | ||
2055 | |||
2056 | if (priv->scan_vif == vif) { | 2092 | if (priv->scan_vif == vif) { |
2057 | scan_completed = true; | 2093 | iwl_scan_cancel_timeout(priv, 200); |
2058 | priv->scan_vif = NULL; | 2094 | iwl_force_scan_end(priv); |
2059 | priv->scan_request = NULL; | ||
2060 | } | 2095 | } |
2096 | iwl_set_mode(priv, vif); | ||
2097 | |||
2098 | if (!ctx->always_active) | ||
2099 | ctx->is_active = false; | ||
2061 | 2100 | ||
2062 | /* | 2101 | /* |
2063 | * When removing the IBSS interface, overwrite the | 2102 | * When removing the IBSS interface, overwrite the |
@@ -2072,9 +2111,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2072 | memset(priv->bssid, 0, ETH_ALEN); | 2111 | memset(priv->bssid, 0, ETH_ALEN); |
2073 | mutex_unlock(&priv->mutex); | 2112 | mutex_unlock(&priv->mutex); |
2074 | 2113 | ||
2075 | if (scan_completed) | ||
2076 | ieee80211_scan_completed(priv->hw, true); | ||
2077 | |||
2078 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2114 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2079 | 2115 | ||
2080 | } | 2116 | } |
@@ -2255,6 +2291,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2255 | 2291 | ||
2256 | spin_unlock_irqrestore(&priv->lock, flags); | 2292 | spin_unlock_irqrestore(&priv->lock, flags); |
2257 | 2293 | ||
2294 | iwl_scan_cancel_timeout(priv, 100); | ||
2258 | if (!iwl_is_ready_rf(priv)) { | 2295 | if (!iwl_is_ready_rf(priv)) { |
2259 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2296 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2260 | mutex_unlock(&priv->mutex); | 2297 | mutex_unlock(&priv->mutex); |
@@ -2264,7 +2301,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2264 | /* we are restarting association process | 2301 | /* we are restarting association process |
2265 | * clear RXON_FILTER_ASSOC_MSK bit | 2302 | * clear RXON_FILTER_ASSOC_MSK bit |
2266 | */ | 2303 | */ |
2267 | iwl_scan_cancel_timeout(priv, 100); | ||
2268 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2304 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2269 | iwlcore_commit_rxon(priv, ctx); | 2305 | iwlcore_commit_rxon(priv, ctx); |
2270 | 2306 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f7b57ed84f66..f0302bfe85f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -111,7 +111,7 @@ struct iwl_hcmd_utils_ops { | |||
111 | __le16 fc, __le32 *tx_flags); | 111 | __le16 fc, __le32 *tx_flags); |
112 | int (*calc_rssi)(struct iwl_priv *priv, | 112 | int (*calc_rssi)(struct iwl_priv *priv, |
113 | struct iwl_rx_phy_res *rx_resp); | 113 | struct iwl_rx_phy_res *rx_resp); |
114 | void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); | 114 | int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); |
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct iwl_apm_ops { | 117 | struct iwl_apm_ops { |
@@ -130,6 +130,8 @@ struct iwl_debugfs_ops { | |||
130 | size_t count, loff_t *ppos); | 130 | size_t count, loff_t *ppos); |
131 | ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, | 131 | ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, |
132 | size_t count, loff_t *ppos); | 132 | size_t count, loff_t *ppos); |
133 | ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf, | ||
134 | size_t count, loff_t *ppos); | ||
133 | }; | 135 | }; |
134 | 136 | ||
135 | struct iwl_temp_ops { | 137 | struct iwl_temp_ops { |
@@ -553,6 +555,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
553 | void iwl_init_scan_params(struct iwl_priv *priv); | 555 | void iwl_init_scan_params(struct iwl_priv *priv); |
554 | int iwl_scan_cancel(struct iwl_priv *priv); | 556 | int iwl_scan_cancel(struct iwl_priv *priv); |
555 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 557 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
558 | void iwl_force_scan_end(struct iwl_priv *priv); | ||
556 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, | 559 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
557 | struct ieee80211_vif *vif, | 560 | struct ieee80211_vif *vif, |
558 | struct cfg80211_scan_request *req); | 561 | struct cfg80211_scan_request *req); |
@@ -568,6 +571,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
568 | enum ieee80211_band band, | 571 | enum ieee80211_band band, |
569 | struct ieee80211_vif *vif); | 572 | struct ieee80211_vif *vif); |
570 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | 573 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); |
574 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); | ||
571 | 575 | ||
572 | /* For faster active scanning, scan will move to the next channel if fewer than | 576 | /* For faster active scanning, scan will move to the next channel if fewer than |
573 | * PLCP_QUIET_THRESH packets are heard on this channel within | 577 | * PLCP_QUIET_THRESH packets are heard on this channel within |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0ee8f516c4ab..265ad01a443f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -575,10 +575,10 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | |||
575 | priv->isr_stats.hw); | 575 | priv->isr_stats.hw); |
576 | pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", | 576 | pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", |
577 | priv->isr_stats.sw); | 577 | priv->isr_stats.sw); |
578 | if (priv->isr_stats.sw > 0) { | 578 | if (priv->isr_stats.sw || priv->isr_stats.hw) { |
579 | pos += scnprintf(buf + pos, bufsz - pos, | 579 | pos += scnprintf(buf + pos, bufsz - pos, |
580 | "\tLast Restarting Code: 0x%X\n", | 580 | "\tLast Restarting Code: 0x%X\n", |
581 | priv->isr_stats.sw_err); | 581 | priv->isr_stats.err_code); |
582 | } | 582 | } |
583 | #ifdef CONFIG_IWLWIFI_DEBUG | 583 | #ifdef CONFIG_IWLWIFI_DEBUG |
584 | pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", | 584 | pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", |
@@ -1604,6 +1604,56 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, | |||
1604 | return ret; | 1604 | return ret; |
1605 | } | 1605 | } |
1606 | 1606 | ||
1607 | static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, | ||
1608 | char __user *user_buf, | ||
1609 | size_t count, loff_t *ppos) | ||
1610 | { | ||
1611 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
1612 | |||
1613 | int pos = 0; | ||
1614 | char buf[40]; | ||
1615 | const size_t bufsz = sizeof(buf); | ||
1616 | |||
1617 | pos += scnprintf(buf + pos, bufsz - pos, "use %s for aggregation\n", | ||
1618 | (priv->cfg->use_rts_for_aggregation) ? "rts/cts" : | ||
1619 | "cts-to-self"); | ||
1620 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1621 | } | ||
1622 | |||
1623 | static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | ||
1624 | const char __user *user_buf, | ||
1625 | size_t count, loff_t *ppos) { | ||
1626 | |||
1627 | struct iwl_priv *priv = file->private_data; | ||
1628 | char buf[8]; | ||
1629 | int buf_size; | ||
1630 | int rts; | ||
1631 | |||
1632 | memset(buf, 0, sizeof(buf)); | ||
1633 | buf_size = min(count, sizeof(buf) - 1); | ||
1634 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1635 | return -EFAULT; | ||
1636 | if (sscanf(buf, "%d", &rts) != 1) | ||
1637 | return -EINVAL; | ||
1638 | if (rts) | ||
1639 | priv->cfg->use_rts_for_aggregation = true; | ||
1640 | else | ||
1641 | priv->cfg->use_rts_for_aggregation = false; | ||
1642 | return count; | ||
1643 | } | ||
1644 | |||
1645 | static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, | ||
1646 | char __user *user_buf, | ||
1647 | size_t count, loff_t *ppos) | ||
1648 | { | ||
1649 | struct iwl_priv *priv = file->private_data; | ||
1650 | |||
1651 | if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) | ||
1652 | return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( | ||
1653 | file, user_buf, count, ppos); | ||
1654 | else | ||
1655 | return -ENODATA; | ||
1656 | } | ||
1607 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 1657 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
1608 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 1658 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
1609 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 1659 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1629,6 +1679,8 @@ DEBUGFS_WRITE_FILE_OPS(txfifo_flush); | |||
1629 | DEBUGFS_READ_FILE_OPS(ucode_bt_stats); | 1679 | DEBUGFS_READ_FILE_OPS(ucode_bt_stats); |
1630 | DEBUGFS_WRITE_FILE_OPS(monitor_period); | 1680 | DEBUGFS_WRITE_FILE_OPS(monitor_period); |
1631 | DEBUGFS_READ_FILE_OPS(bt_traffic); | 1681 | DEBUGFS_READ_FILE_OPS(bt_traffic); |
1682 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | ||
1683 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | ||
1632 | 1684 | ||
1633 | /* | 1685 | /* |
1634 | * Create the debugfs files and directories | 1686 | * Create the debugfs files and directories |
@@ -1689,6 +1741,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1689 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 1741 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
1690 | if (priv->cfg->ops->lib->dev_txfifo_flush) | 1742 | if (priv->cfg->ops->lib->dev_txfifo_flush) |
1691 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); | 1743 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); |
1744 | DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); | ||
1692 | 1745 | ||
1693 | if (priv->cfg->sensitivity_calib_by_driver) | 1746 | if (priv->cfg->sensitivity_calib_by_driver) |
1694 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 1747 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
@@ -1698,6 +1751,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1698 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 1751 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
1699 | if (priv->cfg->bt_statistics) | 1752 | if (priv->cfg->bt_statistics) |
1700 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); | 1753 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); |
1754 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); | ||
1701 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 1755 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
1702 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 1756 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
1703 | DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); | 1757 | DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4dd38b7b8b74..74d25bcbfcb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -945,7 +945,7 @@ enum iwl_pa_type { | |||
945 | struct isr_statistics { | 945 | struct isr_statistics { |
946 | u32 hw; | 946 | u32 hw; |
947 | u32 sw; | 947 | u32 sw; |
948 | u32 sw_err; | 948 | u32 err_code; |
949 | u32 sch; | 949 | u32 sch; |
950 | u32 alive; | 950 | u32 alive; |
951 | u32 rfkill; | 951 | u32 rfkill; |
@@ -957,6 +957,50 @@ struct isr_statistics { | |||
957 | u32 unhandled; | 957 | u32 unhandled; |
958 | }; | 958 | }; |
959 | 959 | ||
960 | /* reply_tx_statistics (for _agn devices) */ | ||
961 | struct reply_tx_error_statistics { | ||
962 | u32 pp_delay; | ||
963 | u32 pp_few_bytes; | ||
964 | u32 pp_bt_prio; | ||
965 | u32 pp_quiet_period; | ||
966 | u32 pp_calc_ttak; | ||
967 | u32 int_crossed_retry; | ||
968 | u32 short_limit; | ||
969 | u32 long_limit; | ||
970 | u32 fifo_underrun; | ||
971 | u32 drain_flow; | ||
972 | u32 rfkill_flush; | ||
973 | u32 life_expire; | ||
974 | u32 dest_ps; | ||
975 | u32 host_abort; | ||
976 | u32 bt_retry; | ||
977 | u32 sta_invalid; | ||
978 | u32 frag_drop; | ||
979 | u32 tid_disable; | ||
980 | u32 fifo_flush; | ||
981 | u32 insuff_cf_poll; | ||
982 | u32 fail_hw_drop; | ||
983 | u32 sta_color_mismatch; | ||
984 | u32 unknown; | ||
985 | }; | ||
986 | |||
987 | /* reply_agg_tx_statistics (for _agn devices) */ | ||
988 | struct reply_agg_tx_error_statistics { | ||
989 | u32 underrun; | ||
990 | u32 bt_prio; | ||
991 | u32 few_bytes; | ||
992 | u32 abort; | ||
993 | u32 last_sent_ttl; | ||
994 | u32 last_sent_try; | ||
995 | u32 last_sent_bt_kill; | ||
996 | u32 scd_query; | ||
997 | u32 bad_crc32; | ||
998 | u32 response; | ||
999 | u32 dump_tx; | ||
1000 | u32 delay_tx; | ||
1001 | u32 unknown; | ||
1002 | }; | ||
1003 | |||
960 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1004 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
961 | /* management statistics */ | 1005 | /* management statistics */ |
962 | enum iwl_mgmt_stats { | 1006 | enum iwl_mgmt_stats { |
@@ -1116,6 +1160,13 @@ struct iwl_rxon_context { | |||
1116 | const u8 *ac_to_queue; | 1160 | const u8 *ac_to_queue; |
1117 | u8 mcast_queue; | 1161 | u8 mcast_queue; |
1118 | 1162 | ||
1163 | /* | ||
1164 | * We could use the vif to indicate active, but we | ||
1165 | * also need it to be active during disabling when | ||
1166 | * we already removed the vif for type setting. | ||
1167 | */ | ||
1168 | bool always_active, is_active; | ||
1169 | |||
1119 | enum iwl_rxon_context_id ctxid; | 1170 | enum iwl_rxon_context_id ctxid; |
1120 | 1171 | ||
1121 | u32 interface_modes, exclusive_interface_modes; | 1172 | u32 interface_modes, exclusive_interface_modes; |
@@ -1408,6 +1459,9 @@ struct iwl_priv { | |||
1408 | 1459 | ||
1409 | struct iwl_notif_statistics statistics; | 1460 | struct iwl_notif_statistics statistics; |
1410 | struct iwl_bt_notif_statistics statistics_bt; | 1461 | struct iwl_bt_notif_statistics statistics_bt; |
1462 | /* counts reply_tx error */ | ||
1463 | struct reply_tx_error_statistics reply_tx_stats; | ||
1464 | struct reply_agg_tx_error_statistics reply_agg_tx_stats; | ||
1411 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1465 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1412 | struct iwl_notif_statistics accum_statistics; | 1466 | struct iwl_notif_statistics accum_statistics; |
1413 | struct iwl_notif_statistics delta_statistics; | 1467 | struct iwl_notif_statistics delta_statistics; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 7727f0966d31..c54c20023e7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -54,100 +54,134 @@ | |||
54 | #define IWL_PASSIVE_DWELL_BASE (100) | 54 | #define IWL_PASSIVE_DWELL_BASE (100) |
55 | #define IWL_CHANNEL_TUNE_TIME 5 | 55 | #define IWL_CHANNEL_TUNE_TIME 5 |
56 | 56 | ||
57 | static int iwl_send_scan_abort(struct iwl_priv *priv) | ||
58 | { | ||
59 | int ret; | ||
60 | struct iwl_rx_packet *pkt; | ||
61 | struct iwl_host_cmd cmd = { | ||
62 | .id = REPLY_SCAN_ABORT_CMD, | ||
63 | .flags = CMD_WANT_SKB, | ||
64 | }; | ||
57 | 65 | ||
66 | /* Exit instantly with error when device is not ready | ||
67 | * to receive scan abort command or it does not perform | ||
68 | * hardware scan currently */ | ||
69 | if (!test_bit(STATUS_READY, &priv->status) || | ||
70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || | ||
71 | !test_bit(STATUS_SCAN_HW, &priv->status) || | ||
72 | test_bit(STATUS_FW_ERROR, &priv->status) || | ||
73 | test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
74 | return -EIO; | ||
58 | 75 | ||
59 | /** | 76 | ret = iwl_send_cmd_sync(priv, &cmd); |
60 | * iwl_scan_cancel - Cancel any currently executing HW scan | 77 | if (ret) |
61 | * | 78 | return ret; |
62 | * NOTE: priv->mutex is not required before calling this function | 79 | |
63 | */ | 80 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
64 | int iwl_scan_cancel(struct iwl_priv *priv) | 81 | if (pkt->u.status != CAN_ABORT_STATUS) { |
82 | /* The scan abort will return 1 for success or | ||
83 | * 2 for "failure". A failure condition can be | ||
84 | * due to simply not being in an active scan which | ||
85 | * can occur if we send the scan abort before we | ||
86 | * the microcode has notified us that a scan is | ||
87 | * completed. */ | ||
88 | IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status); | ||
89 | ret = -EIO; | ||
90 | } | ||
91 | |||
92 | iwl_free_pages(priv, cmd.reply_page); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | ||
65 | { | 97 | { |
66 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) { | 98 | /* check if scan was requested from mac80211 */ |
67 | clear_bit(STATUS_SCANNING, &priv->status); | 99 | if (priv->scan_request) { |
68 | return 0; | 100 | IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n"); |
101 | ieee80211_scan_completed(priv->hw, aborted); | ||
69 | } | 102 | } |
70 | 103 | ||
71 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 104 | priv->is_internal_short_scan = false; |
72 | if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 105 | priv->scan_vif = NULL; |
73 | IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); | 106 | priv->scan_request = NULL; |
74 | queue_work(priv->workqueue, &priv->abort_scan); | 107 | } |
75 | 108 | ||
76 | } else | 109 | void iwl_force_scan_end(struct iwl_priv *priv) |
77 | IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n"); | 110 | { |
111 | lockdep_assert_held(&priv->mutex); | ||
78 | 112 | ||
79 | return test_bit(STATUS_SCANNING, &priv->status); | 113 | if (!test_bit(STATUS_SCANNING, &priv->status)) { |
114 | IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); | ||
115 | return; | ||
80 | } | 116 | } |
81 | 117 | ||
118 | IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); | ||
119 | clear_bit(STATUS_SCANNING, &priv->status); | ||
120 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
121 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
122 | iwl_complete_scan(priv, true); | ||
123 | } | ||
124 | EXPORT_SYMBOL(iwl_force_scan_end); | ||
125 | |||
126 | static void iwl_do_scan_abort(struct iwl_priv *priv) | ||
127 | { | ||
128 | int ret; | ||
129 | |||
130 | lockdep_assert_held(&priv->mutex); | ||
131 | |||
132 | if (!test_bit(STATUS_SCANNING, &priv->status)) { | ||
133 | IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
138 | IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | ret = iwl_send_scan_abort(priv); | ||
143 | if (ret) { | ||
144 | IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret); | ||
145 | iwl_force_scan_end(priv); | ||
146 | } else | ||
147 | IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n"); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * iwl_scan_cancel - Cancel any currently executing HW scan | ||
152 | */ | ||
153 | int iwl_scan_cancel(struct iwl_priv *priv) | ||
154 | { | ||
155 | IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); | ||
156 | queue_work(priv->workqueue, &priv->abort_scan); | ||
82 | return 0; | 157 | return 0; |
83 | } | 158 | } |
84 | EXPORT_SYMBOL(iwl_scan_cancel); | 159 | EXPORT_SYMBOL(iwl_scan_cancel); |
160 | |||
85 | /** | 161 | /** |
86 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan | 162 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan |
87 | * @ms: amount of time to wait (in milliseconds) for scan to abort | 163 | * @ms: amount of time to wait (in milliseconds) for scan to abort |
88 | * | 164 | * |
89 | * NOTE: priv->mutex must be held before calling this function | ||
90 | */ | 165 | */ |
91 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | 166 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) |
92 | { | 167 | { |
93 | unsigned long now = jiffies; | 168 | unsigned long timeout = jiffies + msecs_to_jiffies(ms); |
94 | int ret; | ||
95 | |||
96 | ret = iwl_scan_cancel(priv); | ||
97 | if (ret && ms) { | ||
98 | mutex_unlock(&priv->mutex); | ||
99 | while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && | ||
100 | test_bit(STATUS_SCANNING, &priv->status)) | ||
101 | msleep(1); | ||
102 | mutex_lock(&priv->mutex); | ||
103 | |||
104 | return test_bit(STATUS_SCANNING, &priv->status); | ||
105 | } | ||
106 | 169 | ||
107 | return ret; | 170 | lockdep_assert_held(&priv->mutex); |
108 | } | ||
109 | EXPORT_SYMBOL(iwl_scan_cancel_timeout); | ||
110 | 171 | ||
111 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 172 | IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); |
112 | { | ||
113 | int ret = 0; | ||
114 | struct iwl_rx_packet *pkt; | ||
115 | struct iwl_host_cmd cmd = { | ||
116 | .id = REPLY_SCAN_ABORT_CMD, | ||
117 | .flags = CMD_WANT_SKB, | ||
118 | }; | ||
119 | 173 | ||
120 | /* If there isn't a scan actively going on in the hardware | 174 | iwl_do_scan_abort(priv); |
121 | * then we are in between scan bands and not actually | ||
122 | * actively scanning, so don't send the abort command */ | ||
123 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
124 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | ret = iwl_send_cmd_sync(priv, &cmd); | ||
129 | if (ret) { | ||
130 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
131 | return ret; | ||
132 | } | ||
133 | 175 | ||
134 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | 176 | while (time_before_eq(jiffies, timeout)) { |
135 | if (pkt->u.status != CAN_ABORT_STATUS) { | 177 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) |
136 | /* The scan abort will return 1 for success or | 178 | break; |
137 | * 2 for "failure". A failure condition can be | 179 | msleep(20); |
138 | * due to simply not being in an active scan which | ||
139 | * can occur if we send the scan abort before we | ||
140 | * the microcode has notified us that a scan is | ||
141 | * completed. */ | ||
142 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status); | ||
143 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
144 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
145 | } | 180 | } |
146 | 181 | ||
147 | iwl_free_pages(priv, cmd.reply_page); | 182 | return test_bit(STATUS_SCAN_HW, &priv->status); |
148 | |||
149 | return ret; | ||
150 | } | 183 | } |
184 | EXPORT_SYMBOL(iwl_scan_cancel_timeout); | ||
151 | 185 | ||
152 | /* Service response to REPLY_SCAN_CMD (0x80) */ | 186 | /* Service response to REPLY_SCAN_CMD (0x80) */ |
153 | static void iwl_rx_reply_scan(struct iwl_priv *priv, | 187 | static void iwl_rx_reply_scan(struct iwl_priv *priv, |
@@ -158,7 +192,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
158 | struct iwl_scanreq_notification *notif = | 192 | struct iwl_scanreq_notification *notif = |
159 | (struct iwl_scanreq_notification *)pkt->u.raw; | 193 | (struct iwl_scanreq_notification *)pkt->u.raw; |
160 | 194 | ||
161 | IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status); | 195 | IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); |
162 | #endif | 196 | #endif |
163 | } | 197 | } |
164 | 198 | ||
@@ -217,26 +251,16 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
217 | /* The HW is no longer scanning */ | 251 | /* The HW is no longer scanning */ |
218 | clear_bit(STATUS_SCAN_HW, &priv->status); | 252 | clear_bit(STATUS_SCAN_HW, &priv->status); |
219 | 253 | ||
220 | IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n", | 254 | IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", |
221 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", | 255 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", |
222 | jiffies_to_msecs(elapsed_jiffies | 256 | jiffies_to_msecs(elapsed_jiffies |
223 | (priv->scan_start, jiffies))); | 257 | (priv->scan_start, jiffies))); |
224 | 258 | ||
225 | /* | 259 | queue_work(priv->workqueue, &priv->scan_completed); |
226 | * If a request to abort was given, or the scan did not succeed | ||
227 | * then we reset the scan state machine and terminate, | ||
228 | * re-queuing another scan if one has been requested | ||
229 | */ | ||
230 | if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status)) | ||
231 | IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); | ||
232 | |||
233 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | ||
234 | |||
235 | clear_bit(STATUS_SCANNING, &priv->status); | ||
236 | 260 | ||
237 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && | 261 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && |
238 | priv->cfg->advanced_bt_coexist && priv->bt_status != | 262 | priv->cfg->advanced_bt_coexist && |
239 | scan_notif->bt_status) { | 263 | priv->bt_status != scan_notif->bt_status) { |
240 | if (scan_notif->bt_status) { | 264 | if (scan_notif->bt_status) { |
241 | /* BT on */ | 265 | /* BT on */ |
242 | if (!priv->bt_ch_announce) | 266 | if (!priv->bt_ch_announce) |
@@ -254,7 +278,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
254 | priv->bt_status = scan_notif->bt_status; | 278 | priv->bt_status = scan_notif->bt_status; |
255 | queue_work(priv->workqueue, &priv->bt_traffic_change_work); | 279 | queue_work(priv->workqueue, &priv->bt_traffic_change_work); |
256 | } | 280 | } |
257 | queue_work(priv->workqueue, &priv->scan_completed); | ||
258 | } | 281 | } |
259 | 282 | ||
260 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | 283 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) |
@@ -324,19 +347,53 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
324 | } | 347 | } |
325 | EXPORT_SYMBOL(iwl_init_scan_params); | 348 | EXPORT_SYMBOL(iwl_init_scan_params); |
326 | 349 | ||
327 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 350 | static int __must_check iwl_scan_initiate(struct iwl_priv *priv, |
351 | struct ieee80211_vif *vif, | ||
352 | bool internal, | ||
353 | enum ieee80211_band band) | ||
328 | { | 354 | { |
355 | int ret; | ||
356 | |||
329 | lockdep_assert_held(&priv->mutex); | 357 | lockdep_assert_held(&priv->mutex); |
330 | 358 | ||
331 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 359 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) |
360 | return -EOPNOTSUPP; | ||
361 | |||
362 | cancel_delayed_work(&priv->scan_check); | ||
363 | |||
364 | if (!iwl_is_ready_rf(priv)) { | ||
365 | IWL_WARN(priv, "Request scan called when driver not ready.\n"); | ||
366 | return -EIO; | ||
367 | } | ||
368 | |||
369 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
370 | IWL_DEBUG_SCAN(priv, | ||
371 | "Multiple concurrent scan requests in parallel.\n"); | ||
372 | return -EBUSY; | ||
373 | } | ||
374 | |||
375 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
376 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); | ||
377 | return -EBUSY; | ||
378 | } | ||
379 | |||
380 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", | ||
381 | internal ? "internal short " : ""); | ||
382 | |||
332 | set_bit(STATUS_SCANNING, &priv->status); | 383 | set_bit(STATUS_SCANNING, &priv->status); |
333 | priv->is_internal_short_scan = false; | 384 | priv->is_internal_short_scan = internal; |
334 | priv->scan_start = jiffies; | 385 | priv->scan_start = jiffies; |
386 | priv->scan_band = band; | ||
335 | 387 | ||
336 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | 388 | ret = priv->cfg->ops->utils->request_scan(priv, vif); |
337 | return -EOPNOTSUPP; | 389 | if (ret) { |
390 | clear_bit(STATUS_SCANNING, &priv->status); | ||
391 | priv->is_internal_short_scan = false; | ||
392 | return ret; | ||
393 | } | ||
338 | 394 | ||
339 | priv->cfg->ops->utils->request_scan(priv, vif); | 395 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
396 | IWL_SCAN_CHECK_WATCHDOG); | ||
340 | 397 | ||
341 | return 0; | 398 | return 0; |
342 | } | 399 | } |
@@ -355,12 +412,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
355 | 412 | ||
356 | mutex_lock(&priv->mutex); | 413 | mutex_lock(&priv->mutex); |
357 | 414 | ||
358 | if (!iwl_is_ready_rf(priv)) { | ||
359 | ret = -EIO; | ||
360 | IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); | ||
361 | goto out_unlock; | ||
362 | } | ||
363 | |||
364 | if (test_bit(STATUS_SCANNING, &priv->status) && | 415 | if (test_bit(STATUS_SCANNING, &priv->status) && |
365 | !priv->is_internal_short_scan) { | 416 | !priv->is_internal_short_scan) { |
366 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 417 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
@@ -368,14 +419,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
368 | goto out_unlock; | 419 | goto out_unlock; |
369 | } | 420 | } |
370 | 421 | ||
371 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
372 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
373 | ret = -EAGAIN; | ||
374 | goto out_unlock; | ||
375 | } | ||
376 | |||
377 | /* mac80211 will only ask for one band at a time */ | 422 | /* mac80211 will only ask for one band at a time */ |
378 | priv->scan_band = req->channels[0]->band; | ||
379 | priv->scan_request = req; | 423 | priv->scan_request = req; |
380 | priv->scan_vif = vif; | 424 | priv->scan_vif = vif; |
381 | 425 | ||
@@ -383,10 +427,12 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
383 | * If an internal scan is in progress, just set | 427 | * If an internal scan is in progress, just set |
384 | * up the scan_request as per above. | 428 | * up the scan_request as per above. |
385 | */ | 429 | */ |
386 | if (priv->is_internal_short_scan) | 430 | if (priv->is_internal_short_scan) { |
431 | IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); | ||
387 | ret = 0; | 432 | ret = 0; |
388 | else | 433 | } else |
389 | ret = iwl_scan_initiate(priv, vif); | 434 | ret = iwl_scan_initiate(priv, vif, false, |
435 | req->channels[0]->band); | ||
390 | 436 | ||
391 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 437 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
392 | 438 | ||
@@ -411,6 +457,8 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) | |||
411 | struct iwl_priv *priv = | 457 | struct iwl_priv *priv = |
412 | container_of(work, struct iwl_priv, start_internal_scan); | 458 | container_of(work, struct iwl_priv, start_internal_scan); |
413 | 459 | ||
460 | IWL_DEBUG_SCAN(priv, "Start internal scan\n"); | ||
461 | |||
414 | mutex_lock(&priv->mutex); | 462 | mutex_lock(&priv->mutex); |
415 | 463 | ||
416 | if (priv->is_internal_short_scan == true) { | 464 | if (priv->is_internal_short_scan == true) { |
@@ -418,31 +466,13 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) | |||
418 | goto unlock; | 466 | goto unlock; |
419 | } | 467 | } |
420 | 468 | ||
421 | if (!iwl_is_ready_rf(priv)) { | ||
422 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | ||
423 | goto unlock; | ||
424 | } | ||
425 | |||
426 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 469 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
427 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 470 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
428 | goto unlock; | 471 | goto unlock; |
429 | } | 472 | } |
430 | 473 | ||
431 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 474 | if (iwl_scan_initiate(priv, NULL, true, priv->band)) |
432 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | 475 | IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); |
433 | goto unlock; | ||
434 | } | ||
435 | |||
436 | priv->scan_band = priv->band; | ||
437 | |||
438 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | ||
439 | set_bit(STATUS_SCANNING, &priv->status); | ||
440 | priv->is_internal_short_scan = true; | ||
441 | |||
442 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | ||
443 | goto unlock; | ||
444 | |||
445 | priv->cfg->ops->utils->request_scan(priv, NULL); | ||
446 | unlock: | 476 | unlock: |
447 | mutex_unlock(&priv->mutex); | 477 | mutex_unlock(&priv->mutex); |
448 | } | 478 | } |
@@ -452,18 +482,13 @@ static void iwl_bg_scan_check(struct work_struct *data) | |||
452 | struct iwl_priv *priv = | 482 | struct iwl_priv *priv = |
453 | container_of(data, struct iwl_priv, scan_check.work); | 483 | container_of(data, struct iwl_priv, scan_check.work); |
454 | 484 | ||
455 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 485 | IWL_DEBUG_SCAN(priv, "Scan check work\n"); |
456 | return; | ||
457 | 486 | ||
487 | /* Since we are here firmware does not finish scan and | ||
488 | * most likely is in bad shape, so we don't bother to | ||
489 | * send abort command, just force scan complete to mac80211 */ | ||
458 | mutex_lock(&priv->mutex); | 490 | mutex_lock(&priv->mutex); |
459 | if (test_bit(STATUS_SCANNING, &priv->status) && | 491 | iwl_force_scan_end(priv); |
460 | !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
461 | IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", | ||
462 | jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); | ||
463 | |||
464 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
465 | iwl_send_scan_abort(priv); | ||
466 | } | ||
467 | mutex_unlock(&priv->mutex); | 492 | mutex_unlock(&priv->mutex); |
468 | } | 493 | } |
469 | 494 | ||
@@ -519,15 +544,12 @@ static void iwl_bg_abort_scan(struct work_struct *work) | |||
519 | { | 544 | { |
520 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); | 545 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); |
521 | 546 | ||
522 | if (!test_bit(STATUS_READY, &priv->status) || | 547 | IWL_DEBUG_SCAN(priv, "Abort scan work\n"); |
523 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | ||
524 | return; | ||
525 | |||
526 | cancel_delayed_work(&priv->scan_check); | ||
527 | 548 | ||
549 | /* We keep scan_check work queued in case when firmware will not | ||
550 | * report back scan completed notification */ | ||
528 | mutex_lock(&priv->mutex); | 551 | mutex_lock(&priv->mutex); |
529 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) | 552 | iwl_scan_cancel_timeout(priv, 200); |
530 | iwl_send_scan_abort(priv); | ||
531 | mutex_unlock(&priv->mutex); | 553 | mutex_unlock(&priv->mutex); |
532 | } | 554 | } |
533 | 555 | ||
@@ -535,30 +557,52 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
535 | { | 557 | { |
536 | struct iwl_priv *priv = | 558 | struct iwl_priv *priv = |
537 | container_of(work, struct iwl_priv, scan_completed); | 559 | container_of(work, struct iwl_priv, scan_completed); |
538 | bool internal = false; | 560 | bool aborted; |
539 | bool scan_completed = false; | ||
540 | struct iwl_rxon_context *ctx; | 561 | struct iwl_rxon_context *ctx; |
541 | 562 | ||
542 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 563 | IWL_DEBUG_SCAN(priv, "Completed %sscan.\n", |
564 | priv->is_internal_short_scan ? "internal short " : ""); | ||
543 | 565 | ||
544 | cancel_delayed_work(&priv->scan_check); | 566 | cancel_delayed_work(&priv->scan_check); |
545 | 567 | ||
546 | mutex_lock(&priv->mutex); | 568 | mutex_lock(&priv->mutex); |
547 | if (priv->is_internal_short_scan) { | 569 | |
548 | priv->is_internal_short_scan = false; | 570 | aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); |
549 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 571 | if (aborted) |
550 | internal = true; | 572 | IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); |
551 | } else if (priv->scan_request) { | 573 | |
552 | scan_completed = true; | 574 | if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { |
553 | priv->scan_request = NULL; | 575 | IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); |
554 | priv->scan_vif = NULL; | 576 | goto out_settings; |
555 | } | 577 | } |
556 | 578 | ||
557 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 579 | if (priv->is_internal_short_scan && !aborted) { |
580 | int err; | ||
581 | |||
582 | /* Check if mac80211 requested scan during our internal scan */ | ||
583 | if (priv->scan_request == NULL) | ||
584 | goto out_complete; | ||
585 | |||
586 | /* If so request a new scan */ | ||
587 | err = iwl_scan_initiate(priv, priv->scan_vif, false, | ||
588 | priv->scan_request->channels[0]->band); | ||
589 | if (err) { | ||
590 | IWL_DEBUG_SCAN(priv, | ||
591 | "failed to initiate pending scan: %d\n", err); | ||
592 | aborted = true; | ||
593 | goto out_complete; | ||
594 | } | ||
595 | |||
558 | goto out; | 596 | goto out; |
597 | } | ||
598 | |||
599 | out_complete: | ||
600 | iwl_complete_scan(priv, aborted); | ||
559 | 601 | ||
560 | if (internal && priv->scan_request) | 602 | out_settings: |
561 | iwl_scan_initiate(priv, priv->scan_vif); | 603 | /* Can we still talk to firmware ? */ |
604 | if (!iwl_is_ready_rf(priv)) | ||
605 | goto out; | ||
562 | 606 | ||
563 | /* Since setting the TXPOWER may have been deferred while | 607 | /* Since setting the TXPOWER may have been deferred while |
564 | * performing the scan, fire one off */ | 608 | * performing the scan, fire one off */ |
@@ -571,19 +615,11 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
571 | for_each_context(priv, ctx) | 615 | for_each_context(priv, ctx) |
572 | iwlcore_commit_rxon(priv, ctx); | 616 | iwlcore_commit_rxon(priv, ctx); |
573 | 617 | ||
574 | out: | ||
575 | if (priv->cfg->ops->hcmd->set_pan_params) | 618 | if (priv->cfg->ops->hcmd->set_pan_params) |
576 | priv->cfg->ops->hcmd->set_pan_params(priv); | 619 | priv->cfg->ops->hcmd->set_pan_params(priv); |
577 | 620 | ||
621 | out: | ||
578 | mutex_unlock(&priv->mutex); | 622 | mutex_unlock(&priv->mutex); |
579 | |||
580 | /* | ||
581 | * Do not hold mutex here since this will cause mac80211 to call | ||
582 | * into driver again into functions that will attempt to take | ||
583 | * mutex. | ||
584 | */ | ||
585 | if (scan_completed) | ||
586 | ieee80211_scan_completed(priv->hw, false); | ||
587 | } | 623 | } |
588 | 624 | ||
589 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 625 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
@@ -595,3 +631,16 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | |||
595 | } | 631 | } |
596 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | 632 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); |
597 | 633 | ||
634 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | ||
635 | { | ||
636 | cancel_work_sync(&priv->start_internal_scan); | ||
637 | cancel_work_sync(&priv->abort_scan); | ||
638 | cancel_work_sync(&priv->scan_completed); | ||
639 | |||
640 | if (cancel_delayed_work_sync(&priv->scan_check)) { | ||
641 | mutex_lock(&priv->mutex); | ||
642 | iwl_force_scan_end(priv); | ||
643 | mutex_unlock(&priv->mutex); | ||
644 | } | ||
645 | } | ||
646 | EXPORT_SYMBOL(iwl_cancel_scan_deferred_work); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index ccd09027c7cd..6edd0341dfe2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -386,7 +386,8 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, | |||
386 | { | 386 | { |
387 | int i, r; | 387 | int i, r; |
388 | struct iwl_link_quality_cmd *link_cmd; | 388 | struct iwl_link_quality_cmd *link_cmd; |
389 | u32 rate_flags; | 389 | u32 rate_flags = 0; |
390 | __le32 rate_n_flags; | ||
390 | 391 | ||
391 | link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); | 392 | link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); |
392 | if (!link_cmd) { | 393 | if (!link_cmd) { |
@@ -400,18 +401,14 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, | |||
400 | else | 401 | else |
401 | r = IWL_RATE_1M_INDEX; | 402 | r = IWL_RATE_1M_INDEX; |
402 | 403 | ||
403 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | 404 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) |
404 | rate_flags = 0; | 405 | rate_flags |= RATE_MCS_CCK_MSK; |
405 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
406 | rate_flags |= RATE_MCS_CCK_MSK; | ||
407 | 406 | ||
408 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 407 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << |
409 | RATE_MCS_ANT_POS; | 408 | RATE_MCS_ANT_POS; |
410 | 409 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | |
411 | link_cmd->rs_table[i].rate_n_flags = | 410 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) |
412 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 411 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; |
413 | r = iwl_get_prev_ieee_rate(r); | ||
414 | } | ||
415 | 412 | ||
416 | link_cmd->general_params.single_stream_ant_msk = | 413 | link_cmd->general_params.single_stream_ant_msk = |
417 | first_antenna(priv->hw_params.valid_tx_ant); | 414 | first_antenna(priv->hw_params.valid_tx_ant); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 347d3dc6a015..3290b1552f5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -666,8 +666,8 @@ const char *iwl_get_tx_fail_reason(u32 status) | |||
666 | TX_STATUS_FAIL(TID_DISABLE); | 666 | TX_STATUS_FAIL(TID_DISABLE); |
667 | TX_STATUS_FAIL(FIFO_FLUSHED); | 667 | TX_STATUS_FAIL(FIFO_FLUSHED); |
668 | TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); | 668 | TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); |
669 | TX_STATUS_FAIL(FW_DROP); | 669 | TX_STATUS_FAIL(PASSIVE_NO_RX); |
670 | TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP); | 670 | TX_STATUS_FAIL(NO_BEACON_ON_RADAR); |
671 | } | 671 | } |
672 | 672 | ||
673 | return "UNKNOWN"; | 673 | return "UNKNOWN"; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 68e624afb987..116777122a79 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1730,7 +1730,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1730 | IWL_ERR(priv, "Microcode SW error detected. " | 1730 | IWL_ERR(priv, "Microcode SW error detected. " |
1731 | "Restarting 0x%X.\n", inta); | 1731 | "Restarting 0x%X.\n", inta); |
1732 | priv->isr_stats.sw++; | 1732 | priv->isr_stats.sw++; |
1733 | priv->isr_stats.sw_err = inta; | ||
1734 | iwl_irq_handle_error(priv); | 1733 | iwl_irq_handle_error(priv); |
1735 | handled |= CSR_INT_BIT_SW_ERR; | 1734 | handled |= CSR_INT_BIT_SW_ERR; |
1736 | } | 1735 | } |
@@ -2568,15 +2567,13 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv); | |||
2568 | static void __iwl3945_down(struct iwl_priv *priv) | 2567 | static void __iwl3945_down(struct iwl_priv *priv) |
2569 | { | 2568 | { |
2570 | unsigned long flags; | 2569 | unsigned long flags; |
2571 | int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); | 2570 | int exit_pending; |
2572 | struct ieee80211_conf *conf = NULL; | ||
2573 | 2571 | ||
2574 | IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); | 2572 | IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); |
2575 | 2573 | ||
2576 | conf = ieee80211_get_hw_conf(priv->hw); | 2574 | iwl_scan_cancel_timeout(priv, 200); |
2577 | 2575 | ||
2578 | if (!exit_pending) | 2576 | exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); |
2579 | set_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2580 | 2577 | ||
2581 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set | 2578 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set |
2582 | * to prevent rearm timer */ | 2579 | * to prevent rearm timer */ |
@@ -2820,7 +2817,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data) | |||
2820 | 2817 | ||
2821 | } | 2818 | } |
2822 | 2819 | ||
2823 | void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | 2820 | int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2824 | { | 2821 | { |
2825 | struct iwl_host_cmd cmd = { | 2822 | struct iwl_host_cmd cmd = { |
2826 | .id = REPLY_SCAN_CMD, | 2823 | .id = REPLY_SCAN_CMD, |
@@ -2828,61 +2825,19 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2828 | .flags = CMD_SIZE_HUGE, | 2825 | .flags = CMD_SIZE_HUGE, |
2829 | }; | 2826 | }; |
2830 | struct iwl3945_scan_cmd *scan; | 2827 | struct iwl3945_scan_cmd *scan; |
2831 | struct ieee80211_conf *conf = NULL; | ||
2832 | u8 n_probes = 0; | 2828 | u8 n_probes = 0; |
2833 | enum ieee80211_band band; | 2829 | enum ieee80211_band band; |
2834 | bool is_active = false; | 2830 | bool is_active = false; |
2831 | int ret; | ||
2835 | 2832 | ||
2836 | conf = ieee80211_get_hw_conf(priv->hw); | 2833 | lockdep_assert_held(&priv->mutex); |
2837 | |||
2838 | cancel_delayed_work(&priv->scan_check); | ||
2839 | |||
2840 | if (!iwl_is_ready(priv)) { | ||
2841 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
2842 | goto done; | ||
2843 | } | ||
2844 | |||
2845 | /* Make sure the scan wasn't canceled before this queued work | ||
2846 | * was given the chance to run... */ | ||
2847 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
2848 | goto done; | ||
2849 | |||
2850 | /* This should never be called or scheduled if there is currently | ||
2851 | * a scan active in the hardware. */ | ||
2852 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
2853 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " | ||
2854 | "Ignoring second request.\n"); | ||
2855 | goto done; | ||
2856 | } | ||
2857 | |||
2858 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
2859 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
2860 | goto done; | ||
2861 | } | ||
2862 | |||
2863 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
2864 | IWL_DEBUG_HC(priv, | ||
2865 | "Scan request while abort pending. Queuing.\n"); | ||
2866 | goto done; | ||
2867 | } | ||
2868 | |||
2869 | if (iwl_is_rfkill(priv)) { | ||
2870 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
2871 | goto done; | ||
2872 | } | ||
2873 | |||
2874 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
2875 | IWL_DEBUG_HC(priv, | ||
2876 | "Scan request while uninitialized. Queuing.\n"); | ||
2877 | goto done; | ||
2878 | } | ||
2879 | 2834 | ||
2880 | if (!priv->scan_cmd) { | 2835 | if (!priv->scan_cmd) { |
2881 | priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + | 2836 | priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + |
2882 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | 2837 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); |
2883 | if (!priv->scan_cmd) { | 2838 | if (!priv->scan_cmd) { |
2884 | IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); | 2839 | IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); |
2885 | goto done; | 2840 | return -ENOMEM; |
2886 | } | 2841 | } |
2887 | } | 2842 | } |
2888 | scan = priv->scan_cmd; | 2843 | scan = priv->scan_cmd; |
@@ -2977,7 +2932,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2977 | break; | 2932 | break; |
2978 | default: | 2933 | default: |
2979 | IWL_WARN(priv, "Invalid scan band\n"); | 2934 | IWL_WARN(priv, "Invalid scan band\n"); |
2980 | goto done; | 2935 | return -EIO; |
2981 | } | 2936 | } |
2982 | 2937 | ||
2983 | if (!priv->is_internal_short_scan) { | 2938 | if (!priv->is_internal_short_scan) { |
@@ -3012,7 +2967,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3012 | 2967 | ||
3013 | if (scan->channel_count == 0) { | 2968 | if (scan->channel_count == 0) { |
3014 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 2969 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
3015 | goto done; | 2970 | return -EIO; |
3016 | } | 2971 | } |
3017 | 2972 | ||
3018 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | 2973 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + |
@@ -3021,25 +2976,10 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3021 | scan->len = cpu_to_le16(cmd.len); | 2976 | scan->len = cpu_to_le16(cmd.len); |
3022 | 2977 | ||
3023 | set_bit(STATUS_SCAN_HW, &priv->status); | 2978 | set_bit(STATUS_SCAN_HW, &priv->status); |
3024 | if (iwl_send_cmd_sync(priv, &cmd)) | 2979 | ret = iwl_send_cmd_sync(priv, &cmd); |
3025 | goto done; | 2980 | if (ret) |
3026 | 2981 | clear_bit(STATUS_SCAN_HW, &priv->status); | |
3027 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 2982 | return ret; |
3028 | IWL_SCAN_CHECK_WATCHDOG); | ||
3029 | |||
3030 | return; | ||
3031 | |||
3032 | done: | ||
3033 | /* can not perform scan make sure we clear scanning | ||
3034 | * bits from status so next scan request can be performed. | ||
3035 | * if we dont clear scanning status bit here all next scan | ||
3036 | * will fail | ||
3037 | */ | ||
3038 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
3039 | clear_bit(STATUS_SCANNING, &priv->status); | ||
3040 | |||
3041 | /* inform mac80211 scan aborted */ | ||
3042 | queue_work(priv->workqueue, &priv->scan_completed); | ||
3043 | } | 2983 | } |
3044 | 2984 | ||
3045 | static void iwl3945_bg_restart(struct work_struct *data) | 2985 | static void iwl3945_bg_restart(struct work_struct *data) |
@@ -3233,15 +3173,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) | |||
3233 | 3173 | ||
3234 | priv->is_open = 0; | 3174 | priv->is_open = 0; |
3235 | 3175 | ||
3236 | if (iwl_is_ready_rf(priv)) { | ||
3237 | /* stop mac, cancel any scan request and clear | ||
3238 | * RXON_FILTER_ASSOC_MSK BIT | ||
3239 | */ | ||
3240 | mutex_lock(&priv->mutex); | ||
3241 | iwl_scan_cancel_timeout(priv, 100); | ||
3242 | mutex_unlock(&priv->mutex); | ||
3243 | } | ||
3244 | |||
3245 | iwl3945_down(priv); | 3176 | iwl3945_down(priv); |
3246 | 3177 | ||
3247 | flush_workqueue(priv->workqueue); | 3178 | flush_workqueue(priv->workqueue); |
@@ -3831,10 +3762,10 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) | |||
3831 | iwl3945_hw_cancel_deferred_work(priv); | 3762 | iwl3945_hw_cancel_deferred_work(priv); |
3832 | 3763 | ||
3833 | cancel_delayed_work_sync(&priv->init_alive_start); | 3764 | cancel_delayed_work_sync(&priv->init_alive_start); |
3834 | cancel_delayed_work(&priv->scan_check); | ||
3835 | cancel_delayed_work(&priv->alive_start); | 3765 | cancel_delayed_work(&priv->alive_start); |
3836 | cancel_work_sync(&priv->start_internal_scan); | ||
3837 | cancel_work_sync(&priv->beacon_update); | 3766 | cancel_work_sync(&priv->beacon_update); |
3767 | |||
3768 | iwl_cancel_scan_deferred_work(priv); | ||
3838 | } | 3769 | } |
3839 | 3770 | ||
3840 | static struct attribute *iwl3945_sysfs_entries[] = { | 3771 | static struct attribute *iwl3945_sysfs_entries[] = { |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 317f086ced0a..1bbdb14f7d76 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -481,7 +481,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
481 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; | 481 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; |
482 | int bsssize; | 482 | int bsssize; |
483 | const u8 *pos; | 483 | const u8 *pos; |
484 | u16 nr_sets; | ||
485 | const u8 *tsfdesc; | 484 | const u8 *tsfdesc; |
486 | int tsfsize; | 485 | int tsfsize; |
487 | int i; | 486 | int i; |
@@ -490,12 +489,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
490 | lbs_deb_enter(LBS_DEB_CFG80211); | 489 | lbs_deb_enter(LBS_DEB_CFG80211); |
491 | 490 | ||
492 | bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); | 491 | bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); |
493 | nr_sets = le16_to_cpu(scanresp->nr_sets); | ||
494 | 492 | ||
495 | lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n", | 493 | lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n", |
496 | nr_sets, bsssize, le16_to_cpu(resp->size)); | 494 | scanresp->nr_sets, bsssize, le16_to_cpu(resp->size)); |
497 | 495 | ||
498 | if (nr_sets == 0) { | 496 | if (scanresp->nr_sets == 0) { |
499 | ret = 0; | 497 | ret = 0; |
500 | goto done; | 498 | goto done; |
501 | } | 499 | } |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 194762ab0142..acf3bf63ee33 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -574,7 +574,7 @@ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) | |||
574 | memset(&cmd, 0, sizeof(cmd)); | 574 | memset(&cmd, 0, sizeof(cmd)); |
575 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 575 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
576 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); | 576 | cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT); |
577 | cmd.id = !!inverted; | 577 | cmd.id = cpu_to_le32(!!inverted); |
578 | 578 | ||
579 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); | 579 | ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd); |
580 | 580 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 92b486d46eb9..7eaaa3bab547 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -595,7 +595,8 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | |||
595 | struct ieee80211_vif *vif) | 595 | struct ieee80211_vif *vif) |
596 | { | 596 | { |
597 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 597 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
598 | __func__, vif->type, vif->addr); | 598 | __func__, ieee80211_vif_type_p2p(vif), |
599 | vif->addr); | ||
599 | hwsim_set_magic(vif); | 600 | hwsim_set_magic(vif); |
600 | return 0; | 601 | return 0; |
601 | } | 602 | } |
@@ -603,11 +604,14 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | |||
603 | 604 | ||
604 | static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, | 605 | static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, |
605 | struct ieee80211_vif *vif, | 606 | struct ieee80211_vif *vif, |
606 | enum nl80211_iftype newtype) | 607 | enum nl80211_iftype newtype, |
608 | bool newp2p) | ||
607 | { | 609 | { |
610 | newtype = ieee80211_iftype_p2p(newtype, newp2p); | ||
608 | wiphy_debug(hw->wiphy, | 611 | wiphy_debug(hw->wiphy, |
609 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", | 612 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", |
610 | __func__, vif->type, newtype, vif->addr); | 613 | __func__, ieee80211_vif_type_p2p(vif), |
614 | newtype, vif->addr); | ||
611 | hwsim_check_magic(vif); | 615 | hwsim_check_magic(vif); |
612 | 616 | ||
613 | return 0; | 617 | return 0; |
@@ -617,7 +621,8 @@ static void mac80211_hwsim_remove_interface( | |||
617 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 621 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
618 | { | 622 | { |
619 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 623 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
620 | __func__, vif->type, vif->addr); | 624 | __func__, ieee80211_vif_type_p2p(vif), |
625 | vif->addr); | ||
621 | hwsim_check_magic(vif); | 626 | hwsim_check_magic(vif); |
622 | hwsim_clear_magic(vif); | 627 | hwsim_clear_magic(vif); |
623 | } | 628 | } |
@@ -1310,6 +1315,8 @@ static int __init init_mac80211_hwsim(void) | |||
1310 | hw->wiphy->interface_modes = | 1315 | hw->wiphy->interface_modes = |
1311 | BIT(NL80211_IFTYPE_STATION) | | 1316 | BIT(NL80211_IFTYPE_STATION) | |
1312 | BIT(NL80211_IFTYPE_AP) | | 1317 | BIT(NL80211_IFTYPE_AP) | |
1318 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
1319 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
1313 | BIT(NL80211_IFTYPE_ADHOC) | | 1320 | BIT(NL80211_IFTYPE_ADHOC) | |
1314 | BIT(NL80211_IFTYPE_MESH_POINT); | 1321 | BIT(NL80211_IFTYPE_MESH_POINT); |
1315 | 1322 | ||
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 156e57dbd2cf..18d24b7b1e34 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -202,6 +202,8 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev) | |||
202 | dev_info(&priv->spi->dev, "loading default eeprom...\n"); | 202 | dev_info(&priv->spi->dev, "loading default eeprom...\n"); |
203 | ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom, | 203 | ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom, |
204 | sizeof(p54spi_eeprom)); | 204 | sizeof(p54spi_eeprom)); |
205 | #else | ||
206 | dev_err(&priv->spi->dev, "Failed to request user eeprom\n"); | ||
205 | #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ | 207 | #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ |
206 | } else { | 208 | } else { |
207 | dev_info(&priv->spi->dev, "loading user eeprom...\n"); | 209 | dev_info(&priv->spi->dev, "loading user eeprom...\n"); |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index d91a831a7700..5ca624a64c42 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -194,7 +194,7 @@ module_param(bc, int, 0); | |||
194 | module_param(phy_addr, charp, 0); | 194 | module_param(phy_addr, charp, 0); |
195 | module_param(ray_mem_speed, int, 0); | 195 | module_param(ray_mem_speed, int, 0); |
196 | 196 | ||
197 | static UCHAR b5_default_startup_parms[] = { | 197 | static const UCHAR b5_default_startup_parms[] = { |
198 | 0, 0, /* Adhoc station */ | 198 | 0, 0, /* Adhoc station */ |
199 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ | 199 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ |
200 | 0, 0, 0, 0, 0, 0, 0, 0, | 200 | 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -229,7 +229,7 @@ static UCHAR b5_default_startup_parms[] = { | |||
229 | 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ | 229 | 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ |
230 | }; | 230 | }; |
231 | 231 | ||
232 | static UCHAR b4_default_startup_parms[] = { | 232 | static const UCHAR b4_default_startup_parms[] = { |
233 | 0, 0, /* Adhoc station */ | 233 | 0, 0, /* Adhoc station */ |
234 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ | 234 | 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ |
235 | 0, 0, 0, 0, 0, 0, 0, 0, | 235 | 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -261,9 +261,9 @@ static UCHAR b4_default_startup_parms[] = { | |||
261 | }; | 261 | }; |
262 | 262 | ||
263 | /*===========================================================================*/ | 263 | /*===========================================================================*/ |
264 | static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 }; | 264 | static const u8 eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 }; |
265 | 265 | ||
266 | static char hop_pattern_length[] = { 1, | 266 | static const char hop_pattern_length[] = { 1, |
267 | USA_HOP_MOD, EUROPE_HOP_MOD, | 267 | USA_HOP_MOD, EUROPE_HOP_MOD, |
268 | JAPAN_HOP_MOD, KOREA_HOP_MOD, | 268 | JAPAN_HOP_MOD, KOREA_HOP_MOD, |
269 | SPAIN_HOP_MOD, FRANCE_HOP_MOD, | 269 | SPAIN_HOP_MOD, FRANCE_HOP_MOD, |
@@ -271,7 +271,7 @@ static char hop_pattern_length[] = { 1, | |||
271 | JAPAN_TEST_HOP_MOD | 271 | JAPAN_TEST_HOP_MOD |
272 | }; | 272 | }; |
273 | 273 | ||
274 | static char rcsid[] = | 274 | static const char rcsid[] = |
275 | "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>"; | 275 | "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>"; |
276 | 276 | ||
277 | static const struct net_device_ops ray_netdev_ops = { | 277 | static const struct net_device_ops ray_netdev_ops = { |
@@ -2575,7 +2575,7 @@ static void clear_interrupt(ray_dev_t *local) | |||
2575 | #ifdef CONFIG_PROC_FS | 2575 | #ifdef CONFIG_PROC_FS |
2576 | #define MAXDATA (PAGE_SIZE - 80) | 2576 | #define MAXDATA (PAGE_SIZE - 80) |
2577 | 2577 | ||
2578 | static char *card_status[] = { | 2578 | static const char *card_status[] = { |
2579 | "Card inserted - uninitialized", /* 0 */ | 2579 | "Card inserted - uninitialized", /* 0 */ |
2580 | "Card not downloaded", /* 1 */ | 2580 | "Card not downloaded", /* 1 */ |
2581 | "Waiting for download parameters", /* 2 */ | 2581 | "Waiting for download parameters", /* 2 */ |
@@ -2592,8 +2592,8 @@ static char *card_status[] = { | |||
2592 | "Association failed" /* 16 */ | 2592 | "Association failed" /* 16 */ |
2593 | }; | 2593 | }; |
2594 | 2594 | ||
2595 | static char *nettype[] = { "Adhoc", "Infra " }; | 2595 | static const char *nettype[] = { "Adhoc", "Infra " }; |
2596 | static char *framing[] = { "Encapsulation", "Translation" } | 2596 | static const char *framing[] = { "Encapsulation", "Translation" } |
2597 | 2597 | ||
2598 | ; | 2598 | ; |
2599 | /*===========================================================================*/ | 2599 | /*===========================================================================*/ |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 103c71164f10..d49e830fa1da 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -321,7 +321,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
321 | } | 321 | } |
322 | 322 | ||
323 | static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, | 323 | static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, |
324 | struct rt2x00lib_erp *erp) | 324 | struct rt2x00lib_erp *erp, |
325 | u32 changed) | ||
325 | { | 326 | { |
326 | int preamble_mask; | 327 | int preamble_mask; |
327 | u32 reg; | 328 | u32 reg; |
@@ -329,59 +330,72 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
329 | /* | 330 | /* |
330 | * When short preamble is enabled, we should set bit 0x08 | 331 | * When short preamble is enabled, we should set bit 0x08 |
331 | */ | 332 | */ |
332 | preamble_mask = erp->short_preamble << 3; | 333 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
333 | 334 | preamble_mask = erp->short_preamble << 3; | |
334 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); | 335 | |
335 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); | 336 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); |
336 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); | 337 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); |
337 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); | 338 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); |
338 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); | 339 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); |
339 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | 340 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); |
340 | 341 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | |
341 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 342 | |
342 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 343 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); |
343 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 344 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
344 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); | 345 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
345 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 346 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
346 | 347 | GET_DURATION(ACK_SIZE, 10)); | |
347 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 348 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); |
348 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 349 | |
349 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 350 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); |
350 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); | 351 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
351 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 352 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
352 | 353 | rt2x00_set_field32(®, ARCSR2_LENGTH, | |
353 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 354 | GET_DURATION(ACK_SIZE, 20)); |
354 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 355 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); |
355 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 356 | |
356 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); | 357 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); |
357 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 358 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
358 | 359 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | |
359 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 360 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
360 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 361 | GET_DURATION(ACK_SIZE, 55)); |
361 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 362 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); |
362 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); | 363 | |
363 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 364 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); |
364 | 365 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | |
365 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 366 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
367 | rt2x00_set_field32(®, ARCSR2_LENGTH, | ||
368 | GET_DURATION(ACK_SIZE, 110)); | ||
369 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | ||
370 | } | ||
366 | 371 | ||
367 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 372 | if (changed & BSS_CHANGED_BASIC_RATES) |
368 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); | 373 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
369 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | ||
370 | 374 | ||
371 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | 375 | if (changed & BSS_CHANGED_ERP_SLOT) { |
372 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); | 376 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); |
373 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); | 377 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); |
374 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | 378 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); |
375 | 379 | ||
376 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); | 380 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); |
377 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); | 381 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); |
378 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); | 382 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); |
379 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); | 383 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); |
380 | 384 | ||
381 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); | 385 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); |
382 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); | 386 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); |
383 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); | 387 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); |
384 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); | 388 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); |
389 | } | ||
390 | |||
391 | if (changed & BSS_CHANGED_BEACON_INT) { | ||
392 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | ||
393 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, | ||
394 | erp->beacon_int * 16); | ||
395 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, | ||
396 | erp->beacon_int * 16); | ||
397 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | ||
398 | } | ||
385 | } | 399 | } |
386 | 400 | ||
387 | static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev, | 401 | static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ab0507110e42..2214c3231727 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -327,7 +327,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
327 | } | 327 | } |
328 | 328 | ||
329 | static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, | 329 | static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, |
330 | struct rt2x00lib_erp *erp) | 330 | struct rt2x00lib_erp *erp, |
331 | u32 changed) | ||
331 | { | 332 | { |
332 | int preamble_mask; | 333 | int preamble_mask; |
333 | u32 reg; | 334 | u32 reg; |
@@ -335,59 +336,73 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
335 | /* | 336 | /* |
336 | * When short preamble is enabled, we should set bit 0x08 | 337 | * When short preamble is enabled, we should set bit 0x08 |
337 | */ | 338 | */ |
338 | preamble_mask = erp->short_preamble << 3; | 339 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
339 | 340 | preamble_mask = erp->short_preamble << 3; | |
340 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); | 341 | |
341 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); | 342 | rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); |
342 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); | 343 | rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); |
343 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); | 344 | rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); |
344 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); | 345 | rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); |
345 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | 346 | rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); |
346 | 347 | rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); | |
347 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); | 348 | |
348 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); | 349 | rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); |
349 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); | 350 | rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); |
350 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); | 351 | rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); |
351 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); | 352 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
352 | 353 | GET_DURATION(ACK_SIZE, 10)); | |
353 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); | 354 | rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); |
354 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); | 355 | |
355 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); | 356 | rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); |
356 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); | 357 | rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); |
357 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); | 358 | rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); |
358 | 359 | rt2x00_set_field32(®, ARCSR2_LENGTH, | |
359 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); | 360 | GET_DURATION(ACK_SIZE, 20)); |
360 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); | 361 | rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); |
361 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | 362 | |
362 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); | 363 | rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); |
363 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); | 364 | rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); |
364 | 365 | rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); | |
365 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); | 366 | rt2x00_set_field32(®, ARCSR2_LENGTH, |
366 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | 367 | GET_DURATION(ACK_SIZE, 55)); |
367 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); | 368 | rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); |
368 | rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); | 369 | |
369 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | 370 | rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); |
370 | 371 | rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); | |
371 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); | 372 | rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); |
373 | rt2x00_set_field32(®, ARCSR2_LENGTH, | ||
374 | GET_DURATION(ACK_SIZE, 110)); | ||
375 | rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); | ||
376 | } | ||
372 | 377 | ||
373 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | 378 | if (changed & BSS_CHANGED_BASIC_RATES) |
374 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); | 379 | rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); |
375 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | 380 | |
381 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
382 | rt2x00pci_register_read(rt2x00dev, CSR11, ®); | ||
383 | rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); | ||
384 | rt2x00pci_register_write(rt2x00dev, CSR11, reg); | ||
376 | 385 | ||
377 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | 386 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); |
378 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); | 387 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); |
379 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); | 388 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); |
380 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | 389 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); |
381 | 390 | ||
382 | rt2x00pci_register_read(rt2x00dev, CSR18, ®); | 391 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); |
383 | rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); | 392 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); |
384 | rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); | 393 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); |
385 | rt2x00pci_register_write(rt2x00dev, CSR18, reg); | 394 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); |
395 | } | ||
396 | |||
397 | if (changed & BSS_CHANGED_BEACON_INT) { | ||
398 | rt2x00pci_register_read(rt2x00dev, CSR12, ®); | ||
399 | rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, | ||
400 | erp->beacon_int * 16); | ||
401 | rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, | ||
402 | erp->beacon_int * 16); | ||
403 | rt2x00pci_register_write(rt2x00dev, CSR12, reg); | ||
404 | } | ||
386 | 405 | ||
387 | rt2x00pci_register_read(rt2x00dev, CSR19, ®); | ||
388 | rt2x00_set_field32(®, CSR19_DIFS, erp->difs); | ||
389 | rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); | ||
390 | rt2x00pci_register_write(rt2x00dev, CSR19, reg); | ||
391 | } | 406 | } |
392 | 407 | ||
393 | static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | 408 | static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index db64df4267d8..6e94356265b3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -494,24 +494,34 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
494 | } | 494 | } |
495 | 495 | ||
496 | static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, | 496 | static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, |
497 | struct rt2x00lib_erp *erp) | 497 | struct rt2x00lib_erp *erp, |
498 | u32 changed) | ||
498 | { | 499 | { |
499 | u16 reg; | 500 | u16 reg; |
500 | 501 | ||
501 | rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); | 502 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
502 | rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, | 503 | rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); |
503 | !!erp->short_preamble); | 504 | rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, |
504 | rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); | 505 | !!erp->short_preamble); |
506 | rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); | ||
507 | } | ||
505 | 508 | ||
506 | rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); | 509 | if (changed & BSS_CHANGED_BASIC_RATES) |
510 | rt2500usb_register_write(rt2x00dev, TXRX_CSR11, | ||
511 | erp->basic_rates); | ||
507 | 512 | ||
508 | rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); | 513 | if (changed & BSS_CHANGED_BEACON_INT) { |
509 | rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); | 514 | rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); |
510 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); | 515 | rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, |
516 | erp->beacon_int * 4); | ||
517 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); | ||
518 | } | ||
511 | 519 | ||
512 | rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); | 520 | if (changed & BSS_CHANGED_ERP_SLOT) { |
513 | rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); | 521 | rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); |
514 | rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); | 522 | rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); |
523 | rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); | ||
524 | } | ||
515 | } | 525 | } |
516 | 526 | ||
517 | static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | 527 | static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 70a5cb86405b..2edc7742a7e9 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -639,6 +639,18 @@ | |||
639 | #define LED_CFG_LED_POLAR FIELD32(0x40000000) | 639 | #define LED_CFG_LED_POLAR FIELD32(0x40000000) |
640 | 640 | ||
641 | /* | 641 | /* |
642 | * AMPDU_BA_WINSIZE: Force BlockAck window size | ||
643 | * FORCE_WINSIZE_ENABLE: | ||
644 | * 0: Disable forcing of BlockAck window size | ||
645 | * 1: Enable forcing of BlockAck window size, overwrites values BlockAck | ||
646 | * window size values in the TXWI | ||
647 | * FORCE_WINSIZE: BlockAck window size | ||
648 | */ | ||
649 | #define AMPDU_BA_WINSIZE 0x1040 | ||
650 | #define AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE FIELD32(0x00000020) | ||
651 | #define AMPDU_BA_WINSIZE_FORCE_WINSIZE FIELD32(0x0000001f) | ||
652 | |||
653 | /* | ||
642 | * XIFS_TIME_CFG: MAC timing | 654 | * XIFS_TIME_CFG: MAC timing |
643 | * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX | 655 | * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX |
644 | * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX | 656 | * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 27a6e225083c..3bb67492d754 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1159,38 +1159,50 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
1159 | } | 1159 | } |
1160 | EXPORT_SYMBOL_GPL(rt2800_config_intf); | 1160 | EXPORT_SYMBOL_GPL(rt2800_config_intf); |
1161 | 1161 | ||
1162 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) | 1162 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, |
1163 | u32 changed) | ||
1163 | { | 1164 | { |
1164 | u32 reg; | 1165 | u32 reg; |
1165 | 1166 | ||
1166 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | 1167 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
1167 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | 1168 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); |
1168 | !!erp->short_preamble); | 1169 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, |
1169 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, | 1170 | !!erp->short_preamble); |
1170 | !!erp->short_preamble); | 1171 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, |
1171 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | 1172 | !!erp->short_preamble); |
1173 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | ||
1174 | } | ||
1172 | 1175 | ||
1173 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | 1176 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
1174 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, | 1177 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); |
1175 | erp->cts_protection ? 2 : 0); | 1178 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, |
1176 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | 1179 | erp->cts_protection ? 2 : 0); |
1180 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
1181 | } | ||
1177 | 1182 | ||
1178 | rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, | 1183 | if (changed & BSS_CHANGED_BASIC_RATES) { |
1179 | erp->basic_rates); | 1184 | rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, |
1180 | rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | 1185 | erp->basic_rates); |
1186 | rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | ||
1187 | } | ||
1181 | 1188 | ||
1182 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | 1189 | if (changed & BSS_CHANGED_ERP_SLOT) { |
1183 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | 1190 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); |
1184 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | 1191 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, |
1192 | erp->slot_time); | ||
1193 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | ||
1185 | 1194 | ||
1186 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | 1195 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); |
1187 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | 1196 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); |
1188 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | 1197 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); |
1198 | } | ||
1189 | 1199 | ||
1190 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 1200 | if (changed & BSS_CHANGED_BEACON_INT) { |
1191 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | 1201 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
1192 | erp->beacon_int * 16); | 1202 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, |
1193 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1203 | erp->beacon_int * 16); |
1204 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
1205 | } | ||
1194 | } | 1206 | } |
1195 | EXPORT_SYMBOL_GPL(rt2800_config_erp); | 1207 | EXPORT_SYMBOL_GPL(rt2800_config_erp); |
1196 | 1208 | ||
@@ -2053,6 +2065,14 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
2053 | rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg); | 2065 | rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg); |
2054 | 2066 | ||
2055 | /* | 2067 | /* |
2068 | * Do not force the BA window size, we use the TXWI to set it | ||
2069 | */ | ||
2070 | rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, ®); | ||
2071 | rt2x00_set_field32(®, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0); | ||
2072 | rt2x00_set_field32(®, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0); | ||
2073 | rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg); | ||
2074 | |||
2075 | /* | ||
2056 | * We must clear the error counters. | 2076 | * We must clear the error counters. |
2057 | * These registers are cleared on read, | 2077 | * These registers are cleared on read, |
2058 | * so we may pass a useless variable to store the value. | 2078 | * so we may pass a useless variable to store the value. |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 986229c06c19..600c5eb25c41 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -169,7 +169,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, | |||
169 | const unsigned int filter_flags); | 169 | const unsigned int filter_flags); |
170 | void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | 170 | void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, |
171 | struct rt2x00intf_conf *conf, const unsigned int flags); | 171 | struct rt2x00intf_conf *conf, const unsigned int flags); |
172 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp); | 172 | void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp, |
173 | u32 changed); | ||
173 | void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); | 174 | void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant); |
174 | void rt2800_config(struct rt2x00_dev *rt2x00dev, | 175 | void rt2800_config(struct rt2x00_dev *rt2x00dev, |
175 | struct rt2x00lib_conf *libconf, | 176 | struct rt2x00lib_conf *libconf, |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2bcb1507e3ac..005ee153e0cc 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -342,24 +342,24 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
342 | } | 342 | } |
343 | 343 | ||
344 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | 344 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); |
345 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, mask); | 345 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); |
346 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, mask); | 346 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); |
347 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); | 347 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); |
348 | rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, mask); | 348 | rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, 0); |
349 | rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, mask); | 349 | rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, 0); |
350 | rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, mask); | 350 | rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, 0); |
351 | rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, mask); | 351 | rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, 0); |
352 | rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, mask); | 352 | rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, 0); |
353 | rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, mask); | 353 | rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, 0); |
354 | rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, mask); | 354 | rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, 0); |
355 | rt2x00_set_field32(®, INT_MASK_CSR_RXTX_COHERENT, mask); | 355 | rt2x00_set_field32(®, INT_MASK_CSR_RXTX_COHERENT, 0); |
356 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, mask); | 356 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, mask); |
357 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, mask); | 357 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, mask); |
358 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, mask); | 358 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, mask); |
359 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, mask); | 359 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, mask); |
360 | rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, mask); | 360 | rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); |
361 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, mask); | 361 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); |
362 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, mask); | 362 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); |
363 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | 363 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); |
364 | } | 364 | } |
365 | 365 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0ae942cb66df..7832a5996a8c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -596,7 +596,8 @@ struct rt2x00lib_ops { | |||
596 | #define CONFIG_UPDATE_BSSID ( 1 << 3 ) | 596 | #define CONFIG_UPDATE_BSSID ( 1 << 3 ) |
597 | 597 | ||
598 | void (*config_erp) (struct rt2x00_dev *rt2x00dev, | 598 | void (*config_erp) (struct rt2x00_dev *rt2x00dev, |
599 | struct rt2x00lib_erp *erp); | 599 | struct rt2x00lib_erp *erp, |
600 | u32 changed); | ||
600 | void (*config_ant) (struct rt2x00_dev *rt2x00dev, | 601 | void (*config_ant) (struct rt2x00_dev *rt2x00dev, |
601 | struct antenna_setup *ant); | 602 | struct antenna_setup *ant); |
602 | void (*config) (struct rt2x00_dev *rt2x00dev, | 603 | void (*config) (struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 34f34fa7f53a..4c7ff765a8bf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -81,7 +81,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, | |||
81 | 81 | ||
82 | void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | 82 | void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, |
83 | struct rt2x00_intf *intf, | 83 | struct rt2x00_intf *intf, |
84 | struct ieee80211_bss_conf *bss_conf) | 84 | struct ieee80211_bss_conf *bss_conf, |
85 | u32 changed) | ||
85 | { | 86 | { |
86 | struct rt2x00lib_erp erp; | 87 | struct rt2x00lib_erp erp; |
87 | 88 | ||
@@ -102,7 +103,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
102 | /* Update global beacon interval time, this is needed for PS support */ | 103 | /* Update global beacon interval time, this is needed for PS support */ |
103 | rt2x00dev->beacon_int = bss_conf->beacon_int; | 104 | rt2x00dev->beacon_int = bss_conf->beacon_int; |
104 | 105 | ||
105 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); | 106 | rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); |
106 | } | 107 | } |
107 | 108 | ||
108 | static inline | 109 | static inline |
@@ -129,12 +130,12 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
129 | */ | 130 | */ |
130 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) | 131 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) |
131 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); | 132 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); |
132 | else | 133 | else if(config.rx == ANTENNA_SW_DIVERSITY) |
133 | config.rx = active->rx; | 134 | config.rx = active->rx; |
134 | 135 | ||
135 | if (!(ant->flags & ANTENNA_TX_DIVERSITY)) | 136 | if (!(ant->flags & ANTENNA_TX_DIVERSITY)) |
136 | config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); | 137 | config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); |
137 | else | 138 | else if (config.tx == ANTENNA_SW_DIVERSITY) |
138 | config.tx = active->tx; | 139 | config.tx = active->tx; |
139 | 140 | ||
140 | /* | 141 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index dc5c6574aaf4..70c85ac2e53e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -86,7 +86,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, | |||
86 | const u8 *mac, const u8 *bssid); | 86 | const u8 *mac, const u8 *bssid); |
87 | void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | 87 | void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, |
88 | struct rt2x00_intf *intf, | 88 | struct rt2x00_intf *intf, |
89 | struct ieee80211_bss_conf *conf); | 89 | struct ieee80211_bss_conf *conf, |
90 | u32 changed); | ||
90 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | 91 | void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, |
91 | struct antenna_setup ant); | 92 | struct antenna_setup ant); |
92 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | 93 | void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 666cef3f8472..4d534e9dc628 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -188,7 +188,6 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev) | |||
188 | static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) | 188 | static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) |
189 | { | 189 | { |
190 | struct link_ant *ant = &rt2x00dev->link.ant; | 190 | struct link_ant *ant = &rt2x00dev->link.ant; |
191 | unsigned int flags = ant->flags; | ||
192 | 191 | ||
193 | /* | 192 | /* |
194 | * Determine if software diversity is enabled for | 193 | * Determine if software diversity is enabled for |
@@ -196,13 +195,13 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) | |||
196 | * Always perform this check since within the link | 195 | * Always perform this check since within the link |
197 | * tuner interval the configuration might have changed. | 196 | * tuner interval the configuration might have changed. |
198 | */ | 197 | */ |
199 | flags &= ~ANTENNA_RX_DIVERSITY; | 198 | ant->flags &= ~ANTENNA_RX_DIVERSITY; |
200 | flags &= ~ANTENNA_TX_DIVERSITY; | 199 | ant->flags &= ~ANTENNA_TX_DIVERSITY; |
201 | 200 | ||
202 | if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) | 201 | if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) |
203 | flags |= ANTENNA_RX_DIVERSITY; | 202 | ant->flags |= ANTENNA_RX_DIVERSITY; |
204 | if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) | 203 | if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) |
205 | flags |= ANTENNA_TX_DIVERSITY; | 204 | ant->flags |= ANTENNA_TX_DIVERSITY; |
206 | 205 | ||
207 | if (!(ant->flags & ANTENNA_RX_DIVERSITY) && | 206 | if (!(ant->flags & ANTENNA_RX_DIVERSITY) && |
208 | !(ant->flags & ANTENNA_TX_DIVERSITY)) { | 207 | !(ant->flags & ANTENNA_TX_DIVERSITY)) { |
@@ -210,9 +209,6 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) | |||
210 | return true; | 209 | return true; |
211 | } | 210 | } |
212 | 211 | ||
213 | /* Update flags */ | ||
214 | ant->flags = flags; | ||
215 | |||
216 | /* | 212 | /* |
217 | * If we have only sampled the data over the last period | 213 | * If we have only sampled the data over the last period |
218 | * we should now harvest the data. Otherwise just evaluate | 214 | * we should now harvest the data. Otherwise just evaluate |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 235e037e6509..7862a840984a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -669,8 +669,10 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
669 | * When the erp information has changed, we should perform | 669 | * When the erp information has changed, we should perform |
670 | * additional configuration steps. For all other changes we are done. | 670 | * additional configuration steps. For all other changes we are done. |
671 | */ | 671 | */ |
672 | if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) | 672 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | |
673 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); | 673 | BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES | |
674 | BSS_CHANGED_BEACON_INT)) | ||
675 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes); | ||
674 | } | 676 | } |
675 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); | 677 | EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); |
676 | 678 | ||
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3a7759929190..97b3935f615b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -594,7 +594,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
594 | } | 594 | } |
595 | 595 | ||
596 | static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, | 596 | static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, |
597 | struct rt2x00lib_erp *erp) | 597 | struct rt2x00lib_erp *erp, |
598 | u32 changed) | ||
598 | { | 599 | { |
599 | u32 reg; | 600 | u32 reg; |
600 | 601 | ||
@@ -603,28 +604,36 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, | |||
603 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); | 604 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); |
604 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 605 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); |
605 | 606 | ||
606 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); | 607 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
607 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); | 608 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); |
608 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, | 609 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); |
609 | !!erp->short_preamble); | 610 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, |
610 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); | 611 | !!erp->short_preamble); |
612 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); | ||
613 | } | ||
611 | 614 | ||
612 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); | 615 | if (changed & BSS_CHANGED_BASIC_RATES) |
616 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, | ||
617 | erp->basic_rates); | ||
613 | 618 | ||
614 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 619 | if (changed & BSS_CHANGED_BEACON_INT) { |
615 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, | 620 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
616 | erp->beacon_int * 16); | 621 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, |
617 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 622 | erp->beacon_int * 16); |
623 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
624 | } | ||
618 | 625 | ||
619 | rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); | 626 | if (changed & BSS_CHANGED_ERP_SLOT) { |
620 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); | 627 | rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); |
621 | rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); | 628 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); |
629 | rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); | ||
622 | 630 | ||
623 | rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); | 631 | rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); |
624 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); | 632 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); |
625 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); | 633 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); |
626 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); | 634 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); |
627 | rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); | 635 | rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); |
636 | } | ||
628 | } | 637 | } |
629 | 638 | ||
630 | static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | 639 | static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, |
@@ -1645,6 +1654,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1645 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 1654 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); |
1646 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); | 1655 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); |
1647 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); | 1656 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); |
1657 | rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, mask); | ||
1648 | rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); | 1658 | rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); |
1649 | rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); | 1659 | rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); |
1650 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | 1660 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); |
@@ -1658,6 +1668,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1658 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, mask); | 1668 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, mask); |
1659 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); | 1669 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); |
1660 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); | 1670 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); |
1671 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); | ||
1661 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 1672 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
1662 | } | 1673 | } |
1663 | 1674 | ||
@@ -2106,7 +2117,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2106 | "TX status report missed for entry %d\n", | 2117 | "TX status report missed for entry %d\n", |
2107 | entry_done->entry_idx); | 2118 | entry_done->entry_idx); |
2108 | 2119 | ||
2109 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); | 2120 | rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN); |
2110 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 2121 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
2111 | } | 2122 | } |
2112 | 2123 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 87fb2201537b..e22f01c1818e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -545,7 +545,8 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
545 | } | 545 | } |
546 | 546 | ||
547 | static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, | 547 | static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, |
548 | struct rt2x00lib_erp *erp) | 548 | struct rt2x00lib_erp *erp, |
549 | u32 changed) | ||
549 | { | 550 | { |
550 | u32 reg; | 551 | u32 reg; |
551 | 552 | ||
@@ -554,28 +555,36 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, | |||
554 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); | 555 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); |
555 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 556 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
556 | 557 | ||
557 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 558 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
558 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); | 559 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
559 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, | 560 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); |
560 | !!erp->short_preamble); | 561 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, |
561 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); | 562 | !!erp->short_preamble); |
563 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); | ||
564 | } | ||
562 | 565 | ||
563 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); | 566 | if (changed & BSS_CHANGED_BASIC_RATES) |
567 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, | ||
568 | erp->basic_rates); | ||
564 | 569 | ||
565 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 570 | if (changed & BSS_CHANGED_BEACON_INT) { |
566 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, | 571 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
567 | erp->beacon_int * 16); | 572 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, |
568 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 573 | erp->beacon_int * 16); |
574 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
575 | } | ||
569 | 576 | ||
570 | rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); | 577 | if (changed & BSS_CHANGED_ERP_SLOT) { |
571 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); | 578 | rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); |
572 | rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); | 579 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); |
580 | rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); | ||
573 | 581 | ||
574 | rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); | 582 | rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); |
575 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); | 583 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); |
576 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); | 584 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); |
577 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); | 585 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); |
578 | rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); | 586 | rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); |
587 | } | ||
579 | } | 588 | } |
580 | 589 | ||
581 | static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | 590 | static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 2f98058be451..4a8bb25c1739 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -74,4 +74,7 @@ config WL1271_SDIO | |||
74 | If you choose to build a module, it'll be called | 74 | If you choose to build a module, it'll be called |
75 | wl1271_sdio. Say N if unsure. | 75 | wl1271_sdio. Say N if unsure. |
76 | 76 | ||
77 | 77 | config WL12XX_PLATFORM_DATA | |
78 | bool | ||
79 | depends on WL1271_SDIO != n | ||
80 | default y | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index c0b68b0a9aa8..74ba9ced5393 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/mmc/sdio_func.h> | 24 | #include <linux/mmc/sdio_func.h> |
25 | #include <linux/mmc/sdio_ids.h> | 25 | #include <linux/mmc/sdio_ids.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/spi/wl12xx.h> | 27 | #include <linux/wl12xx.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | 29 | ||
30 | #include "wl1251.h" | 30 | #include "wl1251.h" |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 334ded9881c0..320de79667a6 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/crc7.h> | 25 | #include <linux/crc7.h> |
26 | #include <linux/spi/spi.h> | 26 | #include <linux/spi/spi.h> |
27 | #include <linux/spi/wl12xx.h> | 27 | #include <linux/wl12xx.h> |
28 | 28 | ||
29 | #include "wl1251.h" | 29 | #include "wl1251.h" |
30 | #include "wl1251_reg.h" | 30 | #include "wl1251_reg.h" |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index dd3cee6ea5bb..4134f4495b95 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -313,7 +313,7 @@ struct wl1271_if_operations { | |||
313 | bool fixed); | 313 | bool fixed); |
314 | void (*reset)(struct wl1271 *wl); | 314 | void (*reset)(struct wl1271 *wl); |
315 | void (*init)(struct wl1271 *wl); | 315 | void (*init)(struct wl1271 *wl); |
316 | void (*power)(struct wl1271 *wl, bool enable); | 316 | int (*power)(struct wl1271 *wl, bool enable); |
317 | struct device* (*dev)(struct wl1271 *wl); | 317 | struct device* (*dev)(struct wl1271 *wl); |
318 | void (*enable_irq)(struct wl1271 *wl); | 318 | void (*enable_irq)(struct wl1271 *wl); |
319 | void (*disable_irq)(struct wl1271 *wl); | 319 | void (*disable_irq)(struct wl1271 *wl); |
@@ -330,6 +330,7 @@ struct wl1271 { | |||
330 | 330 | ||
331 | void (*set_power)(bool enable); | 331 | void (*set_power)(bool enable); |
332 | int irq; | 332 | int irq; |
333 | int ref_clock; | ||
333 | 334 | ||
334 | spinlock_t wl_lock; | 335 | spinlock_t wl_lock; |
335 | 336 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index f36430b0336d..fc21db810812 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -457,17 +457,20 @@ int wl1271_boot(struct wl1271 *wl) | |||
457 | { | 457 | { |
458 | int ret = 0; | 458 | int ret = 0; |
459 | u32 tmp, clk, pause; | 459 | u32 tmp, clk, pause; |
460 | int ref_clock = wl->ref_clock; | ||
460 | 461 | ||
461 | wl1271_boot_hw_version(wl); | 462 | wl1271_boot_hw_version(wl); |
462 | 463 | ||
463 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) | 464 | if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4) |
464 | /* ref clk: 19.2/38.4/38.4-XTAL */ | 465 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
465 | clk = 0x3; | 466 | clk = 0x3; |
466 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) | 467 | else if (ref_clock == 1 || ref_clock == 3) |
467 | /* ref clk: 26/52 */ | 468 | /* ref clk: 26/52 */ |
468 | clk = 0x5; | 469 | clk = 0x5; |
470 | else | ||
471 | return -EINVAL; | ||
469 | 472 | ||
470 | if (REF_CLOCK != 0) { | 473 | if (ref_clock != 0) { |
471 | u16 val; | 474 | u16 val; |
472 | /* Set clock type (open drain) */ | 475 | /* Set clock type (open drain) */ |
473 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 476 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
@@ -516,7 +519,7 @@ int wl1271_boot(struct wl1271 *wl) | |||
516 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 519 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
517 | 520 | ||
518 | /* 2 */ | 521 | /* 2 */ |
519 | clk |= (REF_CLOCK << 1) << 4; | 522 | clk |= (ref_clock << 1) << 4; |
520 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); | 523 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
521 | 524 | ||
522 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 525 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index f829699d597e..f73b0b15a280 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -46,7 +46,6 @@ struct wl1271_static_data { | |||
46 | /* delay between retries */ | 46 | /* delay between retries */ |
47 | #define INIT_LOOP_DELAY 50 | 47 | #define INIT_LOOP_DELAY 50 |
48 | 48 | ||
49 | #define REF_CLOCK 2 | ||
50 | #define WU_COUNTER_PAUSE_VAL 0x3FF | 49 | #define WU_COUNTER_PAUSE_VAL 0x3FF |
51 | #define WELP_ARM_COMMAND_VAL 0x4 | 50 | #define WELP_ARM_COMMAND_VAL 0x4 |
52 | 51 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index bc806c74c63a..c1f92e65ded0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -144,10 +144,13 @@ static inline void wl1271_power_off(struct wl1271 *wl) | |||
144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); |
145 | } | 145 | } |
146 | 146 | ||
147 | static inline void wl1271_power_on(struct wl1271 *wl) | 147 | static inline int wl1271_power_on(struct wl1271 *wl) |
148 | { | 148 | { |
149 | wl->if_ops->power(wl, true); | 149 | int ret = wl->if_ops->power(wl, true); |
150 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 150 | if (ret == 0) |
151 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
152 | |||
153 | return ret; | ||
151 | } | 154 | } |
152 | 155 | ||
153 | 156 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 8e55cf8d509d..776cd7c41148 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -621,7 +621,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
621 | int ret = 0; | 621 | int ret = 0; |
622 | 622 | ||
623 | msleep(WL1271_PRE_POWER_ON_SLEEP); | 623 | msleep(WL1271_PRE_POWER_ON_SLEEP); |
624 | wl1271_power_on(wl); | 624 | ret = wl1271_power_on(wl); |
625 | if (ret < 0) | ||
626 | goto out; | ||
625 | msleep(WL1271_POWER_ON_SLEEP); | 627 | msleep(WL1271_POWER_ON_SLEEP); |
626 | wl1271_io_reset(wl); | 628 | wl1271_io_reset(wl); |
627 | wl1271_io_init(wl); | 629 | wl1271_io_init(wl); |
@@ -1632,7 +1634,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1632 | if (ret < 0) | 1634 | if (ret < 0) |
1633 | goto out; | 1635 | goto out; |
1634 | 1636 | ||
1635 | if ((changed && BSS_CHANGED_BEACON_INT) && | 1637 | if ((changed & BSS_CHANGED_BEACON_INT) && |
1636 | (wl->bss_type == BSS_TYPE_IBSS)) { | 1638 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1637 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", | 1639 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1638 | bss_conf->beacon_int); | 1640 | bss_conf->beacon_int); |
@@ -1641,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1641 | do_join = true; | 1643 | do_join = true; |
1642 | } | 1644 | } |
1643 | 1645 | ||
1644 | if ((changed && BSS_CHANGED_BEACON) && | 1646 | if ((changed & BSS_CHANGED_BEACON) && |
1645 | (wl->bss_type == BSS_TYPE_IBSS)) { | 1647 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1646 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1648 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1647 | 1649 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 019aa79cd9df..94da5dd7723c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -76,7 +76,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
76 | 76 | ||
77 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | 77 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) |
78 | { | 78 | { |
79 | struct ieee80211_rx_status rx_status; | ||
80 | struct wl1271_rx_descriptor *desc; | 79 | struct wl1271_rx_descriptor *desc; |
81 | struct sk_buff *skb; | 80 | struct sk_buff *skb; |
82 | u16 *fc; | 81 | u16 *fc; |
@@ -109,14 +108,13 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
109 | if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) | 108 | if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) |
110 | beacon = 1; | 109 | beacon = 1; |
111 | 110 | ||
112 | wl1271_rx_status(wl, desc, &rx_status, beacon); | 111 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
113 | 112 | ||
114 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | 113 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, |
115 | beacon ? "beacon" : ""); | 114 | beacon ? "beacon" : ""); |
116 | 115 | ||
117 | skb_trim(skb, skb->len - desc->pad_len); | 116 | skb_trim(skb, skb->len - desc->pad_len); |
118 | 117 | ||
119 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | ||
120 | ieee80211_rx_ni(wl->hw, skb); | 118 | ieee80211_rx_ni(wl->hw, skb); |
121 | } | 119 | } |
122 | 120 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 7059b5cccf0f..f2f04663627c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -29,14 +29,12 @@ | |||
29 | #include <linux/mmc/sdio_ids.h> | 29 | #include <linux/mmc/sdio_ids.h> |
30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/wl12xx.h> | ||
32 | 33 | ||
33 | #include "wl1271.h" | 34 | #include "wl1271.h" |
34 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
35 | #include "wl1271_io.h" | 36 | #include "wl1271_io.h" |
36 | 37 | ||
37 | |||
38 | #define RX71_WL1271_IRQ_GPIO 42 | ||
39 | |||
40 | #ifndef SDIO_VENDOR_ID_TI | 38 | #ifndef SDIO_VENDOR_ID_TI |
41 | #define SDIO_VENDOR_ID_TI 0x0097 | 39 | #define SDIO_VENDOR_ID_TI 0x0097 |
42 | #endif | 40 | #endif |
@@ -107,6 +105,8 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
107 | int ret; | 105 | int ret; |
108 | struct sdio_func *func = wl_to_func(wl); | 106 | struct sdio_func *func = wl_to_func(wl); |
109 | 107 | ||
108 | sdio_claim_host(func); | ||
109 | |||
110 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 110 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
111 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 111 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
112 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", | 112 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", |
@@ -122,9 +122,10 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
123 | } | 123 | } |
124 | 124 | ||
125 | sdio_release_host(func); | ||
126 | |||
125 | if (ret) | 127 | if (ret) |
126 | wl1271_error("sdio read failed (%d)", ret); | 128 | wl1271_error("sdio read failed (%d)", ret); |
127 | |||
128 | } | 129 | } |
129 | 130 | ||
130 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | 131 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, |
@@ -133,6 +134,8 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
133 | int ret; | 134 | int ret; |
134 | struct sdio_func *func = wl_to_func(wl); | 135 | struct sdio_func *func = wl_to_func(wl); |
135 | 136 | ||
137 | sdio_claim_host(func); | ||
138 | |||
136 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 139 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
137 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 140 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | 141 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", |
@@ -147,26 +150,45 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
147 | else | 150 | else |
148 | ret = sdio_memcpy_toio(func, addr, buf, len); | 151 | ret = sdio_memcpy_toio(func, addr, buf, len); |
149 | } | 152 | } |
153 | |||
154 | sdio_release_host(func); | ||
155 | |||
150 | if (ret) | 156 | if (ret) |
151 | wl1271_error("sdio write failed (%d)", ret); | 157 | wl1271_error("sdio write failed (%d)", ret); |
158 | } | ||
159 | |||
160 | static int wl1271_sdio_power_on(struct wl1271 *wl) | ||
161 | { | ||
162 | struct sdio_func *func = wl_to_func(wl); | ||
163 | |||
164 | sdio_claim_host(func); | ||
165 | sdio_enable_func(func); | ||
166 | sdio_release_host(func); | ||
152 | 167 | ||
168 | return 0; | ||
153 | } | 169 | } |
154 | 170 | ||
155 | static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | 171 | static int wl1271_sdio_power_off(struct wl1271 *wl) |
156 | { | 172 | { |
157 | struct sdio_func *func = wl_to_func(wl); | 173 | struct sdio_func *func = wl_to_func(wl); |
158 | 174 | ||
175 | sdio_claim_host(func); | ||
176 | sdio_disable_func(func); | ||
177 | sdio_release_host(func); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | ||
183 | { | ||
159 | /* Let the SDIO stack handle wlan_enable control, so we | 184 | /* Let the SDIO stack handle wlan_enable control, so we |
160 | * keep host claimed while wlan is in use to keep wl1271 | 185 | * keep host claimed while wlan is in use to keep wl1271 |
161 | * alive. | 186 | * alive. |
162 | */ | 187 | */ |
163 | if (enable) { | 188 | if (enable) |
164 | sdio_claim_host(func); | 189 | return wl1271_sdio_power_on(wl); |
165 | sdio_enable_func(func); | 190 | else |
166 | } else { | 191 | return wl1271_sdio_power_off(wl); |
167 | sdio_disable_func(func); | ||
168 | sdio_release_host(func); | ||
169 | } | ||
170 | } | 192 | } |
171 | 193 | ||
172 | static struct wl1271_if_operations sdio_ops = { | 194 | static struct wl1271_if_operations sdio_ops = { |
@@ -184,6 +206,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
184 | const struct sdio_device_id *id) | 206 | const struct sdio_device_id *id) |
185 | { | 207 | { |
186 | struct ieee80211_hw *hw; | 208 | struct ieee80211_hw *hw; |
209 | const struct wl12xx_platform_data *wlan_data; | ||
187 | struct wl1271 *wl; | 210 | struct wl1271 *wl; |
188 | int ret; | 211 | int ret; |
189 | 212 | ||
@@ -203,13 +226,16 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
203 | /* Grab access to FN0 for ELP reg. */ | 226 | /* Grab access to FN0 for ELP reg. */ |
204 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | 227 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; |
205 | 228 | ||
206 | wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); | 229 | wlan_data = wl12xx_get_platform_data(); |
207 | if (wl->irq < 0) { | 230 | if (IS_ERR(wlan_data)) { |
208 | ret = wl->irq; | 231 | ret = PTR_ERR(wlan_data); |
209 | wl1271_error("could not get irq!"); | 232 | wl1271_error("missing wlan platform data: %d", ret); |
210 | goto out_free; | 233 | goto out_free; |
211 | } | 234 | } |
212 | 235 | ||
236 | wl->irq = wlan_data->irq; | ||
237 | wl->ref_clock = wlan_data->board_ref_clock; | ||
238 | |||
213 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | 239 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); |
214 | if (ret < 0) { | 240 | if (ret < 0) { |
215 | wl1271_error("request_irq() failed: %d", ret); | 241 | wl1271_error("request_irq() failed: %d", ret); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4cb99c541e2a..ced0a9e2c7e1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/spi/wl12xx.h> | 28 | #include <linux/wl12xx.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | #include "wl1271.h" | 31 | #include "wl1271.h" |
@@ -312,10 +312,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
312 | return IRQ_HANDLED; | 312 | return IRQ_HANDLED; |
313 | } | 313 | } |
314 | 314 | ||
315 | static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) | 315 | static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) |
316 | { | 316 | { |
317 | if (wl->set_power) | 317 | if (wl->set_power) |
318 | wl->set_power(enable); | 318 | wl->set_power(enable); |
319 | |||
320 | return 0; | ||
319 | } | 321 | } |
320 | 322 | ||
321 | static struct wl1271_if_operations spi_ops = { | 323 | static struct wl1271_if_operations spi_ops = { |
@@ -370,6 +372,8 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
370 | goto out_free; | 372 | goto out_free; |
371 | } | 373 | } |
372 | 374 | ||
375 | wl->ref_clock = pdata->board_ref_clock; | ||
376 | |||
373 | wl->irq = spi->irq; | 377 | wl->irq = spi->irq; |
374 | if (wl->irq < 0) { | 378 | if (wl->irq < 0) { |
375 | wl1271_error("irq missing in platform data"); | 379 | wl1271_error("irq missing in platform data"); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c new file mode 100644 index 000000000000..973b11060a8f --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c | |||
@@ -0,0 +1,28 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/err.h> | ||
3 | #include <linux/wl12xx.h> | ||
4 | |||
5 | static const struct wl12xx_platform_data *platform_data; | ||
6 | |||
7 | int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) | ||
8 | { | ||
9 | if (platform_data) | ||
10 | return -EBUSY; | ||
11 | if (!data) | ||
12 | return -EINVAL; | ||
13 | |||
14 | platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); | ||
15 | if (!platform_data) | ||
16 | return -ENOMEM; | ||
17 | |||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | const struct wl12xx_platform_data *wl12xx_get_platform_data(void) | ||
22 | { | ||
23 | if (!platform_data) | ||
24 | return ERR_PTR(-ENODEV); | ||
25 | |||
26 | return platform_data; | ||
27 | } | ||
28 | EXPORT_SYMBOL(wl12xx_get_platform_data); | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 31603e8b5581..f0518b0278a9 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -1020,6 +1020,8 @@ enum nl80211_attrs { | |||
1020 | * @NL80211_IFTYPE_WDS: wireless distribution interface | 1020 | * @NL80211_IFTYPE_WDS: wireless distribution interface |
1021 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames | 1021 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames |
1022 | * @NL80211_IFTYPE_MESH_POINT: mesh point | 1022 | * @NL80211_IFTYPE_MESH_POINT: mesh point |
1023 | * @NL80211_IFTYPE_P2P_CLIENT: P2P client | ||
1024 | * @NL80211_IFTYPE_P2P_GO: P2P group owner | ||
1023 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined | 1025 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined |
1024 | * @NUM_NL80211_IFTYPES: number of defined interface types | 1026 | * @NUM_NL80211_IFTYPES: number of defined interface types |
1025 | * | 1027 | * |
@@ -1036,6 +1038,8 @@ enum nl80211_iftype { | |||
1036 | NL80211_IFTYPE_WDS, | 1038 | NL80211_IFTYPE_WDS, |
1037 | NL80211_IFTYPE_MONITOR, | 1039 | NL80211_IFTYPE_MONITOR, |
1038 | NL80211_IFTYPE_MESH_POINT, | 1040 | NL80211_IFTYPE_MESH_POINT, |
1041 | NL80211_IFTYPE_P2P_CLIENT, | ||
1042 | NL80211_IFTYPE_P2P_GO, | ||
1039 | 1043 | ||
1040 | /* keep last */ | 1044 | /* keep last */ |
1041 | NUM_NL80211_IFTYPES, | 1045 | NUM_NL80211_IFTYPES, |
diff --git a/include/linux/spi/wl12xx.h b/include/linux/wl12xx.h index a20bccf0b5c2..95deae3968f4 100644 --- a/include/linux/spi/wl12xx.h +++ b/include/linux/wl12xx.h | |||
@@ -21,14 +21,18 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef _LINUX_SPI_WL12XX_H | 24 | #ifndef _LINUX_WL12XX_H |
25 | #define _LINUX_SPI_WL12XX_H | 25 | #define _LINUX_WL12XX_H |
26 | 26 | ||
27 | struct wl12xx_platform_data { | 27 | struct wl12xx_platform_data { |
28 | void (*set_power)(bool enable); | 28 | void (*set_power)(bool enable); |
29 | /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */ | 29 | /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */ |
30 | int irq; | 30 | int irq; |
31 | bool use_eeprom; | 31 | bool use_eeprom; |
32 | int board_ref_clock; | ||
32 | }; | 33 | }; |
33 | 34 | ||
35 | int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); | ||
36 | const struct wl12xx_platform_data *wl12xx_get_platform_data(void); | ||
37 | |||
34 | #endif | 38 | #endif |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4c8c727d0cca..a0613ff62c97 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -2558,49 +2558,36 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, | |||
2558 | /* wiphy_printk helpers, similar to dev_printk */ | 2558 | /* wiphy_printk helpers, similar to dev_printk */ |
2559 | 2559 | ||
2560 | #define wiphy_printk(level, wiphy, format, args...) \ | 2560 | #define wiphy_printk(level, wiphy, format, args...) \ |
2561 | printk(level "%s: " format, wiphy_name(wiphy), ##args) | 2561 | dev_printk(level, &(wiphy)->dev, format, ##args) |
2562 | #define wiphy_emerg(wiphy, format, args...) \ | 2562 | #define wiphy_emerg(wiphy, format, args...) \ |
2563 | wiphy_printk(KERN_EMERG, wiphy, format, ##args) | 2563 | dev_emerg(&(wiphy)->dev, format, ##args) |
2564 | #define wiphy_alert(wiphy, format, args...) \ | 2564 | #define wiphy_alert(wiphy, format, args...) \ |
2565 | wiphy_printk(KERN_ALERT, wiphy, format, ##args) | 2565 | dev_alert(&(wiphy)->dev, format, ##args) |
2566 | #define wiphy_crit(wiphy, format, args...) \ | 2566 | #define wiphy_crit(wiphy, format, args...) \ |
2567 | wiphy_printk(KERN_CRIT, wiphy, format, ##args) | 2567 | dev_crit(&(wiphy)->dev, format, ##args) |
2568 | #define wiphy_err(wiphy, format, args...) \ | 2568 | #define wiphy_err(wiphy, format, args...) \ |
2569 | wiphy_printk(KERN_ERR, wiphy, format, ##args) | 2569 | dev_err(&(wiphy)->dev, format, ##args) |
2570 | #define wiphy_warn(wiphy, format, args...) \ | 2570 | #define wiphy_warn(wiphy, format, args...) \ |
2571 | wiphy_printk(KERN_WARNING, wiphy, format, ##args) | 2571 | dev_warn(&(wiphy)->dev, format, ##args) |
2572 | #define wiphy_notice(wiphy, format, args...) \ | 2572 | #define wiphy_notice(wiphy, format, args...) \ |
2573 | wiphy_printk(KERN_NOTICE, wiphy, format, ##args) | 2573 | dev_notice(&(wiphy)->dev, format, ##args) |
2574 | #define wiphy_info(wiphy, format, args...) \ | 2574 | #define wiphy_info(wiphy, format, args...) \ |
2575 | wiphy_printk(KERN_INFO, wiphy, format, ##args) | 2575 | dev_info(&(wiphy)->dev, format, ##args) |
2576 | 2576 | ||
2577 | int wiphy_debug(const struct wiphy *wiphy, const char *format, ...) | 2577 | #define wiphy_debug(wiphy, format, args...) \ |
2578 | __attribute__ ((format (printf, 2, 3))); | ||
2579 | |||
2580 | #if defined(DEBUG) | ||
2581 | #define wiphy_dbg(wiphy, format, args...) \ | ||
2582 | wiphy_printk(KERN_DEBUG, wiphy, format, ##args) | 2578 | wiphy_printk(KERN_DEBUG, wiphy, format, ##args) |
2583 | #elif defined(CONFIG_DYNAMIC_DEBUG) | 2579 | |
2584 | #define wiphy_dbg(wiphy, format, args...) \ | 2580 | #define wiphy_dbg(wiphy, format, args...) \ |
2585 | dynamic_pr_debug("%s: " format, wiphy_name(wiphy), ##args) | 2581 | dev_dbg(&(wiphy)->dev, format, ##args) |
2586 | #else | ||
2587 | #define wiphy_dbg(wiphy, format, args...) \ | ||
2588 | ({ \ | ||
2589 | if (0) \ | ||
2590 | wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \ | ||
2591 | 0; \ | ||
2592 | }) | ||
2593 | #endif | ||
2594 | 2582 | ||
2595 | #if defined(VERBOSE_DEBUG) | 2583 | #if defined(VERBOSE_DEBUG) |
2596 | #define wiphy_vdbg wiphy_dbg | 2584 | #define wiphy_vdbg wiphy_dbg |
2597 | #else | 2585 | #else |
2598 | |||
2599 | #define wiphy_vdbg(wiphy, format, args...) \ | 2586 | #define wiphy_vdbg(wiphy, format, args...) \ |
2600 | ({ \ | 2587 | ({ \ |
2601 | if (0) \ | 2588 | if (0) \ |
2602 | wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \ | 2589 | wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \ |
2603 | 0; \ | 2590 | 0; \ |
2604 | }) | 2591 | }) |
2605 | #endif | 2592 | #endif |
2606 | 2593 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f91fc331369b..12a49f0ba32c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -769,6 +769,8 @@ struct ieee80211_channel_switch { | |||
769 | * @bss_conf: BSS configuration for this interface, either our own | 769 | * @bss_conf: BSS configuration for this interface, either our own |
770 | * or the BSS we're associated to | 770 | * or the BSS we're associated to |
771 | * @addr: address of this interface | 771 | * @addr: address of this interface |
772 | * @p2p: indicates whether this AP or STA interface is a p2p | ||
773 | * interface, i.e. a GO or p2p-sta respectively | ||
772 | * @drv_priv: data area for driver use, will always be aligned to | 774 | * @drv_priv: data area for driver use, will always be aligned to |
773 | * sizeof(void *). | 775 | * sizeof(void *). |
774 | */ | 776 | */ |
@@ -776,6 +778,7 @@ struct ieee80211_vif { | |||
776 | enum nl80211_iftype type; | 778 | enum nl80211_iftype type; |
777 | struct ieee80211_bss_conf bss_conf; | 779 | struct ieee80211_bss_conf bss_conf; |
778 | u8 addr[ETH_ALEN]; | 780 | u8 addr[ETH_ALEN]; |
781 | bool p2p; | ||
779 | /* must be last */ | 782 | /* must be last */ |
780 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 783 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
781 | }; | 784 | }; |
@@ -1701,7 +1704,7 @@ struct ieee80211_ops { | |||
1701 | struct ieee80211_vif *vif); | 1704 | struct ieee80211_vif *vif); |
1702 | int (*change_interface)(struct ieee80211_hw *hw, | 1705 | int (*change_interface)(struct ieee80211_hw *hw, |
1703 | struct ieee80211_vif *vif, | 1706 | struct ieee80211_vif *vif, |
1704 | enum nl80211_iftype new_type); | 1707 | enum nl80211_iftype new_type, bool p2p); |
1705 | void (*remove_interface)(struct ieee80211_hw *hw, | 1708 | void (*remove_interface)(struct ieee80211_hw *hw, |
1706 | struct ieee80211_vif *vif); | 1709 | struct ieee80211_vif *vif); |
1707 | int (*config)(struct ieee80211_hw *hw, u32 changed); | 1710 | int (*config)(struct ieee80211_hw *hw, u32 changed); |
@@ -2293,6 +2296,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); | |||
2293 | * This function allows the iterator function to sleep, when the iterator | 2296 | * This function allows the iterator function to sleep, when the iterator |
2294 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can | 2297 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can |
2295 | * be used. | 2298 | * be used. |
2299 | * Does not iterate over a new interface during add_interface() | ||
2296 | * | 2300 | * |
2297 | * @hw: the hardware struct of which the interfaces should be iterated over | 2301 | * @hw: the hardware struct of which the interfaces should be iterated over |
2298 | * @iterator: the iterator function to call | 2302 | * @iterator: the iterator function to call |
@@ -2310,6 +2314,7 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, | |||
2310 | * hardware that are currently active and calls the callback for them. | 2314 | * hardware that are currently active and calls the callback for them. |
2311 | * This function requires the iterator callback function to be atomic, | 2315 | * This function requires the iterator callback function to be atomic, |
2312 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. | 2316 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. |
2317 | * Does not iterate over a new interface during add_interface() | ||
2313 | * | 2318 | * |
2314 | * @hw: the hardware struct of which the interfaces should be iterated over | 2319 | * @hw: the hardware struct of which the interfaces should be iterated over |
2315 | * @iterator: the iterator function to call, cannot sleep | 2320 | * @iterator: the iterator function to call, cannot sleep |
@@ -2719,4 +2724,26 @@ conf_is_ht(struct ieee80211_conf *conf) | |||
2719 | return conf->channel_type != NL80211_CHAN_NO_HT; | 2724 | return conf->channel_type != NL80211_CHAN_NO_HT; |
2720 | } | 2725 | } |
2721 | 2726 | ||
2727 | static inline enum nl80211_iftype | ||
2728 | ieee80211_iftype_p2p(enum nl80211_iftype type, bool p2p) | ||
2729 | { | ||
2730 | if (p2p) { | ||
2731 | switch (type) { | ||
2732 | case NL80211_IFTYPE_STATION: | ||
2733 | return NL80211_IFTYPE_P2P_CLIENT; | ||
2734 | case NL80211_IFTYPE_AP: | ||
2735 | return NL80211_IFTYPE_P2P_GO; | ||
2736 | default: | ||
2737 | break; | ||
2738 | } | ||
2739 | } | ||
2740 | return type; | ||
2741 | } | ||
2742 | |||
2743 | static inline enum nl80211_iftype | ||
2744 | ieee80211_vif_type_p2p(struct ieee80211_vif *vif) | ||
2745 | { | ||
2746 | return ieee80211_iftype_p2p(vif->type, vif->p2p); | ||
2747 | } | ||
2748 | |||
2722 | #endif /* MAC80211_H */ | 2749 | #endif /* MAC80211_H */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5de1ca3f17b9..c981604b71e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -577,6 +577,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
577 | struct sta_info *sta, | 577 | struct sta_info *sta, |
578 | struct station_parameters *params) | 578 | struct station_parameters *params) |
579 | { | 579 | { |
580 | unsigned long flags; | ||
580 | u32 rates; | 581 | u32 rates; |
581 | int i, j; | 582 | int i, j; |
582 | struct ieee80211_supported_band *sband; | 583 | struct ieee80211_supported_band *sband; |
@@ -585,7 +586,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
585 | 586 | ||
586 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 587 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
587 | 588 | ||
588 | spin_lock_bh(&sta->lock); | 589 | spin_lock_irqsave(&sta->flaglock, flags); |
589 | mask = params->sta_flags_mask; | 590 | mask = params->sta_flags_mask; |
590 | set = params->sta_flags_set; | 591 | set = params->sta_flags_set; |
591 | 592 | ||
@@ -612,7 +613,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
612 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 613 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
613 | sta->flags |= WLAN_STA_MFP; | 614 | sta->flags |= WLAN_STA_MFP; |
614 | } | 615 | } |
615 | spin_unlock_bh(&sta->lock); | 616 | spin_unlock_irqrestore(&sta->flaglock, flags); |
616 | 617 | ||
617 | /* | 618 | /* |
618 | * cfg80211 validates this (1-2007) and allows setting the AID | 619 | * cfg80211 validates this (1-2007) and allows setting the AID |
@@ -1150,15 +1151,26 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1150 | struct net_device *dev, | 1151 | struct net_device *dev, |
1151 | struct cfg80211_scan_request *req) | 1152 | struct cfg80211_scan_request *req) |
1152 | { | 1153 | { |
1153 | struct ieee80211_sub_if_data *sdata; | 1154 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1154 | |||
1155 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1156 | 1155 | ||
1157 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1156 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1158 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1157 | case NL80211_IFTYPE_STATION: |
1159 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 1158 | case NL80211_IFTYPE_ADHOC: |
1160 | (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | 1159 | case NL80211_IFTYPE_MESH_POINT: |
1160 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1161 | break; | ||
1162 | case NL80211_IFTYPE_P2P_GO: | ||
1163 | if (sdata->local->ops->hw_scan) | ||
1164 | break; | ||
1165 | /* FIXME: implement NoA while scanning in software */ | ||
1166 | return -EOPNOTSUPP; | ||
1167 | case NL80211_IFTYPE_AP: | ||
1168 | if (sdata->u.ap.beacon) | ||
1169 | return -EOPNOTSUPP; | ||
1170 | break; | ||
1171 | default: | ||
1161 | return -EOPNOTSUPP; | 1172 | return -EOPNOTSUPP; |
1173 | } | ||
1162 | 1174 | ||
1163 | return ieee80211_request_scan(sdata, req); | 1175 | return ieee80211_request_scan(sdata, req); |
1164 | } | 1176 | } |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 32be11e4c4d9..5b24740fc0b0 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -11,7 +11,7 @@ __ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
11 | { | 11 | { |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | 13 | ||
14 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | 14 | lockdep_assert_held(&local->iflist_mtx); |
15 | 15 | ||
16 | list_for_each_entry(sdata, &local->interfaces, list) { | 16 | list_for_each_entry(sdata, &local->interfaces, list) { |
17 | if (sdata == ignore) | 17 | if (sdata == ignore) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6064b7b09e01..16983825f8e8 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -56,14 +56,14 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
56 | 56 | ||
57 | static inline int drv_change_interface(struct ieee80211_local *local, | 57 | static inline int drv_change_interface(struct ieee80211_local *local, |
58 | struct ieee80211_sub_if_data *sdata, | 58 | struct ieee80211_sub_if_data *sdata, |
59 | enum nl80211_iftype type) | 59 | enum nl80211_iftype type, bool p2p) |
60 | { | 60 | { |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | might_sleep(); | 63 | might_sleep(); |
64 | 64 | ||
65 | trace_drv_change_interface(local, sdata, type); | 65 | trace_drv_change_interface(local, sdata, type, p2p); |
66 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type); | 66 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); |
67 | trace_drv_return_int(local, ret); | 67 | trace_drv_return_int(local, ret); |
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index f6f3d89e43fa..6831fb1641c8 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -25,12 +25,14 @@ static inline void trace_ ## name(proto) {} | |||
25 | #define STA_PR_FMT " sta:%pM" | 25 | #define STA_PR_FMT " sta:%pM" |
26 | #define STA_PR_ARG __entry->sta_addr | 26 | #define STA_PR_ARG __entry->sta_addr |
27 | 27 | ||
28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ | 28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ |
29 | __field(bool, p2p) \ | ||
29 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 30 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
30 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 31 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
32 | __entry->p2p = sdata->vif.p2p; \ | ||
31 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 33 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | #define VIF_PR_FMT " vif:%s(%d)" | 34 | #define VIF_PR_FMT " vif:%s(%d%s)" |
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | 35 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
34 | 36 | ||
35 | /* | 37 | /* |
36 | * Tracing for driver callbacks. | 38 | * Tracing for driver callbacks. |
@@ -139,25 +141,28 @@ TRACE_EVENT(drv_add_interface, | |||
139 | TRACE_EVENT(drv_change_interface, | 141 | TRACE_EVENT(drv_change_interface, |
140 | TP_PROTO(struct ieee80211_local *local, | 142 | TP_PROTO(struct ieee80211_local *local, |
141 | struct ieee80211_sub_if_data *sdata, | 143 | struct ieee80211_sub_if_data *sdata, |
142 | enum nl80211_iftype type), | 144 | enum nl80211_iftype type, bool p2p), |
143 | 145 | ||
144 | TP_ARGS(local, sdata, type), | 146 | TP_ARGS(local, sdata, type, p2p), |
145 | 147 | ||
146 | TP_STRUCT__entry( | 148 | TP_STRUCT__entry( |
147 | LOCAL_ENTRY | 149 | LOCAL_ENTRY |
148 | VIF_ENTRY | 150 | VIF_ENTRY |
149 | __field(u32, new_type) | 151 | __field(u32, new_type) |
152 | __field(bool, new_p2p) | ||
150 | ), | 153 | ), |
151 | 154 | ||
152 | TP_fast_assign( | 155 | TP_fast_assign( |
153 | LOCAL_ASSIGN; | 156 | LOCAL_ASSIGN; |
154 | VIF_ASSIGN; | 157 | VIF_ASSIGN; |
155 | __entry->new_type = type; | 158 | __entry->new_type = type; |
159 | __entry->new_p2p = p2p; | ||
156 | ), | 160 | ), |
157 | 161 | ||
158 | TP_printk( | 162 | TP_printk( |
159 | LOCAL_PR_FMT VIF_PR_FMT " new type:%d", | 163 | LOCAL_PR_FMT VIF_PR_FMT " new type:%d%s", |
160 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type | 164 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type, |
165 | __entry->new_p2p ? "/p2p" : "" | ||
161 | ) | 166 | ) |
162 | ); | 167 | ); |
163 | 168 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4e635e2fabdb..9346a6b0f400 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1041,6 +1041,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | |||
1041 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1041 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1042 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1042 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1043 | struct sk_buff *skb); | 1043 | struct sk_buff *skb); |
1044 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); | ||
1045 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | ||
1044 | 1046 | ||
1045 | /* IBSS code */ | 1047 | /* IBSS code */ |
1046 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1048 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index c1cc200ac81f..66785739dad3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -188,6 +188,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
188 | break; | 188 | break; |
189 | case NL80211_IFTYPE_UNSPECIFIED: | 189 | case NL80211_IFTYPE_UNSPECIFIED: |
190 | case NUM_NL80211_IFTYPES: | 190 | case NUM_NL80211_IFTYPES: |
191 | case NL80211_IFTYPE_P2P_CLIENT: | ||
192 | case NL80211_IFTYPE_P2P_GO: | ||
191 | /* cannot happen */ | 193 | /* cannot happen */ |
192 | WARN_ON(1); | 194 | WARN_ON(1); |
193 | break; | 195 | break; |
@@ -280,6 +282,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
280 | netif_carrier_on(dev); | 282 | netif_carrier_on(dev); |
281 | } | 283 | } |
282 | 284 | ||
285 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
286 | |||
283 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 287 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
284 | /* Create STA entry for the WDS peer */ | 288 | /* Create STA entry for the WDS peer */ |
285 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | 289 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
@@ -331,8 +335,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
331 | 335 | ||
332 | netif_tx_start_all_queues(dev); | 336 | netif_tx_start_all_queues(dev); |
333 | 337 | ||
334 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
335 | |||
336 | return 0; | 338 | return 0; |
337 | err_del_interface: | 339 | err_del_interface: |
338 | drv_remove_interface(local, &sdata->vif); | 340 | drv_remove_interface(local, &sdata->vif); |
@@ -343,6 +345,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
343 | sdata->bss = NULL; | 345 | sdata->bss = NULL; |
344 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 346 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
345 | list_del(&sdata->u.vlan.list); | 347 | list_del(&sdata->u.vlan.list); |
348 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
346 | return res; | 349 | return res; |
347 | } | 350 | } |
348 | 351 | ||
@@ -843,6 +846,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
843 | 846 | ||
844 | /* and set some type-dependent values */ | 847 | /* and set some type-dependent values */ |
845 | sdata->vif.type = type; | 848 | sdata->vif.type = type; |
849 | sdata->vif.p2p = false; | ||
846 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | 850 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
847 | sdata->wdev.iftype = type; | 851 | sdata->wdev.iftype = type; |
848 | 852 | ||
@@ -856,10 +860,20 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
856 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 860 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
857 | 861 | ||
858 | switch (type) { | 862 | switch (type) { |
863 | case NL80211_IFTYPE_P2P_GO: | ||
864 | type = NL80211_IFTYPE_AP; | ||
865 | sdata->vif.type = type; | ||
866 | sdata->vif.p2p = true; | ||
867 | /* fall through */ | ||
859 | case NL80211_IFTYPE_AP: | 868 | case NL80211_IFTYPE_AP: |
860 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 869 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
861 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 870 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
862 | break; | 871 | break; |
872 | case NL80211_IFTYPE_P2P_CLIENT: | ||
873 | type = NL80211_IFTYPE_STATION; | ||
874 | sdata->vif.type = type; | ||
875 | sdata->vif.p2p = true; | ||
876 | /* fall through */ | ||
863 | case NL80211_IFTYPE_STATION: | 877 | case NL80211_IFTYPE_STATION: |
864 | ieee80211_sta_setup_sdata(sdata); | 878 | ieee80211_sta_setup_sdata(sdata); |
865 | break; | 879 | break; |
@@ -893,6 +907,8 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
893 | { | 907 | { |
894 | struct ieee80211_local *local = sdata->local; | 908 | struct ieee80211_local *local = sdata->local; |
895 | int ret, err; | 909 | int ret, err; |
910 | enum nl80211_iftype internal_type = type; | ||
911 | bool p2p = false; | ||
896 | 912 | ||
897 | ASSERT_RTNL(); | 913 | ASSERT_RTNL(); |
898 | 914 | ||
@@ -925,11 +941,19 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
925 | * code isn't prepared to handle). | 941 | * code isn't prepared to handle). |
926 | */ | 942 | */ |
927 | break; | 943 | break; |
944 | case NL80211_IFTYPE_P2P_CLIENT: | ||
945 | p2p = true; | ||
946 | internal_type = NL80211_IFTYPE_STATION; | ||
947 | break; | ||
948 | case NL80211_IFTYPE_P2P_GO: | ||
949 | p2p = true; | ||
950 | internal_type = NL80211_IFTYPE_AP; | ||
951 | break; | ||
928 | default: | 952 | default: |
929 | return -EBUSY; | 953 | return -EBUSY; |
930 | } | 954 | } |
931 | 955 | ||
932 | ret = ieee80211_check_concurrent_iface(sdata, type); | 956 | ret = ieee80211_check_concurrent_iface(sdata, internal_type); |
933 | if (ret) | 957 | if (ret) |
934 | return ret; | 958 | return ret; |
935 | 959 | ||
@@ -937,7 +961,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
937 | 961 | ||
938 | ieee80211_teardown_sdata(sdata->dev); | 962 | ieee80211_teardown_sdata(sdata->dev); |
939 | 963 | ||
940 | ret = drv_change_interface(local, sdata, type); | 964 | ret = drv_change_interface(local, sdata, internal_type, p2p); |
941 | if (ret) | 965 | if (ret) |
942 | type = sdata->vif.type; | 966 | type = sdata->vif.type; |
943 | 967 | ||
@@ -956,7 +980,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
956 | 980 | ||
957 | ASSERT_RTNL(); | 981 | ASSERT_RTNL(); |
958 | 982 | ||
959 | if (type == sdata->vif.type) | 983 | if (type == ieee80211_vif_type_p2p(&sdata->vif)) |
960 | return 0; | 984 | return 0; |
961 | 985 | ||
962 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ | 986 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 3570f8c2bb40..6a63d1abd14d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -49,7 +49,7 @@ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | |||
49 | 49 | ||
50 | static void assert_key_lock(struct ieee80211_local *local) | 50 | static void assert_key_lock(struct ieee80211_local *local) |
51 | { | 51 | { |
52 | WARN_ON(!mutex_is_locked(&local->key_mtx)); | 52 | lockdep_assert_held(&local->key_mtx); |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | 55 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b8cf2821f00d..fda97bb0018b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -305,6 +305,9 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
305 | 305 | ||
306 | trace_api_restart_hw(local); | 306 | trace_api_restart_hw(local); |
307 | 307 | ||
308 | /* wait for scan work complete */ | ||
309 | flush_workqueue(local->workqueue); | ||
310 | |||
308 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | 311 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), |
309 | "%s called with hardware scan in progress\n", __func__); | 312 | "%s called with hardware scan in progress\n", __func__); |
310 | 313 | ||
@@ -456,6 +459,21 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
456 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
457 | BIT(IEEE80211_STYPE_ACTION >> 4), | 460 | BIT(IEEE80211_STYPE_ACTION >> 4), |
458 | }, | 461 | }, |
462 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
463 | .tx = 0xffff, | ||
464 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
465 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
466 | }, | ||
467 | [NL80211_IFTYPE_P2P_GO] = { | ||
468 | .tx = 0xffff, | ||
469 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
470 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
471 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
472 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
473 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
474 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
475 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
476 | }, | ||
459 | }; | 477 | }; |
460 | 478 | ||
461 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 479 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0cb822cc12e9..8b733cf6f3ea 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -92,7 +92,7 @@ enum rx_mgmt_action { | |||
92 | /* utils */ | 92 | /* utils */ |
93 | static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | 93 | static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) |
94 | { | 94 | { |
95 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); | 95 | lockdep_assert_held(&ifmgd->mtx); |
96 | } | 96 | } |
97 | 97 | ||
98 | /* | 98 | /* |
@@ -115,7 +115,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, | |||
115 | mod_timer(&ifmgd->timer, timeout); | 115 | mod_timer(&ifmgd->timer, timeout); |
116 | } | 116 | } |
117 | 117 | ||
118 | static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | 118 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
119 | { | 119 | { |
120 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | 120 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) |
121 | return; | 121 | return; |
@@ -124,6 +124,19 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | |||
124 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | 124 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); |
125 | } | 125 | } |
126 | 126 | ||
127 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | ||
128 | { | ||
129 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
130 | |||
131 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
132 | return; | ||
133 | |||
134 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
135 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
136 | |||
137 | ifmgd->probe_send_count = 0; | ||
138 | } | ||
139 | |||
127 | static int ecw2cw(int ecw) | 140 | static int ecw2cw(int ecw) |
128 | { | 141 | { |
129 | return (1 << ecw) - 1; | 142 | return (1 << ecw) - 1; |
@@ -1018,21 +1031,26 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1018 | if (is_multicast_ether_addr(hdr->addr1)) | 1031 | if (is_multicast_ether_addr(hdr->addr1)) |
1019 | return; | 1032 | return; |
1020 | 1033 | ||
1021 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 1034 | ieee80211_sta_reset_conn_monitor(sdata); |
1022 | return; | ||
1023 | |||
1024 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
1025 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
1026 | } | 1035 | } |
1027 | 1036 | ||
1028 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1037 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
1029 | { | 1038 | { |
1030 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1039 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1031 | const u8 *ssid; | 1040 | const u8 *ssid; |
1041 | u8 *dst = ifmgd->associated->bssid; | ||
1042 | u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | ||
1043 | |||
1044 | /* | ||
1045 | * Try sending broadcast probe requests for the last three | ||
1046 | * probe requests after the first ones failed since some | ||
1047 | * buggy APs only support broadcast probe requests. | ||
1048 | */ | ||
1049 | if (ifmgd->probe_send_count >= unicast_limit) | ||
1050 | dst = NULL; | ||
1032 | 1051 | ||
1033 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1052 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1034 | ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, | 1053 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
1035 | ssid + 2, ssid[1], NULL, 0); | ||
1036 | 1054 | ||
1037 | ifmgd->probe_send_count++; | 1055 | ifmgd->probe_send_count++; |
1038 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1056 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; |
@@ -1381,7 +1399,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1381 | * Also start the timer that will detect beacon loss. | 1399 | * Also start the timer that will detect beacon loss. |
1382 | */ | 1400 | */ |
1383 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1401 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1384 | mod_beacon_timer(sdata); | 1402 | ieee80211_sta_reset_beacon_monitor(sdata); |
1385 | 1403 | ||
1386 | return true; | 1404 | return true; |
1387 | } | 1405 | } |
@@ -1484,7 +1502,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1484 | * we have or will be receiving any beacons or data, so let's | 1502 | * we have or will be receiving any beacons or data, so let's |
1485 | * schedule the timers again, just in case. | 1503 | * schedule the timers again, just in case. |
1486 | */ | 1504 | */ |
1487 | mod_beacon_timer(sdata); | 1505 | ieee80211_sta_reset_beacon_monitor(sdata); |
1488 | 1506 | ||
1489 | mod_timer(&ifmgd->conn_mon_timer, | 1507 | mod_timer(&ifmgd->conn_mon_timer, |
1490 | round_jiffies_up(jiffies + | 1508 | round_jiffies_up(jiffies + |
@@ -1610,7 +1628,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1610 | * Push the beacon loss detection into the future since | 1628 | * Push the beacon loss detection into the future since |
1611 | * we are processing a beacon from the AP just now. | 1629 | * we are processing a beacon from the AP just now. |
1612 | */ | 1630 | */ |
1613 | mod_beacon_timer(sdata); | 1631 | ieee80211_sta_reset_beacon_monitor(sdata); |
1614 | 1632 | ||
1615 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | 1633 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); |
1616 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, | 1634 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index eeacaa59380a..4b564091e51d 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -22,12 +22,16 @@ | |||
22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | 22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) |
23 | { | 23 | { |
24 | struct ieee80211_local *local = sdata->local; | 24 | struct ieee80211_local *local = sdata->local; |
25 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
25 | 26 | ||
26 | local->offchannel_ps_enabled = false; | 27 | local->offchannel_ps_enabled = false; |
27 | 28 | ||
28 | /* FIXME: what to do when local->pspolling is true? */ | 29 | /* FIXME: what to do when local->pspolling is true? */ |
29 | 30 | ||
30 | del_timer_sync(&local->dynamic_ps_timer); | 31 | del_timer_sync(&local->dynamic_ps_timer); |
32 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
33 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
34 | |||
31 | cancel_work_sync(&local->dynamic_ps_enable_work); | 35 | cancel_work_sync(&local->dynamic_ps_enable_work); |
32 | 36 | ||
33 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 37 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
@@ -85,6 +89,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
85 | mod_timer(&local->dynamic_ps_timer, jiffies + | 89 | mod_timer(&local->dynamic_ps_timer, jiffies + |
86 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 90 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
87 | } | 91 | } |
92 | |||
93 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
94 | ieee80211_sta_reset_conn_monitor(sdata); | ||
88 | } | 95 | } |
89 | 96 | ||
90 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | 97 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ac205a33690f..c0368152b721 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2588,9 +2588,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2588 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 2588 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
2589 | return 0; | 2589 | return 0; |
2590 | break; | 2590 | break; |
2591 | case NL80211_IFTYPE_MONITOR: | 2591 | default: |
2592 | case NL80211_IFTYPE_UNSPECIFIED: | ||
2593 | case NUM_NL80211_IFTYPES: | ||
2594 | /* should never get here */ | 2592 | /* should never get here */ |
2595 | WARN_ON(1); | 2593 | WARN_ON(1); |
2596 | break; | 2594 | break; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 687077e49dc6..44e10a9de0a7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -125,7 +125,7 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
125 | lockdep_is_held(&local->sta_mtx)); | 125 | lockdep_is_held(&local->sta_mtx)); |
126 | while (sta) { | 126 | while (sta) { |
127 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
128 | sta->sdata->bss == sdata->bss) && | 128 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
130 | break; | 130 | break; |
131 | sta = rcu_dereference_check(sta->hnext, | 131 | sta = rcu_dereference_check(sta->hnext, |
@@ -280,7 +280,7 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) | |||
280 | unsigned long flags; | 280 | unsigned long flags; |
281 | int err = 0; | 281 | int err = 0; |
282 | 282 | ||
283 | WARN_ON(!mutex_is_locked(&local->sta_mtx)); | 283 | lockdep_assert_held(&local->sta_mtx); |
284 | 284 | ||
285 | /* notify driver */ | 285 | /* notify driver */ |
286 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 286 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ccf373788ce9..e1733dcb58a7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1609,6 +1609,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1609 | return; | 1609 | return; |
1610 | } | 1610 | } |
1611 | 1611 | ||
1612 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1612 | info->control.vif = &sdata->vif; | 1613 | info->control.vif = &sdata->vif; |
1613 | 1614 | ||
1614 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 1615 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index bd40b11d5ab9..737f4267c335 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -474,16 +474,10 @@ void ieee80211_iterate_active_interfaces( | |||
474 | 474 | ||
475 | list_for_each_entry(sdata, &local->interfaces, list) { | 475 | list_for_each_entry(sdata, &local->interfaces, list) { |
476 | switch (sdata->vif.type) { | 476 | switch (sdata->vif.type) { |
477 | case NUM_NL80211_IFTYPES: | ||
478 | case NL80211_IFTYPE_UNSPECIFIED: | ||
479 | case NL80211_IFTYPE_MONITOR: | 477 | case NL80211_IFTYPE_MONITOR: |
480 | case NL80211_IFTYPE_AP_VLAN: | 478 | case NL80211_IFTYPE_AP_VLAN: |
481 | continue; | 479 | continue; |
482 | case NL80211_IFTYPE_AP: | 480 | default: |
483 | case NL80211_IFTYPE_STATION: | ||
484 | case NL80211_IFTYPE_ADHOC: | ||
485 | case NL80211_IFTYPE_WDS: | ||
486 | case NL80211_IFTYPE_MESH_POINT: | ||
487 | break; | 481 | break; |
488 | } | 482 | } |
489 | if (ieee80211_sdata_running(sdata)) | 483 | if (ieee80211_sdata_running(sdata)) |
@@ -508,16 +502,10 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
508 | 502 | ||
509 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 503 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
510 | switch (sdata->vif.type) { | 504 | switch (sdata->vif.type) { |
511 | case NUM_NL80211_IFTYPES: | ||
512 | case NL80211_IFTYPE_UNSPECIFIED: | ||
513 | case NL80211_IFTYPE_MONITOR: | 505 | case NL80211_IFTYPE_MONITOR: |
514 | case NL80211_IFTYPE_AP_VLAN: | 506 | case NL80211_IFTYPE_AP_VLAN: |
515 | continue; | 507 | continue; |
516 | case NL80211_IFTYPE_AP: | 508 | default: |
517 | case NL80211_IFTYPE_STATION: | ||
518 | case NL80211_IFTYPE_ADHOC: | ||
519 | case NL80211_IFTYPE_WDS: | ||
520 | case NL80211_IFTYPE_MESH_POINT: | ||
521 | break; | 509 | break; |
522 | } | 510 | } |
523 | if (ieee80211_sdata_running(sdata)) | 511 | if (ieee80211_sdata_running(sdata)) |
@@ -1193,6 +1181,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1193 | break; | 1181 | break; |
1194 | case NL80211_IFTYPE_UNSPECIFIED: | 1182 | case NL80211_IFTYPE_UNSPECIFIED: |
1195 | case NUM_NL80211_IFTYPES: | 1183 | case NUM_NL80211_IFTYPES: |
1184 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1185 | case NL80211_IFTYPE_P2P_GO: | ||
1196 | WARN_ON(1); | 1186 | WARN_ON(1); |
1197 | break; | 1187 | break; |
1198 | } | 1188 | } |
@@ -1296,9 +1286,9 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1296 | int count = 0; | 1286 | int count = 0; |
1297 | 1287 | ||
1298 | if (forsdata) | 1288 | if (forsdata) |
1299 | WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); | 1289 | lockdep_assert_held(&forsdata->u.mgd.mtx); |
1300 | 1290 | ||
1301 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | 1291 | lockdep_assert_held(&local->iflist_mtx); |
1302 | 1292 | ||
1303 | /* | 1293 | /* |
1304 | * This function could be improved to handle multiple | 1294 | * This function could be improved to handle multiple |
diff --git a/net/wireless/core.c b/net/wireless/core.c index d587ad284b3d..9c21ebf9780e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -729,6 +729,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
729 | dev->ethtool_ops = &cfg80211_ethtool_ops; | 729 | dev->ethtool_ops = &cfg80211_ethtool_ops; |
730 | 730 | ||
731 | if ((wdev->iftype == NL80211_IFTYPE_STATION || | 731 | if ((wdev->iftype == NL80211_IFTYPE_STATION || |
732 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || | ||
732 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) | 733 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) |
733 | dev->priv_flags |= IFF_DONT_BRIDGE; | 734 | dev->priv_flags |= IFF_DONT_BRIDGE; |
734 | break; | 735 | break; |
@@ -737,6 +738,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
737 | case NL80211_IFTYPE_ADHOC: | 738 | case NL80211_IFTYPE_ADHOC: |
738 | cfg80211_leave_ibss(rdev, dev, true); | 739 | cfg80211_leave_ibss(rdev, dev, true); |
739 | break; | 740 | break; |
741 | case NL80211_IFTYPE_P2P_CLIENT: | ||
740 | case NL80211_IFTYPE_STATION: | 742 | case NL80211_IFTYPE_STATION: |
741 | wdev_lock(wdev); | 743 | wdev_lock(wdev); |
742 | #ifdef CONFIG_CFG80211_WEXT | 744 | #ifdef CONFIG_CFG80211_WEXT |
@@ -915,52 +917,3 @@ static void __exit cfg80211_exit(void) | |||
915 | destroy_workqueue(cfg80211_wq); | 917 | destroy_workqueue(cfg80211_wq); |
916 | } | 918 | } |
917 | module_exit(cfg80211_exit); | 919 | module_exit(cfg80211_exit); |
918 | |||
919 | static int ___wiphy_printk(const char *level, const struct wiphy *wiphy, | ||
920 | struct va_format *vaf) | ||
921 | { | ||
922 | if (!wiphy) | ||
923 | return printk("%s(NULL wiphy *): %pV", level, vaf); | ||
924 | |||
925 | return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf); | ||
926 | } | ||
927 | |||
928 | int __wiphy_printk(const char *level, const struct wiphy *wiphy, | ||
929 | const char *fmt, ...) | ||
930 | { | ||
931 | struct va_format vaf; | ||
932 | va_list args; | ||
933 | int r; | ||
934 | |||
935 | va_start(args, fmt); | ||
936 | |||
937 | vaf.fmt = fmt; | ||
938 | vaf.va = &args; | ||
939 | |||
940 | r = ___wiphy_printk(level, wiphy, &vaf); | ||
941 | va_end(args); | ||
942 | |||
943 | return r; | ||
944 | } | ||
945 | EXPORT_SYMBOL(__wiphy_printk); | ||
946 | |||
947 | #define define_wiphy_printk_level(func, kern_level) \ | ||
948 | int func(const struct wiphy *wiphy, const char *fmt, ...) \ | ||
949 | { \ | ||
950 | struct va_format vaf; \ | ||
951 | va_list args; \ | ||
952 | int r; \ | ||
953 | \ | ||
954 | va_start(args, fmt); \ | ||
955 | \ | ||
956 | vaf.fmt = fmt; \ | ||
957 | vaf.va = &args; \ | ||
958 | \ | ||
959 | r = ___wiphy_printk(kern_level, wiphy, &vaf); \ | ||
960 | va_end(args); \ | ||
961 | \ | ||
962 | return r; \ | ||
963 | } \ | ||
964 | EXPORT_SYMBOL(func); | ||
965 | |||
966 | define_wiphy_printk_level(wiphy_debug, KERN_DEBUG); | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 58ab2c791d28..37580e090a3d 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -95,7 +95,10 @@ extern struct mutex cfg80211_mutex; | |||
95 | extern struct list_head cfg80211_rdev_list; | 95 | extern struct list_head cfg80211_rdev_list; |
96 | extern int cfg80211_rdev_list_generation; | 96 | extern int cfg80211_rdev_list_generation; |
97 | 97 | ||
98 | #define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) | 98 | static inline void assert_cfg80211_lock(void) |
99 | { | ||
100 | lockdep_assert_held(&cfg80211_mutex); | ||
101 | } | ||
99 | 102 | ||
100 | /* | 103 | /* |
101 | * You can use this to mark a wiphy_idx as not having an associated wiphy. | 104 | * You can use this to mark a wiphy_idx as not having an associated wiphy. |
@@ -202,8 +205,8 @@ static inline void wdev_unlock(struct wireless_dev *wdev) | |||
202 | mutex_unlock(&wdev->mtx); | 205 | mutex_unlock(&wdev->mtx); |
203 | } | 206 | } |
204 | 207 | ||
205 | #define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx)); | 208 | #define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) |
206 | #define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx)); | 209 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) |
207 | 210 | ||
208 | enum cfg80211_event_type { | 211 | enum cfg80211_event_type { |
209 | EVENT_CONNECT_RESULT, | 212 | EVENT_CONNECT_RESULT, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8515b1e5c578..46f371160896 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -882,7 +882,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
882 | if (!wdev->current_bss || | 882 | if (!wdev->current_bss || |
883 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, | 883 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, |
884 | ETH_ALEN) != 0 || | 884 | ETH_ALEN) != 0 || |
885 | (wdev->iftype == NL80211_IFTYPE_STATION && | 885 | ((wdev->iftype == NL80211_IFTYPE_STATION || |
886 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && | ||
886 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, | 887 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, |
887 | ETH_ALEN) != 0)) { | 888 | ETH_ALEN) != 0)) { |
888 | wdev_unlock(wdev); | 889 | wdev_unlock(wdev); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 85a23de7bff3..f15b1af2c768 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -410,12 +410,14 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
410 | switch (wdev->iftype) { | 410 | switch (wdev->iftype) { |
411 | case NL80211_IFTYPE_AP: | 411 | case NL80211_IFTYPE_AP: |
412 | case NL80211_IFTYPE_AP_VLAN: | 412 | case NL80211_IFTYPE_AP_VLAN: |
413 | case NL80211_IFTYPE_P2P_GO: | ||
413 | break; | 414 | break; |
414 | case NL80211_IFTYPE_ADHOC: | 415 | case NL80211_IFTYPE_ADHOC: |
415 | if (!wdev->current_bss) | 416 | if (!wdev->current_bss) |
416 | return -ENOLINK; | 417 | return -ENOLINK; |
417 | break; | 418 | break; |
418 | case NL80211_IFTYPE_STATION: | 419 | case NL80211_IFTYPE_STATION: |
420 | case NL80211_IFTYPE_P2P_CLIENT: | ||
419 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 421 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
420 | return -ENOLINK; | 422 | return -ENOLINK; |
421 | break; | 423 | break; |
@@ -766,7 +768,8 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | |||
766 | wdev->iftype == NL80211_IFTYPE_AP || | 768 | wdev->iftype == NL80211_IFTYPE_AP || |
767 | wdev->iftype == NL80211_IFTYPE_WDS || | 769 | wdev->iftype == NL80211_IFTYPE_WDS || |
768 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || | 770 | wdev->iftype == NL80211_IFTYPE_MESH_POINT || |
769 | wdev->iftype == NL80211_IFTYPE_MONITOR; | 771 | wdev->iftype == NL80211_IFTYPE_MONITOR || |
772 | wdev->iftype == NL80211_IFTYPE_P2P_GO; | ||
770 | } | 773 | } |
771 | 774 | ||
772 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | 775 | static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, |
@@ -833,7 +836,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
833 | struct cfg80211_registered_device *rdev; | 836 | struct cfg80211_registered_device *rdev; |
834 | struct net_device *netdev = NULL; | 837 | struct net_device *netdev = NULL; |
835 | struct wireless_dev *wdev; | 838 | struct wireless_dev *wdev; |
836 | int result, rem_txq_params = 0; | 839 | int result = 0, rem_txq_params = 0; |
837 | struct nlattr *nl_txq_params; | 840 | struct nlattr *nl_txq_params; |
838 | u32 changed; | 841 | u32 changed; |
839 | u8 retry_short = 0, retry_long = 0; | 842 | u8 retry_short = 0, retry_long = 0; |
@@ -1693,7 +1696,8 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1693 | if (err) | 1696 | if (err) |
1694 | goto unlock_rtnl; | 1697 | goto unlock_rtnl; |
1695 | 1698 | ||
1696 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 1699 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1700 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
1697 | err = -EOPNOTSUPP; | 1701 | err = -EOPNOTSUPP; |
1698 | goto out; | 1702 | goto out; |
1699 | } | 1703 | } |
@@ -1785,7 +1789,8 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1785 | goto out; | 1789 | goto out; |
1786 | } | 1790 | } |
1787 | 1791 | ||
1788 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 1792 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1793 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
1789 | err = -EOPNOTSUPP; | 1794 | err = -EOPNOTSUPP; |
1790 | goto out; | 1795 | goto out; |
1791 | } | 1796 | } |
@@ -2128,10 +2133,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2128 | switch (dev->ieee80211_ptr->iftype) { | 2133 | switch (dev->ieee80211_ptr->iftype) { |
2129 | case NL80211_IFTYPE_AP: | 2134 | case NL80211_IFTYPE_AP: |
2130 | case NL80211_IFTYPE_AP_VLAN: | 2135 | case NL80211_IFTYPE_AP_VLAN: |
2136 | case NL80211_IFTYPE_P2P_GO: | ||
2131 | /* disallow mesh-specific things */ | 2137 | /* disallow mesh-specific things */ |
2132 | if (params.plink_action) | 2138 | if (params.plink_action) |
2133 | err = -EINVAL; | 2139 | err = -EINVAL; |
2134 | break; | 2140 | break; |
2141 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2135 | case NL80211_IFTYPE_STATION: | 2142 | case NL80211_IFTYPE_STATION: |
2136 | /* disallow everything but AUTHORIZED flag */ | 2143 | /* disallow everything but AUTHORIZED flag */ |
2137 | if (params.plink_action) | 2144 | if (params.plink_action) |
@@ -2233,7 +2240,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2233 | goto out_rtnl; | 2240 | goto out_rtnl; |
2234 | 2241 | ||
2235 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2242 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2236 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 2243 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2244 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2237 | err = -EINVAL; | 2245 | err = -EINVAL; |
2238 | goto out; | 2246 | goto out; |
2239 | } | 2247 | } |
@@ -2286,7 +2294,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2286 | 2294 | ||
2287 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2295 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2288 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2296 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2289 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | 2297 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && |
2298 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2290 | err = -EINVAL; | 2299 | err = -EINVAL; |
2291 | goto out; | 2300 | goto out; |
2292 | } | 2301 | } |
@@ -2660,7 +2669,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
2660 | goto out; | 2669 | goto out; |
2661 | } | 2670 | } |
2662 | 2671 | ||
2663 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) { | 2672 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2673 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
2664 | err = -EOPNOTSUPP; | 2674 | err = -EOPNOTSUPP; |
2665 | goto out; | 2675 | goto out; |
2666 | } | 2676 | } |
@@ -3363,6 +3373,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3363 | } | 3373 | } |
3364 | 3374 | ||
3365 | switch (wdev->iftype) { | 3375 | switch (wdev->iftype) { |
3376 | case NL80211_IFTYPE_P2P_CLIENT: | ||
3366 | case NL80211_IFTYPE_STATION: | 3377 | case NL80211_IFTYPE_STATION: |
3367 | if (intbss == wdev->current_bss) | 3378 | if (intbss == wdev->current_bss) |
3368 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | 3379 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, |
@@ -3649,7 +3660,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3649 | goto out; | 3660 | goto out; |
3650 | } | 3661 | } |
3651 | 3662 | ||
3652 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3663 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3664 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3653 | err = -EOPNOTSUPP; | 3665 | err = -EOPNOTSUPP; |
3654 | goto out; | 3666 | goto out; |
3655 | } | 3667 | } |
@@ -3804,7 +3816,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
3804 | goto out; | 3816 | goto out; |
3805 | } | 3817 | } |
3806 | 3818 | ||
3807 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3819 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3820 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3808 | err = -EOPNOTSUPP; | 3821 | err = -EOPNOTSUPP; |
3809 | goto out; | 3822 | goto out; |
3810 | } | 3823 | } |
@@ -3888,7 +3901,8 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3888 | goto out; | 3901 | goto out; |
3889 | } | 3902 | } |
3890 | 3903 | ||
3891 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3904 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3905 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3892 | err = -EOPNOTSUPP; | 3906 | err = -EOPNOTSUPP; |
3893 | goto out; | 3907 | goto out; |
3894 | } | 3908 | } |
@@ -3954,7 +3968,8 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3954 | goto out; | 3968 | goto out; |
3955 | } | 3969 | } |
3956 | 3970 | ||
3957 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 3971 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
3972 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
3958 | err = -EOPNOTSUPP; | 3973 | err = -EOPNOTSUPP; |
3959 | goto out; | 3974 | goto out; |
3960 | } | 3975 | } |
@@ -4332,7 +4347,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
4332 | if (err) | 4347 | if (err) |
4333 | goto unlock_rtnl; | 4348 | goto unlock_rtnl; |
4334 | 4349 | ||
4335 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4350 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4351 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4336 | err = -EOPNOTSUPP; | 4352 | err = -EOPNOTSUPP; |
4337 | goto out; | 4353 | goto out; |
4338 | } | 4354 | } |
@@ -4408,7 +4424,8 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
4408 | if (err) | 4424 | if (err) |
4409 | goto unlock_rtnl; | 4425 | goto unlock_rtnl; |
4410 | 4426 | ||
4411 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4427 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4428 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4412 | err = -EOPNOTSUPP; | 4429 | err = -EOPNOTSUPP; |
4413 | goto out; | 4430 | goto out; |
4414 | } | 4431 | } |
@@ -4496,7 +4513,8 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4496 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); | 4513 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); |
4497 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4514 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
4498 | 4515 | ||
4499 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4516 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4517 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4500 | err = -EOPNOTSUPP; | 4518 | err = -EOPNOTSUPP; |
4501 | goto out; | 4519 | goto out; |
4502 | } | 4520 | } |
@@ -4541,7 +4559,8 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4541 | if (err) | 4559 | if (err) |
4542 | goto out_rtnl; | 4560 | goto out_rtnl; |
4543 | 4561 | ||
4544 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4562 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4563 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4545 | err = -EOPNOTSUPP; | 4564 | err = -EOPNOTSUPP; |
4546 | goto out; | 4565 | goto out; |
4547 | } | 4566 | } |
@@ -4823,7 +4842,8 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4823 | goto unlock_rtnl; | 4842 | goto unlock_rtnl; |
4824 | 4843 | ||
4825 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4844 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4826 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | 4845 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4846 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4827 | err = -EOPNOTSUPP; | 4847 | err = -EOPNOTSUPP; |
4828 | goto out; | 4848 | goto out; |
4829 | } | 4849 | } |
@@ -4875,7 +4895,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4875 | } | 4895 | } |
4876 | 4896 | ||
4877 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 4897 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4878 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | 4898 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && |
4899 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
4879 | err = -EOPNOTSUPP; | 4900 | err = -EOPNOTSUPP; |
4880 | goto out; | 4901 | goto out; |
4881 | } | 4902 | } |
@@ -5093,7 +5114,8 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, | |||
5093 | goto unlock_rdev; | 5114 | goto unlock_rdev; |
5094 | } | 5115 | } |
5095 | 5116 | ||
5096 | if (wdev->iftype != NL80211_IFTYPE_STATION) { | 5117 | if (wdev->iftype != NL80211_IFTYPE_STATION && |
5118 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) { | ||
5097 | err = -EOPNOTSUPP; | 5119 | err = -EOPNOTSUPP; |
5098 | goto unlock_rdev; | 5120 | goto unlock_rdev; |
5099 | } | 5121 | } |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 1332c445d1c7..c774bc0f155e 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * See COPYING for more details. | 14 | * See COPYING for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
17 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
18 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
19 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
@@ -45,7 +46,7 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { | |||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static const struct ieee80211_radiotap_namespace radiotap_ns = { | 48 | static const struct ieee80211_radiotap_namespace radiotap_ns = { |
48 | .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]), | 49 | .n_bits = ARRAY_SIZE(rtap_namespace_sizes), |
49 | .align_size = rtap_namespace_sizes, | 50 | .align_size = rtap_namespace_sizes, |
50 | }; | 51 | }; |
51 | 52 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b0d9a08447c9..d14bbf960c18 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -74,7 +74,11 @@ const struct ieee80211_regdomain *cfg80211_regdomain; | |||
74 | * - last_request | 74 | * - last_request |
75 | */ | 75 | */ |
76 | static DEFINE_MUTEX(reg_mutex); | 76 | static DEFINE_MUTEX(reg_mutex); |
77 | #define assert_reg_lock() WARN_ON(!mutex_is_locked(®_mutex)) | 77 | |
78 | static inline void assert_reg_lock(void) | ||
79 | { | ||
80 | lockdep_assert_held(®_mutex); | ||
81 | } | ||
78 | 82 | ||
79 | /* Used to queue up regulatory hints */ | 83 | /* Used to queue up regulatory hints */ |
80 | static LIST_HEAD(reg_requests_list); | 84 | static LIST_HEAD(reg_requests_list); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a8c2d6b877ae..f161b9844542 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -411,7 +411,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
411 | 411 | ||
412 | ASSERT_WDEV_LOCK(wdev); | 412 | ASSERT_WDEV_LOCK(wdev); |
413 | 413 | ||
414 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | 414 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
415 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | ||
415 | return; | 416 | return; |
416 | 417 | ||
417 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | 418 | if (wdev->sme_state != CFG80211_SME_CONNECTING) |
@@ -548,7 +549,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | |||
548 | 549 | ||
549 | ASSERT_WDEV_LOCK(wdev); | 550 | ASSERT_WDEV_LOCK(wdev); |
550 | 551 | ||
551 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | 552 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
553 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | ||
552 | return; | 554 | return; |
553 | 555 | ||
554 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 556 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
@@ -644,7 +646,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
644 | 646 | ||
645 | ASSERT_WDEV_LOCK(wdev); | 647 | ASSERT_WDEV_LOCK(wdev); |
646 | 648 | ||
647 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | 649 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
650 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | ||
648 | return; | 651 | return; |
649 | 652 | ||
650 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 653 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index bca32eb8f446..fb5448f7d55a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -326,7 +326,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
326 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 326 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
327 | case cpu_to_le16(IEEE80211_FCTL_TODS): | 327 | case cpu_to_le16(IEEE80211_FCTL_TODS): |
328 | if (unlikely(iftype != NL80211_IFTYPE_AP && | 328 | if (unlikely(iftype != NL80211_IFTYPE_AP && |
329 | iftype != NL80211_IFTYPE_AP_VLAN)) | 329 | iftype != NL80211_IFTYPE_AP_VLAN && |
330 | iftype != NL80211_IFTYPE_P2P_GO)) | ||
330 | return -1; | 331 | return -1; |
331 | break; | 332 | break; |
332 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 333 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
@@ -354,7 +355,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
354 | break; | 355 | break; |
355 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): | 356 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
356 | if ((iftype != NL80211_IFTYPE_STATION && | 357 | if ((iftype != NL80211_IFTYPE_STATION && |
357 | iftype != NL80211_IFTYPE_MESH_POINT) || | 358 | iftype != NL80211_IFTYPE_P2P_CLIENT && |
359 | iftype != NL80211_IFTYPE_MESH_POINT) || | ||
358 | (is_multicast_ether_addr(dst) && | 360 | (is_multicast_ether_addr(dst) && |
359 | !compare_ether_addr(src, addr))) | 361 | !compare_ether_addr(src, addr))) |
360 | return -1; | 362 | return -1; |
@@ -431,6 +433,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | |||
431 | switch (iftype) { | 433 | switch (iftype) { |
432 | case NL80211_IFTYPE_AP: | 434 | case NL80211_IFTYPE_AP: |
433 | case NL80211_IFTYPE_AP_VLAN: | 435 | case NL80211_IFTYPE_AP_VLAN: |
436 | case NL80211_IFTYPE_P2P_GO: | ||
434 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 437 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
435 | /* DA BSSID SA */ | 438 | /* DA BSSID SA */ |
436 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 439 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -439,6 +442,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | |||
439 | hdrlen = 24; | 442 | hdrlen = 24; |
440 | break; | 443 | break; |
441 | case NL80211_IFTYPE_STATION: | 444 | case NL80211_IFTYPE_STATION: |
445 | case NL80211_IFTYPE_P2P_CLIENT: | ||
442 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 446 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
443 | /* BSSID SA DA */ | 447 | /* BSSID SA DA */ |
444 | memcpy(hdr.addr1, bssid, ETH_ALEN); | 448 | memcpy(hdr.addr1, bssid, ETH_ALEN); |
@@ -778,7 +782,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
778 | 782 | ||
779 | /* if it's part of a bridge, reject changing type to station/ibss */ | 783 | /* if it's part of a bridge, reject changing type to station/ibss */ |
780 | if ((dev->priv_flags & IFF_BRIDGE_PORT) && | 784 | if ((dev->priv_flags & IFF_BRIDGE_PORT) && |
781 | (ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION)) | 785 | (ntype == NL80211_IFTYPE_ADHOC || |
786 | ntype == NL80211_IFTYPE_STATION || | ||
787 | ntype == NL80211_IFTYPE_P2P_CLIENT)) | ||
782 | return -EBUSY; | 788 | return -EBUSY; |
783 | 789 | ||
784 | if (ntype != otype) { | 790 | if (ntype != otype) { |
@@ -789,6 +795,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
789 | cfg80211_leave_ibss(rdev, dev, false); | 795 | cfg80211_leave_ibss(rdev, dev, false); |
790 | break; | 796 | break; |
791 | case NL80211_IFTYPE_STATION: | 797 | case NL80211_IFTYPE_STATION: |
798 | case NL80211_IFTYPE_P2P_CLIENT: | ||
792 | cfg80211_disconnect(rdev, dev, | 799 | cfg80211_disconnect(rdev, dev, |
793 | WLAN_REASON_DEAUTH_LEAVING, true); | 800 | WLAN_REASON_DEAUTH_LEAVING, true); |
794 | break; | 801 | break; |
@@ -817,9 +824,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
817 | if (dev->ieee80211_ptr->use_4addr) | 824 | if (dev->ieee80211_ptr->use_4addr) |
818 | break; | 825 | break; |
819 | /* fall through */ | 826 | /* fall through */ |
827 | case NL80211_IFTYPE_P2P_CLIENT: | ||
820 | case NL80211_IFTYPE_ADHOC: | 828 | case NL80211_IFTYPE_ADHOC: |
821 | dev->priv_flags |= IFF_DONT_BRIDGE; | 829 | dev->priv_flags |= IFF_DONT_BRIDGE; |
822 | break; | 830 | break; |
831 | case NL80211_IFTYPE_P2P_GO: | ||
823 | case NL80211_IFTYPE_AP: | 832 | case NL80211_IFTYPE_AP: |
824 | case NL80211_IFTYPE_AP_VLAN: | 833 | case NL80211_IFTYPE_AP_VLAN: |
825 | case NL80211_IFTYPE_WDS: | 834 | case NL80211_IFTYPE_WDS: |