diff options
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: |
